mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Matthew Swift
23.40.2016 fb7bab895bca6c06521b4371ff67523d4b1941ba
OPENDJ-3036 Fix inconsistent field naming in Rest2Ldap config files

* aligned key manager configuration field names with trust manager
* use camel-case throughout configuration (e.g. URL -> Url, DN -> Dn)
* simplify parsing of WritabilityPolicy.
5 files modified
126 ■■■■■ changed files
opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/config.json 31 ●●●● patch | view | raw | blame | history
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LdapHttpApplication.java 14 ●●●● patch | view | raw | blame | history
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LdapJsonConfigurator.java 50 ●●●●● patch | view | raw | blame | history
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/WritabilityPolicy.java 19 ●●●●● patch | view | raw | blame | history
opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/OAuth2JsonConfigurationTestCase.java 12 ●●●● patch | view | raw | blame | history
opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/config.json
@@ -23,18 +23,17 @@
        // the request against the access-token resolver endpoint. Acceptable values are:
        //
        // "jvm"      - use the JVM's default keystore for retrieving certificates. (default)
        // "keystore" - use the named key store file for retrieving certificates.
        // "file"     - use a file-based key store for retrieving certificates.
        // "pkcs11"   - use a PKCS#11 token for retrieving certificates.
        "keyManager": "jvm",
        // Keystore based key manager configuration (see above).
        "keyStoreFile": "/path/to/keystore",
        "keyStorePasswordFile": "/path/to/pinfile",
        "keyStoreFormat": "JKS",
        "keyStoreProvider": "",
        "fileBasedKeyManagerType": "JKS",
        "fileBasedKeyManagerFile": "/path/to/keystore",
        "fileBasedKeyManagerPasswordFile": "/path/to/pinfile",
        // PKCS11 based key manager configuration
        "pkcs11PasswordFile": "/path/to/pinfile"
        "pkcs11KeyManagerPasswordFile": "/path/to/pinfile"
    },
    // The array of connection factories which will be used by the Rest2LDAP
@@ -64,12 +63,12 @@
            "heartBeatTimeoutMilliSeconds": 500,
            // The preferred load-balancing pool.
            "primaryLDAPServers": [{
            "primaryLdapServers": [{
                "hostname": "localhost",
                "port": 1389
            }],
            // The fail-over load-balancing pool (optional).
            "secondaryLDAPServers": [
            "secondaryLdapServers": [
                // Empty.
            ]
        },
@@ -87,7 +86,7 @@
            // to allow the user configured here to perform proxied authorization.
            "authentication": {
                "simple": {
                    "bindDN": "cn=directory manager",
                    "bindDn": "cn=directory manager",
                    "bindPassword": "password"
                }
            }
@@ -127,7 +126,7 @@
                // The Bind DN Template containing a single {username} which will be replaced by the authenticating
                // user's name. (i.e: uid={username},ou=People,dc=example,dc=com)
                // If missing, "{username}" is used.
                "bindDNTemplate": "uid={username},ou=People,dc=example,dc=com"
                "bindDnTemplate": "uid={username},ou=People,dc=example,dc=com"
            },
            // Bind to the LDAP server using a SASL Plain request
@@ -145,15 +144,15 @@
            "search": {
                // Connection factory used to perform the search operation.
                // If missing, "root" factory will be used.
                "searchLDAPConnectionFactory": "root",
                "searchLdapConnectionFactory": "root",
                // Connection factory used to perform the bind operation.
                // If missing, "bind" factory will be used.
                "bindLDAPConnectionFactory": "bind",
                "bindLdapConnectionFactory": "bind",
                // The {username} filter format parameters will be substituted with the client-provided username,
                // using LDAP filter string character escaping.
                "baseDN": "ou=people,dc=example,dc=com",
                "baseDn": "ou=people,dc=example,dc=com",
                "scope": "sub", // Or "one".
                "filterTemplate": "(&(uid={username})(objectClass=inetOrgPerson))"
            }
@@ -199,7 +198,7 @@
            "openam": {
                // Defines the OpenAM endpoint URL where the request should be sent.
                // This attribute is required and must have a string syntax.
                "endpointURL": "http://openam.example.com:8080/openam/oauth2/tokeninfo",
                "endpointUrl": "http://openam.example.com:8080/openam/oauth2/tokeninfo",
                // This alias points at an existing certificate that is used for SSL authentication for secure
                // communication between this gateway and the OpenAM access-token resolver.
@@ -224,7 +223,7 @@
            "rfc7662": {
                // Defines the token introspection endpoint URL where the request should be sent.
                // This attribute is required and must have a string syntax.
                "endpointURL": "http://openam.example.com:8080/openam/oauth2/myrealm/introspect",
                "endpointUrl": "http://openam.example.com:8080/openam/oauth2/myrealm/introspect",
                // This alias points at an existing certificate that is used for SSL authentication for secure
                // communication between this gateway and the introspection access-token resolver.
@@ -263,7 +262,7 @@
                // The access token base DN.
                // This attribute is required and must have a string syntax.
                "baseDN": "ou=famrecords,ou=openam-session,ou=tokens,dc=example,dc=com",
                "baseDn": "ou=famrecords,ou=openam-session,ou=tokens,dc=example,dc=com",
                // The default authzIdTemplate demonstrates how an authorization DN may be constructed
                // from the "userName" field in the following example CTS access token entry:
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LdapHttpApplication.java
@@ -303,12 +303,12 @@
            final JsonValue openAm = configuration.get("openam");
            return new OpenAmAccessTokenResolver(newHttpClientHandler(openAm),
                                                 TimeService.SYSTEM,
                                                 openAm.get("endpointURL").required().asString());
                                                 openAm.get("endpointUrl").required().asString());
        case CTS:
            final JsonValue cts = configuration.get("cts").required();
            return newCtsAccessTokenResolver(
                getConnectionFactory(cts.get("ldapConnectionFactory").defaultTo(DEFAULT_ROOT_FACTORY).asString()),
                                     cts.get("baseDN").required().asString());
                                     cts.get("baseDn").required().asString());
        case FILE:
            return newFileAccessTokenResolver(configuration.get("file").get("folderPath").required().asString());
        default:
@@ -320,7 +320,7 @@
    private AccessTokenResolver parseRfc7662Resolver(final JsonValue configuration) throws HttpApplicationException {
        final JsonValue rfc7662 = configuration.get("rfc7662").required();
        final String introspectionEndPointURL = rfc7662.get("endpointURL").required().asString();
        final String introspectionEndPointURL = rfc7662.get("endpointUrl").required().asString();
        try {
            return newRfc7662AccessTokenResolver(newHttpClientHandler(rfc7662),
                                                 new URI(introspectionEndPointURL),
@@ -448,7 +448,7 @@
    private AuthenticationStrategy buildSimpleBindStrategy(final JsonValue config) {
        return newSimpleBindStrategy(getConnectionFactory(config.get("ldapConnectionFactory")
                                                                .defaultTo(DEFAULT_BIND_FACTORY).asString()),
                                     parseUserNameTemplate(config.get("bindDNTemplate").defaultTo("%s")),
                                     parseUserNameTemplate(config.get("bindDnTemplate").defaultTo("%s")),
                                     schema);
    }
@@ -461,10 +461,10 @@
    private AuthenticationStrategy buildSearchThenBindStrategy(JsonValue config) {
        return newSearchThenBindStrategy(
                getConnectionFactory(
                        config.get("searchLDAPConnectionFactory").defaultTo(DEFAULT_ROOT_FACTORY).asString()),
                        config.get("searchLdapConnectionFactory").defaultTo(DEFAULT_ROOT_FACTORY).asString()),
                getConnectionFactory(
                        config.get("bindLDAPConnectionFactory").defaultTo(DEFAULT_BIND_FACTORY).asString()),
                DN.valueOf(config.get("baseDN").required().asString(), schema),
                        config.get("bindLdapConnectionFactory").defaultTo(DEFAULT_BIND_FACTORY).asString()),
                DN.valueOf(config.get("baseDn").required().asString(), schema),
                SearchScope.valueOf(config.get("scope").required().asString().toLowerCase()),
                parseUserNameTemplate(config.get("filterTemplate").required()));
    }
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LdapJsonConfigurator.java
@@ -356,25 +356,7 @@
    }
    private static WritabilityPolicy parseWritability(final JsonValue mapper) {
        if (mapper.isDefined("writability")) {
            final String writability = mapper.get("writability").asString();
            if (writability.equalsIgnoreCase("readOnly")) {
                return WritabilityPolicy.READ_ONLY;
            } else if (writability.equalsIgnoreCase("readOnlyDiscardWrites")) {
                return WritabilityPolicy.READ_ONLY_DISCARD_WRITES;
            } else if (writability.equalsIgnoreCase("createOnly")) {
                return WritabilityPolicy.CREATE_ONLY;
            } else if (writability.equalsIgnoreCase("createOnlyDiscardWrites")) {
                return WritabilityPolicy.CREATE_ONLY_DISCARD_WRITES;
            } else if (writability.equalsIgnoreCase("readWrite")) {
                return WritabilityPolicy.READ_WRITE;
            } else {
                throw newJsonValueException(mapper, ERR_CONFIG_UNKNOWN_WRITABILITY.get(writability,
                            "readOnly, readOnlyDiscardWrites, createOnly, createOnlyDiscardWrites, readWrite"));
            }
        } else {
            return WritabilityPolicy.READ_WRITE;
        }
        return mapper.get("writability").defaultTo("readWrite").as(enumConstant(WritabilityPolicy.class));
    }
    /** Indicates whether LDAP client connections should use SSL or StartTLS. */
@@ -384,7 +366,7 @@
    private enum TrustManagerType { TRUSTALL, JVM, FILE }
    /** Specifies the type of key-store to use when performing SSL client authentication. */
    private enum KeyManagerType { JVM, KEYSTORE, PKCS11 }
    private enum KeyManagerType { JVM, FILE, PKCS11 }
    /**
     * Configures a {@link X509KeyManager} using the provided JSON configuration.
@@ -410,20 +392,18 @@
        switch (keyManagerType) {
        case JVM:
            return useJvmDefaultKeyStore();
        case KEYSTORE:
            final String fileName = config.get("keyStoreFile").required().asString();
            final String passwordFile = config.get("keyStorePasswordFile").asString();
        case FILE:
            final String fileName = config.get("fileBasedKeyManagerFile").required().asString();
            final String passwordFile = config.get("fileBasedKeyManagerPasswordFile").asString();
            final String password = passwordFile != null
                    ? readPasswordFromFile(passwordFile)
                    : config.get("keyStorePassword").asString();
            final String format = config.get("keyStoreFormat").asString();
            final String provider = config.get("keyStoreProvider").asString();
            return useKeyStoreFile(fileName, password != null ? password.toCharArray() : null, format, provider);
                    ? readPasswordFromFile(passwordFile) : config.get("fileBasedKeyManagerPassword").asString();
            final String type = config.get("fileBasedKeyManagerType").asString();
            final String provider = config.get("fileBasedKeyManagerProvider").asString();
            return useKeyStoreFile(fileName, password != null ? password.toCharArray() : null, type, provider);
        case PKCS11:
            final String pkcs11PasswordFile = config.get("pkcs11PasswordFile").asString();
            final String pkcs11PasswordFile = config.get("pkcs11KeyManagerPasswordFile").asString();
            return usePKCS11Token(pkcs11PasswordFile != null
                                          ? readPasswordFromFile(pkcs11PasswordFile).toCharArray()
                                          : null);
                                          ? readPasswordFromFile(pkcs11PasswordFile).toCharArray() : null);
        default:
            throw new IllegalArgumentException("Unsupported key-manager type: " + keyManagerType);
        }
@@ -555,7 +535,7 @@
            if (authn.isDefined("simple")) {
                final JsonValue simple = authn.get("simple");
                final BindRequest bindRequest =
                        Requests.newSimpleBindRequest(simple.get("bindDN").required().asString(),
                        Requests.newSimpleBindRequest(simple.get("bindDn").required().asString(),
                                                      simple.get("bindPassword").required().asString().toCharArray());
                options.set(AUTHN_BIND_REQUEST, bindRequest);
            } else {
@@ -585,14 +565,14 @@
        }
        // Parse primary data center.
        final JsonValue primaryLdapServers = configuration.get("primaryLDAPServers");
        final JsonValue primaryLdapServers = configuration.get("primaryLdapServers");
        if (!primaryLdapServers.isList() || primaryLdapServers.size() == 0) {
            throw new IllegalArgumentException("No primaryLDAPServers");
            throw new IllegalArgumentException("No primaryLdapServers");
        }
        final ConnectionFactory primary = parseLdapServers(primaryLdapServers, connectionPoolSize, options);
        // Parse secondary data center(s).
        final JsonValue secondaryLdapServers = configuration.get("secondaryLDAPServers");
        final JsonValue secondaryLdapServers = configuration.get("secondaryLdapServers");
        ConnectionFactory secondary = null;
        if (secondaryLdapServers.isList()) {
            if (secondaryLdapServers.size() > 0) {
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/WritabilityPolicy.java
@@ -25,39 +25,41 @@
     * modified afterwards. Attempts to update the attribute will result in an
     * error.
     */
    READ_ONLY(false),
    READ_ONLY("readOnly", false),
    /**
     * The attribute cannot be provided when creating a new resource, nor
     * modified afterwards. Attempts to update the attribute will not result in
     * an error (the new values will be ignored).
     */
    READ_ONLY_DISCARD_WRITES(true),
    READ_ONLY_DISCARD_WRITES("readOnlyDiscardWrites", true),
    /**
     * The attribute may be provided when creating a new resource, but cannot be
     * modified afterwards. Attempts to update the attribute will result in an
     * error.
     */
    CREATE_ONLY(false),
    CREATE_ONLY("createOnly", false),
    /**
     * The attribute may be provided when creating a new resource, but cannot be
     * modified afterwards. Attempts to update the attribute will not result in
     * an error (the new values will be ignored).
     */
    CREATE_ONLY_DISCARD_WRITES(true),
    CREATE_ONLY_DISCARD_WRITES("createOnlyDiscardWrites", true),
    /**
     * The attribute may be provided when creating a new resource, and modified
     * afterwards.
     */
    READ_WRITE(false);
    READ_WRITE("readWrite", false);
    // @formatter:on
    private final String name;
    private final boolean discardWrites;
    private WritabilityPolicy(final boolean discardWrites) {
    WritabilityPolicy(final String name, final boolean discardWrites) {
        this.name = name;
        this.discardWrites = discardWrites;
    }
@@ -72,4 +74,9 @@
    boolean discardWrites() {
        return discardWrites;
    }
    @Override
    public String toString() {
        return name;
    }
}
opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/OAuth2JsonConfigurationTestCase.java
@@ -86,7 +86,7 @@
                                + "'requiredScopes': ['read', 'write', 'dolphin'],"
                                + "'resolver': 'openam',"
                                + "'openam': {"
                                + "    'endpointURL': 'http://www.example.com/token-info',"
                                + "    'endpointUrl': 'http://www.example.com/token-info',"
                                + "    'authzIdTemplate': 'userName: ou={/user/id},dc=example,dc=com'"
                                + "},"
                                + "'accessTokenCache': {'enabled': true, 'cacheExpiration': '42'}}",
@@ -97,7 +97,7 @@
                                + "'requiredScopes': ['read', 'write', 'dolphin'],"
                                + "'resolver': 'openam',"
                                + "'openam': {"
                                + "    'endpointURL': 'http://www.example.com/token-info',"
                                + "    'endpointUrl': 'http://www.example.com/token-info',"
                                + "    'authzIdTemplate': 'dn: ou={/user/id},dc=example,dc=com'"
                                + "},"
                                + "'accessTokenCache': {'enabled': true, 'cacheExpiration': '42'}}",
@@ -119,7 +119,7 @@
                    + "'requiredScopes': [],"
                    + "'resolver': 'openam',"
                    + "'openam': {"
                    + "    'endpointURL': 'http://www.example.com/token-info',"
                    + "    'endpointUrl': 'http://www.example.com/token-info',"
                    + "    'authzIdTemplate': 'dn: ou={/user/id},dc=example,dc=com'"
                    + "}}";
        fakeApp.buildOAuth2Filter(parseJson(config));
@@ -216,7 +216,7 @@
        return new Object[][] {
                {
                        "{'resolver': 'rfc7662',"
                                + "'rfc7662': { 'endpointURL': 'http:/example.com/introspect',"
                                + "'rfc7662': { 'endpointUrl': 'http:/example.com/introspect',"
                                + "             'clientId': 'client_app_id',"
                                + "             'clientSecret': 'client_app_secret',"
                                + "             'authzIdTemplate': 'dn: ou={/user/id},dc=example,dc=com'}}"
@@ -224,12 +224,12 @@
                {
                        "{'resolver': 'openam',"
                                + "'openam': { "
                                + "    'endpointURL': 'http:/example.com/tokeninfo',"
                                + "    'endpointUrl': 'http:/example.com/tokeninfo',"
                                + "    'authzIdTemplate': 'dn: ou={/user/id},dc=example,dc=com'}}"
                },
                {
                        "{'resolver': 'cts',"
                                + "'cts': { 'baseDN': 'coreTokenId={token},dc=com',"
                                + "'cts': { 'baseDn': 'coreTokenId={token},dc=com',"
                                + "         'authzIdTemplate': 'dn: ou={/user/id},dc=example,dc=com'}}"
                },
                {