Verwaltung von LDAP Accounts und Gruppen
Peter Hormanns
2022-06-02 90c690b5dd6e35540254181852e77b4060357561
add csv import
4 files added
3 files modified
286 ■■■■■ changed files
etc/sample.csv 1 ●●●● patch | view | raw | blame | history
pom.xml 8 ●●●● patch | view | raw | blame | history
src/main/java/de/jalin/ldapadmin/ldap/LDAPSession.java 6 ●●●●● patch | view | raw | blame | history
src/main/java/de/jalin/ldapadmin/ldap/RequiredAttributeException.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/de/jalin/ldapadmin/tools/ImportUsersFromCSV.java 76 ●●●●● patch | view | raw | blame | history
src/main/java/de/jalin/ldapadmin/tools/PasswordGenerator.java 147 ●●●●● patch | view | raw | blame | history
src/main/java/de/jalin/ldapadmin/tools/PasswordTool.java 46 ●●●●● patch | view | raw | blame | history
etc/sample.csv
New file
@@ -0,0 +1 @@
"Max Muster","max.muster@example.com","Max","Muster"
pom.xml
@@ -1,4 +1,5 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    
    <modelVersion>4.0.0</modelVersion>
@@ -58,6 +59,11 @@
            <version>3.8.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-csv</artifactId>
            <version>1.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>3.4.1</version>
src/main/java/de/jalin/ldapadmin/ldap/LDAPSession.java
@@ -21,6 +21,7 @@
public class LDAPSession {
    private InitialDirContext ctx;
    private String connectString;
    public LDAPSession(final String providerURL, final String principal, final String password) throws LDAPSessionException {
        final Properties env = new Properties();
@@ -30,6 +31,7 @@
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, principal);
        env.put(Context.SECURITY_CREDENTIALS, password);
        connectString = providerURL;
        try {
            ctx = new InitialDirContext(env);
        } catch (NamingException e) {
@@ -153,6 +155,10 @@
        }
    }
    public String getSessionInfo() {
        return connectString;
    }
    private void createOrgUnitNodesIfNotExist() throws LDAPSessionException {
        try {
            final BasicAttributes usersAttributes = new BasicAttributes();
src/main/java/de/jalin/ldapadmin/ldap/RequiredAttributeException.java
@@ -7,10 +7,12 @@
    private final String fieldname;
    public RequiredAttributeException(final String fieldname) {
        super("required attribute '" + fieldname + "' missing");
        this.fieldname = fieldname;
    }
    public String getFieldname() {
        return fieldname;
    }
}
src/main/java/de/jalin/ldapadmin/tools/ImportUsersFromCSV.java
New file
@@ -0,0 +1,76 @@
package de.jalin.ldapadmin.tools;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.SortedMap;
import javax.naming.NamingException;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import de.jalin.ldapadmin.beans.User;
import de.jalin.ldapadmin.ldap.AlreadyBoundException;
import de.jalin.ldapadmin.ldap.LDAPConfig;
import de.jalin.ldapadmin.ldap.LDAPSession;
import de.jalin.ldapadmin.ldap.LDAPSessionException;
import de.jalin.ldapadmin.ldap.RequiredAttributeException;
import de.jalin.ldapadmin.ldap.UsersDAO;
public class ImportUsersFromCSV {
    public static void main(String[] args) {
        LDAPSession ldapSession = null;
        if (args.length != 2) {
            System.out.println("usage:");
            System.out.println("ImportUsersFromCSV command csvfile");
            System.out.println("valid commands: verfiy, import");
            return;
        }
        try {
            ldapSession = connectLDAP();
            System.out.println("connected " + ldapSession.getSessionInfo());
            final UsersDAO usersDAO = new UsersDAO(ldapSession);
            final SortedMap<String,User> users = usersDAO.loadUsers();
            System.out.println("existing users: " + users.size());
            final File csvFile = new File(args[1]);
            final InputStreamReader csvStreamReader = new InputStreamReader(new FileInputStream(csvFile));
            final CSVParser csvParser = CSVFormat.DEFAULT.parse(csvStreamReader);
            for (CSVRecord record : csvParser) {
                final String userid = record.get(0);
                final String email = record.get(1);
                final String firstname = record.get(2);
                final String lastname = record.get(3);
                System.out.println(userid + "/" + email);
                final User user = new User(userid);
                user.setEmail(email);
                user.setFirstname(firstname);
                user.setLastname(lastname);
                user.setPassword(PasswordTool.generatePassword());
                try {
                    usersDAO.create(user);
                } catch (RequiredAttributeException | AlreadyBoundException e) {
                    System.err.println("user failed: " + userid + " => " + e.getLocalizedMessage());
                }
            }
        } catch (LDAPSessionException | IOException e) {
            System.err.println(e.getLocalizedMessage());
        } finally {
            if (ldapSession != null) {
                try { ldapSession.close(); } catch (NamingException e) { }
            }
        }
    }
    private static LDAPSession connectLDAP() throws LDAPSessionException {
        final LDAPConfig config = LDAPConfig.getConfig();
        final String providerUrl = config.getLdapProviderUrl();
        final String securityPrincipal = config.getLdapSecurityPrincipal();
        final String securityPassword = config.getLdapSecurityPassword();
        return  new LDAPSession(providerUrl, securityPrincipal, securityPassword);
    }
}
src/main/java/de/jalin/ldapadmin/tools/PasswordGenerator.java
New file
@@ -0,0 +1,147 @@
package de.jalin.ldapadmin.tools;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public final class PasswordGenerator {
    private static final String LOWER = "abcdefghijklmnopqrstuvwxyz";
    private static final String UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final String DIGITS = "0123456789";
    private static final String PUNCTUATION = "!@#$%&*()_+-=[]|,./?><";
    private boolean useLower;
    private boolean useUpper;
    private boolean useDigits;
    private boolean usePunctuation;
    private PasswordGenerator() {
        throw new UnsupportedOperationException("Empty constructor is not supported.");
    }
    private PasswordGenerator(PasswordGeneratorBuilder builder) {
        this.useLower = builder.useLower;
        this.useUpper = builder.useUpper;
        this.useDigits = builder.useDigits;
        this.usePunctuation = builder.usePunctuation;
    }
    public static class PasswordGeneratorBuilder {
        private boolean useLower;
        private boolean useUpper;
        private boolean useDigits;
        private boolean usePunctuation;
        public PasswordGeneratorBuilder() {
            this.useLower = false;
            this.useUpper = false;
            this.useDigits = false;
            this.usePunctuation = false;
        }
        /**
         * Set true in case you would like to include lower characters (abc...xyz).
         * Default false.
         *
         * @param useLower true in case you would like to include lower characters
         *                 (abc...xyz). Default false.
         * @return the builder for chaining.
         */
        public PasswordGeneratorBuilder useLower(boolean useLower) {
            this.useLower = useLower;
            return this;
        }
        /**
         * Set true in case you would like to include upper characters (ABC...XYZ).
         * Default false.
         *
         * @param useUpper true in case you would like to include upper characters
         *                 (ABC...XYZ). Default false.
         * @return the builder for chaining.
         */
        public PasswordGeneratorBuilder useUpper(boolean useUpper) {
            this.useUpper = useUpper;
            return this;
        }
        /**
         * Set true in case you would like to include digit characters (123..). Default
         * false.
         *
         * @param useDigits true in case you would like to include digit characters
         *                  (123..). Default false.
         * @return the builder for chaining.
         */
        public PasswordGeneratorBuilder useDigits(boolean useDigits) {
            this.useDigits = useDigits;
            return this;
        }
        /**
         * Set true in case you would like to include punctuation characters (!@#..).
         * Default false.
         *
         * @param usePunctuation true in case you would like to include punctuation
         *                       characters (!@#..). Default false.
         * @return the builder for chaining.
         */
        public PasswordGeneratorBuilder usePunctuation(boolean usePunctuation) {
            this.usePunctuation = usePunctuation;
            return this;
        }
        /**
         * Get an object to use.
         *
         * @return the {@link gr.idrymavmela.business.lib.PasswordGenerator} object.
         */
        public PasswordGenerator build() {
            return new PasswordGenerator(this);
        }
    }
    /**
     * This method will generate a password depending the use* properties you
     * define. It will use the categories with a probability. It is not sure that
     * all of the defined categories will be used.
     *
     * @param length the length of the password you would like to generate.
     * @return a password that uses the categories you define when constructing the
     *         object with a probability.
     */
    public String generate(int length) {
        // Argument Validation.
        if (length <= 0) {
            return "";
        }
        // Variables.
        StringBuilder password = new StringBuilder(length);
        Random random = new Random(System.nanoTime());
        // Collect the categories to use.
        List<String> charCategories = new ArrayList<>(4);
        if (useLower) {
            charCategories.add(LOWER);
        }
        if (useUpper) {
            charCategories.add(UPPER);
        }
        if (useDigits) {
            charCategories.add(DIGITS);
        }
        if (usePunctuation) {
            charCategories.add(PUNCTUATION);
        }
        // Build the password.
        for (int i = 0; i < length; i++) {
            String charCategory = charCategories.get(random.nextInt(charCategories.size()));
            int position = random.nextInt(charCategory.length());
            password.append(charCategory.charAt(position));
        }
        return new String(password);
    }
}
src/main/java/de/jalin/ldapadmin/tools/PasswordTool.java
New file
@@ -0,0 +1,46 @@
package de.jalin.ldapadmin.tools;
import de.jalin.ldapadmin.ldap.SimplePasswordException;
public final class PasswordTool {
    public static final int MIN_COMPLEXITY = 3;
    public static final int MIN_PASSWORD_LENGTH = 6;
    private static final PasswordGenerator passwordGenerator = new PasswordGenerator.PasswordGeneratorBuilder()
            .useDigits(true)
            .useLower(true)
            .useUpper(true)
            .build();
    public static String generatePassword() {
        return passwordGenerator.generate(14);
    }
    public static void checkPasswordComplexity(final String password) throws SimplePasswordException {
        int containsLowercaseCharacter = 0;
        int containsUppercaseCharacter = 0;
        int containsSpecialCharacter = 0;
        int containsDigit = 0;
        for (int idx = 0;  idx < password.length(); idx++) {
            char chr = password.charAt(idx);
            if (chr >= 'a' && chr <= 'z') {
                containsLowercaseCharacter = 1;
            } else
            if (chr >= 'A' && chr <= 'Z') {
                containsUppercaseCharacter = 1;
            } else
            if (chr >= '0' && chr <= '1') {
                containsDigit = 1;
            } else {
                containsSpecialCharacter = 1;
            }
        }
        int complexity = containsLowercaseCharacter + containsUppercaseCharacter
                + containsSpecialCharacter + containsDigit;
        if (complexity < MIN_COMPLEXITY || password.length() < MIN_PASSWORD_LENGTH) {
            throw new SimplePasswordException("simple password");
        }
    }
}