Search code examples
jbossresteasy

EAP: create rest client with elytron client-ssl-context


I know, how to build a ResteasyClient with own SSL context.

  builder.sslContext(mySSLcontext);

It works fine, e.g from standalone client and/or arquillain tests. I build the SSL context programmatically, loading truststore etc.

I have a EAR+War (ProjekctA) offering a Rest Service using web.xml:

  <login-config>
    <auth-method>CLIENT-CERT</auth-method>
    <realm-name>ICSCRest</realm-name>
  </login-config>

and jboss-web.xml

  <jboss-web>
    <server-instance>default-server</server-instance>      
    <virtual-host>default-host</virtual-host>
    <security-domain>ICSDRest</security-domain>
  </jboss-web>

The EAP (7.4.7) is configured with Elytron, offering the security domain (ICSDRest). Works fine. Access to the Rest service is now secured by the SSL layer. I also have configured EAP to have a client-ssl-context (see below LDAP).

  <client-ssl-contexts>
    <client-ssl-context name="ICLdapSslContext" trust-manager="ICTrustManager"/>
  </client-ssl-contexts>

A second EAR+War (ProjectB) should use the Rest service from ProjectA. So ProjectB is a Rest client.

To instanciate the ResteasyClient in ProjectB, I must set the sslContext too (I guess). I want pick a client-ssl-context from Elytron, if possible. Is there a way?

Why I want to pick from Elytron?

ProjectA is also dealing with LDAP via ldaps. So ProjectA is a client for LDAP server. I have configured EAP as a LDAP client like

  <dir-contexts>
    <dir-context name="ICLdap" url="<some url>" principal="<query>" ssl-context="ICLdapSslContext">
    <credential-reference clear-text="<some password>"/>
    </dir-context>
  </dir-contexts>

So I hope, I can get is a similar way the sslContext from EAP/Elytron. The idea is to get from Elytron the SSL context and set like

  builder.sslContext(mySSLcontext)

or create the ReasteasyClient within the context.

Any hints for a EAP beginner. Thanks in advance.


Solution

  • I found another solution:

    I created a new key for my REST client in ProjectB.

    keytool -genkey -keystore projectB-client.p12 ...
    keytool -exportcert -keystore projectB-client.p12 ...
    

    Added public key from JBoss/EAP of projectA to projectB-client.p12

    keytool -keystore projectB-client.p12 -importcert -trustcacerts ...
    

    The keystore projectB-client.p12 is placed in EAP standalone/configuration directory.

    Added public key from projectB-client.p12 to truststore of JBoss/EAP

    keytool -keystore app.truststore -importcert -trustcacerts ....
    

    With Jboss CLI, I added a new security domain.

    /subsystem=security/security-domain=projectB-client:add
    /subsystem=security/security-domain=projectB-client/jsse=classic:add(truststore={password=<...>,url="file:${jboss.server.config.dir}/app.truststore"}, \
      keystore={password=<...>, url="file:${jboss.server.config.dir}/projectB-client.p12"}, client-auth=true)
    

    This is creating a entry like:

    <security-domains>
        ...
        <security-domain name="projectB-client">
            <jsse keystore-password="password here" keystore-url="file:${jboss.server.config.dir}/projectB-client.p12" truststore-password="password here" truststore-url="file:${jboss.server.config.dir}/app.truststore" client-auth="true"/>
        </security-domain>
    </security-domains>
    

    In ProjectB, the following code will request the security domain from EAP and getting access to key- and trusmanager without having any password for both.

    E.g

    @ApplicationScoped
    public class InitalizerOnStartup {
    
        private MyService myService;
    
        // getter
    
        public void onStart(@Observes @Initialized(ApplicationScoped.class) Object pointless) throws Exception {
            buildRestClient();
        }
    
        private void buildRestClient () throws Exception {
            final String sdName = "java:jboss/jaas/projectB-client/jsse";
            final URL endPoint = new URL("https://localhost:8443/myUrl");
            Context ctx = new InitialContext();
            JBossJSSESecurityDomain sd = (JBossJSSESecurityDomain) ctx.lookup(sdName);
            if ( sd == null )
                throw new Exception("Can't get EAP security domain - name=" + sdName);
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(sd.getKeyManagers(), sd.getTrustManagers(), null);
    
            ResteasyClientBuilder builder = new ResteasyClientBuilder();
            builder.sslContext(sslContext);
            ResteasyClient client = builder.build();
            ResteasyWebTarget target = client.target(endPoint.toURI());
            myService = target.proxy(MyService.class);
        }
    }
    

    Or use EBJ technique @Startup.

    I guess, this logic will also work, when having ProjectA + B on different servers (use localhost -> fqdn)

    To use JBossJSSESecurityDomain ->

    dependencies {
        providedCompile 'org.picketbox:picketbox:5.0.3.Final'  // I use the exact same version from my EAP release, here 7.4.7
    }