ldap-scim-bridge 0.3 → 0.4
raw patch · 4 files changed
+29/−8 lines, 4 filesdep +unordered-containersPVP ok
version bump matches the API change (PVP)
Dependencies added: unordered-containers
API changes (from Hackage documentation)
+ LdapScimBridge: [ldapSearchExtra] :: LdapSearch -> [LdapFilterAttr]
+ LdapScimBridge: instance GHC.Show.Show LdapScimBridge.BridgeConf
+ LdapScimBridge: ldapFilterAttrToFilter :: LdapFilterAttr -> Filter
- LdapScimBridge: LdapSearch :: Dn -> Text -> LdapSearch
+ LdapScimBridge: LdapSearch :: Dn -> Text -> [LdapFilterAttr] -> LdapSearch
Files
- CHANGELOG.md +4/−0
- examples/wire-server/conf1.yaml +2/−0
- ldap-scim-bridge.cabal +2/−1
- src/LdapScimBridge.hs +21/−7
CHANGELOG.md view
@@ -3,6 +3,10 @@ `ldap-scim-bridge` uses [PVP][1]-compatible versioning. The changelog is available [on GitHub][2]. +## 0.4++- Filter for arbitrary LDAP attributes (#16)+ ## 0.3 - Better error logging. (#11)
examples/wire-server/conf1.yaml view
@@ -8,6 +8,8 @@ search: base: "ou=People,dc=nodomain" objectClass: "account"+ #memberOf: "team red"+ #hairColor: "yellow" codec: "utf8" scimTarget: tls: false
ldap-scim-bridge.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: ldap-scim-bridge-version: 0.3+version: 0.4 synopsis: See README for synopsis description: See README for description homepage: https://github.com/fisx/ldap-scim-bridge@@ -39,6 +39,7 @@ , email-validate >=2.3.2.13 && <2.4 , string-conversions >=0.4.0.1 && <0.5 , servant-client >=0.18.3 && <0.19+ , unordered-containers >= 0.2.14.0 && <0.3 , servant-client-core >=0.18.3 && <0.19 , servant >=0.18.3 && <0.19 , http-types >=0.12.3 && <0.13
src/LdapScimBridge.hs view
@@ -8,6 +8,7 @@ import qualified Data.Aeson.Encode.Pretty as Aeson import qualified Data.ByteString.Char8 as ByteString import qualified Data.Foldable as Foldable+import qualified Data.HashMap.Lazy as HM import qualified Data.List import qualified Data.Map as Map import Data.String.Conversions (cs)@@ -63,7 +64,9 @@ { -- | `$ slapcat | grep ^dn`, eg. @Dn "dc=nodomain"@. ldapSearchBase :: Dn, -- | eg. @"account"@- ldapSearchObjectClass :: Text+ ldapSearchObjectClass :: Text,+ -- | eg. @[LdapFilterAttr "memberOf" "team red", LdapFilterAttr "hairColor" "yellow"]+ ldapSearchExtra :: [LdapFilterAttr] } deriving stock (Eq, Show) @@ -79,7 +82,7 @@ fpassword :: String <- obj Aeson..: "password" fsearch :: LdapSearch <- obj Aeson..: "search" fcodec :: Text <- obj Aeson..: "codec"- fdeleteOnAttribute :: Maybe LdapFilterAttr <- obj Aeson..:? "deleteOnAttribute"+ fdeleteOnAttribute :: Maybe LdapFilterAttr <- obj Aeson..:? "deleteOnAttribute" -- TODO: this can go into 'fdeleteFromDirectory'. fdeleteFromDirectory :: Maybe LdapSearch <- obj Aeson..:? "deleteFromDirectory" let vhost :: Host@@ -117,8 +120,15 @@ parseJSON = Aeson.withObject "LdapSearch" $ \obj -> do fbase :: Text <- obj Aeson..: "base" fobjectClass :: Text <- obj Aeson..: "objectClass"- pure $ LdapSearch (Dn fbase) fobjectClass + extra :: [LdapFilterAttr] <- do+ let go :: (Text, Yaml.Value) -> Yaml.Parser LdapFilterAttr+ go (key, val) = do+ str <- Aeson.withText "val" pure val+ pure $ LdapFilterAttr key str+ go `mapM` HM.toList (HM.filterWithKey (\k _ -> k `notElem` ["base", "objectClass"]) obj)+ pure $ LdapSearch (Dn fbase) fobjectClass extra+ data ScimConf = ScimConf { scimTls :: Bool, scimHost :: String,@@ -143,7 +153,7 @@ mapping :: Mapping, logLevel :: Level }- deriving stock (Generic)+ deriving stock (Show, Generic) instance Aeson.FromJSON Level where parseJSON "Trace" = pure Trace@@ -255,14 +265,18 @@ type LdapResult a = IO (Either LdapError a) -ldapObjectClassFilter :: Text -> Filter+ldapObjectClassFilter :: Text -> Filter -- TODO: inline? ldapObjectClassFilter = (Attr "objectClass" :=) . cs +ldapFilterAttrToFilter :: LdapFilterAttr -> Filter -- TODO: inline? replace LdapFilterAttr with `Attr` and `:=`?+ldapFilterAttrToFilter (LdapFilterAttr key val) = Attr key := (cs val)+ listLdapUsers :: LdapConf -> LdapSearch -> LdapResult [SearchEntry] listLdapUsers conf searchConf = Ldap.with (ldapHost conf) (ldapPort conf) $ \l -> do Ldap.bind l (ldapDn conf) (ldapPassword conf)- let fltr = ldapObjectClassFilter . ldapSearchObjectClass $ searchConf- Ldap.search l (ldapSearchBase searchConf) mempty fltr mempty+ let fltr :: Filter = ldapObjectClassFilter . ldapSearchObjectClass $ searchConf+ allfltr :: Filter = And (fltr :| (ldapFilterAttrToFilter <$> ldapSearchExtra searchConf))+ Ldap.search l (ldapSearchBase searchConf) mempty allfltr mempty type User = Scim.User ScimTag