ldapply 0.1.0 → 0.2.0
raw patch · 4 files changed
+54/−6 lines, 4 filesdep ~LDAP
Dependency ranges changed: LDAP
Files
- ChangeLog.md +8/−0
- README.md +12/−0
- ldapply.cabal +6/−2
- src/Main.hs +28/−4
ChangeLog.md view
@@ -1,3 +1,11 @@+0.2.0+=====++ * Require [LDAP](https://hackage.haskell.org/package/LDAP) > 0.6.0 for `ldapExternalSaslBind`.+ * Support simple bind. Added options `-x`, `-D`, `-w`, `-y` similar to `ldapmodify`.+ * `changetype: delete` works if entry to be deleted does not exist.++ 0.1.0 =====
README.md view
@@ -33,9 +33,16 @@ Options: -H <ldapuri> LDAP URL to connect to [default: ldapi:///] + -x Use simple bind instead of default SASL External+ -D <binddn> Use <binddn> for the distinguished name or authorization identity+ -w <passwd> Use <passwd> as the password for simple bind+ -y <passwdfile> Read password from <passwdfile>, only the first line is read+ -h, --help Show this message + If option -w is given, -y is ignored. + LDIF example ============ @@ -73,5 +80,10 @@ changetype: modify replace: description description: foo++# This will be deleted if exists:+dn: cn=reader,dc=nodomain+changetype: delete+ ```
ldapply.cabal view
@@ -1,5 +1,5 @@ name: ldapply-version: 0.1.0+version: 0.2.0 synopsis: LDIF idempotent apply tool license: MIT license-file: LICENSE@@ -11,6 +11,10 @@ cabal-version: >=1.20 extra-source-files: README.md ChangeLog.md +source-repository head+ type: git+ location: https://github.com/ip1981/ldapply.git+ executable ldapply hs-source-dirs: src main-is: Main.hs@@ -22,7 +26,7 @@ , bytestring , docopt , interpolatedstring-perl6- , LDAP >= 0.7.0+ , LDAP > 0.6.10 , ldif , unordered-containers
src/Main.hs view
@@ -6,15 +6,16 @@ import Data.ByteString.Char8 (unpack) import Data.Char (toLower) import Data.HashMap.Strict (fromListWith, toList)-import Data.Maybe (fromJust)+import Data.Maybe (fromJust, fromMaybe) import Data.Version (showVersion)-import LDAP.Init (ldapSimpleExternalSaslBind, ldapInitialize)+import LDAP.Init (ldapSimpleBind, ldapExternalSaslBind, ldapInitialize) import LDAP.Modify (LDAPMod(..), LDAPModOp(..), ldapAdd, ldapDelete, ldapModify, list2ldm) import LDAP.Search (LDAPScope(LdapScopeBase), SearchAttributes(LDAPAllUserAttrs), LDAPEntry(..), ldapSearch) import LDAP.Types (LDAP) import Paths_ldapply (version) -- from cabal import System.Environment (getArgs) import System.Exit (die)+import System.IO (IOMode(ReadMode), hGetLine, hIsEOF, withFile) import Text.InterpolatedString.Perl6 (qc) import Text.LDIF.Parser (defaulLDIFConf, parseLDIFFile) import Text.LDIF.Printer (dn2str)@@ -24,7 +25,6 @@ {-- TODO: 1. Streaming from stdin (good for large amount of LDIF data)- 2. Simple bind with DN and password --} usage :: String@@ -38,7 +38,14 @@ Options: -H <ldapuri> LDAP URL to connect to [default: ldapi:///] + -x Use simple bind instead of default SASL External+ -D <binddn> Use <binddn> for the distinguished name or authorization identity+ -w <passwd> Use <passwd> as the password for simple bind+ -y <passwdfile> Read password from <passwdfile>, only the first line is read+ -h, --help Show this message++If option -w is given, -y is ignored. |] @@ -52,11 +59,26 @@ let ldifs = O.getAllArgs args $ O.argument "LDIF" ldapUrl = fromJust $ O.getArg args $ O.shortOption 'H'+ simple = O.isPresent args $ O.shortOption 'x'+ binddn = fromMaybe "" $ O.getArg args $ O.shortOption 'D'+ passwd = O.getArg args $ O.shortOption 'w'+ passwdfile = O.getArg args $ O.shortOption 'y' ldap <- ldapInitialize ldapUrl- ldapSimpleExternalSaslBind ldap+ if simple then simpleBind ldap binddn passwd passwdfile+ else ldapExternalSaslBind ldap binddn mapM_ (processLDIF ldap) ldifs +simpleBind :: LDAP -> String -> Maybe String -> Maybe FilePath -> IO ()+simpleBind ldap bdn (Just pwd) _ = ldapSimpleBind ldap bdn pwd+simpleBind ldap bdn Nothing Nothing = ldapSimpleBind ldap bdn ""+simpleBind ldap bdn Nothing (Just f) = do+ pwd <- withFile f ReadMode $ \h -> do+ empty <- hIsEOF h+ if empty then return "" else hGetLine h+ ldapSimpleBind ldap bdn pwd++ processLDIF :: LDAP -> FilePath -> IO () processLDIF ldap f = do p <- parseLDIFFile defaulLDIFConf f@@ -81,6 +103,8 @@ update :: LDAP -> Maybe LDAPEntry -> LDIFRecord -> IO ()+update _ Nothing (ChangeRecord _ ChangeDelete) = return ()+ update _ Nothing rec@(ChangeRecord _ _) = die $ "cannot update non-existing entry " ++ show (dn rec)