[[SSL_with_Client_Cert_Migration]] = SSL with Client Cert Migration As this documentation is primarily intended for users migrating to WildFly Elytron I am going to jump straight into the configuration required with WildFly Elytron. This section will cover how to create the various resources required to achieve CLIENT_CERT authentication with fallback to username / password authentication for both HTTP and SASL (i.e. Remoting) - both are being covered at the same time as predominantly they require the same core configuration, it is not until the definition of the authentication factories that the configuration becomes really specific. The WildFly Elytron project already contains a dummy certificate authority set up that we use for testing, the KeyStores within this documentation are from the dummy certificate authority although for anything other than testing these should be replaced with your own. As a first step we define some paths that point to the wildfly-elytron project so we can use these in the subsequent configuration. [source, ruby] ---- ./subsystem=security/security-domain=application-security:add ./subsystem=security/security-domain=application-security/authentication=classic:add(login-modules=[{code=UsersRoles, flag=Required, module-options={usersProperties=file://${jboss.server.config.dir}/example-users.properties, rolesProperties=file://${jboss.server.config.dir}/example-roles.properties}}]) ---- This results in the following configuration. [source, xml] ---- ---- == KeyStores, KeyManagers, and TrustManagers. The next step is to define the KeyStore resources, for this example three different keystores are used: - localhost.keystore:: Contains the servers key and certificate for 'localhost'. beetles.keystore:: Contains the individual client certificates. ca.keystore:: Contains the certificate of the certificate authority. When we define the overall configuration we will use the localhost keystore along with the ca keystore for the incoming connections so initially all client certificates signed by the certificate authority will be accepted and subsequently a security realm will check it against the actual certificates within beetles keystore. [source, ruby] ---- ./subsystem=elytron/key-store=localhost:add(type=jks, relative-to=elytron.project.jks, path=localhost.keystore, credential-reference={clear-text=Elytron}) ./subsystem=elytron/key-store=beetles:add(type=jks, relative-to=elytron.project.jks, path=beetles.keystore, credential-reference={clear-text=Elytron}) ./subsystem=elytron/key-store=ca:add(type=jks, relative-to=elytron.project.jks, path=ca.truststore, credential-reference={clear-text=Elytron}) ---- This results in the following configuration. [source, xml] ---- ... ---- Next the key and trust manager resources will be defined using these keystores. [source, ruby] ---- ./subsystem=elytron/key-manager=localhost-manager:add(algorithm=SunX509, key-store=localhost, credential-reference={clear-text=Elytron}) ./subsystem=elytron/trust-manager=ca-manager:add(algorithm=SunX509, key-store=ca) ---- Resulting in: [source, xml] ---- ... ... ---- == Realms and Domains Two security realms are now defined, one of these uses properties files from within the WildFly Elytron project to support username/password authentication and the other using the clients certificates for verification. [source, ruby] ---- ./subsystem=elytron/properties-realm=test-users:add(users-properties={relative-to=elytron.project.properties, path=clear.properties, plain-text=true, digest-realm-name=ManagementRealm}, groups-properties={relative-to=elytron.project.properties, path=groups.properties}) ./subsystem=elytron/key-store-realm=key-store-realm:add(key-store=beetles) ---- Resulting in: [source, xml] ---- ... ... ... ... ---- These security realms can now be referenced from a security domain: [source, ruby] ---- ./subsystem=elytron/security-domain=client-cert-domain:add(realms=[{realm=test-users},{realm=key-store-realm}], \ default-realm=test-users, \ permission-mapper=default-permission-mapper) ---- Resulting in: [source, xml] ---- ... ... ... ---- Before moving onto the individual authentication factories a couple of additional utility resources are also required: - ---- ./subsystem=elytron/constant-realm-mapper=key-store-realm:add(realm-name=key-store-realm) ./subsystem=elytron/x500-attribute-principal-decoder=x500-decoder:add(attribute-name=CN, maximum-segments=1) ---- Resulting in: - [source, xml] ---- ... ... ... ... ... ---- == HTTP Authentication Factory For the HTTP connections we now define a HTTP authentication factory using the previously defined resources and it is configured to support CLIENT_CERT and DIGEST authentication. ---- ./subsystem=elytron/http-authentication-factory=client-cert-digest:add(http-server-mechanism-factory=global, \ security-domain=client-cert-domain, \ mechanism-configurations=[{ \ mechanism-name=CLIENT_CERT, \ realm-mapper=key-store-realm, \ pre-realm-principal-transformer=x500-decoder}, \ {mechanism-name=DIGEST, mechanism-realm-configurations=[{realm-name=ManagementRealm}]}]) ---- Resulting in: - ---- ... ... ... ... ---- Where DIGEST authentication is used we rely on the default configuration within the security domain to select the 'test-users' realm, however where CLIENT_CERT authentication is in use an alternative realm-mapper is referenced to ensure the 'key-store-realm' is used. Additionally for CLIENT_CERT authentication a principal-transformer is referenced to extract the CN attribute from the distinguished name of the client certificate and use this when accessing the identity from the security realm. == SASL Authentication Factory The architecture of the two authentication factories if very similar so a SASL authentication factory can be defined in the same way as the HTTP equivalent. ---- ./subsystem=elytron/sasl-authentication-factory=client-cert-digest:add(sasl-server-factory=elytron, \ security-domain=client-cert-domain, \ mechanism-configurations=[{mechanism-name=EXTERNAL, \ realm-mapper=key-store-realm, \ pre-realm-principal-transformer=x500-decoder}, \ {mechanism-name=DIGEST-MD5, mechanism-realm-configurations=[{realm-name=ManagementRealm}]}]) ---- This results in: - [source, xml] ---- ... ... ... ... ---- Realm mappers and principal transformers are defined in the same way as were defined for HTTP. == SSL Context An SSL context is also defined for use by the server. ---- ./subsystem=elytron/server-ssl-context=localhost:add(key-manager=localhost-manager, trust-manager=ca-manager, \ security-domain=client-cert-domain, \ authentication-optional=true, \ want-client-auth=true, \ need-client-auth=false) ---- Resulting in: - [source, xml] ---- ... ... ---- As we will be supporting fallback to username/password authentication need-client-auth is set to false as well as authentication-optional being set to false, this allows connections to be established but an alternative form of authentication will be required. == Using for Management At this point the management interfaces can be updated to use the newly defined resources, we need to add references to the two new authentication factories and the SSL context, we can also remove the existing reference to the legacy security realm. As this is modifying existing interfaces a server reload will also be required. ---- ./core-service=management/management-interface=http-interface:write-attribute(name=ssl-context, value=localhost) ./core-service=management/management-interface=http-interface:write-attribute(name=secure-socket-binding, value=management-https) ./core-service=management/management-interface=http-interface:write-attribute(name=http-authentication-factory, value=client-cert-digest) ./core-service=management/management-interface=http-interface:write-attribute(name=http-upgrade.sasl-authentication-factory, value=client-cert-digest) ./core-service=management/management-interface=http-interface:undefine-attribute(name=security-realm) :reload ---- The management interface configuration then becomes: - [source, xml] ---- ... ... ---- === Admin Clients At this stage assuming the same files have been used as in this example it should be possible to connect to the management interface of the server either using a web browser or the JBoss CLI with the username elytron and password passwd12#$ For certificate based authentication the keys and certificates from the WildFly Elytron tests can be used, these are found in JKS keystores under 'src/test/resources/ca/jks', these keystores have a password of Elytron. ==== Web Browser Configuration A PKCS#12 file can be created from the test keystores,this can then be imported into the web browser to use when connecting to the server. ---- keytool -importkeystore -srckeystore ladybird.keystore \ -destkeystore ladybird.pkcs12 \ -srcstoretype jks \ -deststoretype pkcs12 \ -deststorepass Elytron \ -srcalias ladybird \ -destalias ladybird ---- ==== CLI Configuration Since the integration of WildFly Elytron it is possible with the CLI to use a configuration file wildfly-config.xml to define the security settings including the settings for the client side SSL context. For the purpose of this example copy the ladybird,keystore and ca.truststore from the Wildfly Elytron testsuite to the location the JBoss CLI is being started from, the following wildfly-config.xml can be created in this location as well: - [source, xml] ---- ---- The CLI can now be started using the following command: - ---- ./jboss-cli.sh -c -Dwildfly.config.url=wildfly-config.xml ---- The :whoami command can be used within the CLI to double check the current identity. ---- [standalone@localhost:9993 /] :whoami(verbose=true) { "outcome" => "success", "result" => { "identity" => {"username" => "Ladybird"}, "mapped-roles" => ["SuperUser"] } } ----