Tuesday, 15 November 2016

WebSphere Application Server - Using Java to manage WAS via SOAP over HTTPS


This has come from a requirement to create a custom Java class to interact with the WAS Deployment Manager via SOAP over HTTPS.

The wrinkle comes because the target WAS cell is secured using: -
  • Transport Layer Security (TLS) 1.2
  • Strong ECDHE/GCM ciphers
  • Mutual Authentication
This is the relevant portion of the security.xml file: -

  <repertoire xmi:id="SSLConfig_1" alias="CellDefaultSSLSettings" managementScope="ManagementScope_1">
    <setting xmi:id="SecureSocketLayer_1" clientAuthentication="true" securityLevel="CUSTOM" enabledCiphers="SSL_ECDHE_RSA_WITH_AES_128_GCM_SHA256 SSL_ECDHE_RSA_WITH_AES_256_GCM_SHA384" jsseProvider="IBMJSSE2" sslProtocol="TLSv1.2" keyStore="KeyStore_1" trustStore="KeyStore_2" trustManager="TrustManager_2" keyManager="KeyManager_1"/>
  </repertoire>

And this is the code that I'm using to prove the concept: -

import java.util.*;
import javax.management.ObjectName;
import com.ibm.websphere.management.configservice.*;
import com.ibm.websphere.management.*;
import com.ibm.websphere.management.exception.ConnectorException;
 
class adminclient  {
    public static void main(String[] args) throws ConnectorException {

String hostName = args[0];
String soapPort = args[1];

        Properties connectProps = new Properties();
        connectProps.setProperty(AdminClient.CONNECTOR_TYPE, AdminClient.CONNECTOR_TYPE_SOAP);
        connectProps.setProperty(AdminClient.CONNECTOR_HOST, hostName);
        connectProps.setProperty(AdminClient.CONNECTOR_PORT, soapPort);
        connectProps.setProperty(AdminClient.CONNECTOR_SECURITY_ENABLED, "true");
        connectProps.setProperty(AdminClient.CACHE_DISABLED, "false");
 
        AdminClient adminClient = null;
        try {
                adminClient = AdminClientFactory.createAdminClient(connectProps);
        }
 
        catch (Exception e) {
                System.out.println("Exception creating admin client: " + e);
                e.printStackTrace();
        }

try {
ConfigService configService = new ConfigServiceProxy(adminClient);
Session session = new Session();

ObjectName[] servers = configService.resolve(session, "Server");
System.out.println("Number of servers: " + servers.length);
for (ObjectName server : servers) {
System.out.println(server.getKeyProperty("_Websphere_Config_Data_Display_Name"));
}
}

catch (Exception e) {
System.err.println("An exception " + e + " occurred.");
}
    }


To use this code, we set up two configuration files - soap.client.props and ssl.client.props - both of which were copied from the WAS configuration: -

soap.client.props

com.ibm.SOAP.securityEnabled=false
com.ibm.SOAP.authenticationTarget=BasicAuth
com.ibm.SOAP.loginUserid=wasadmin
com.ibm.SOAP.loginPassword=passw0rd
com.ibm.SOAP.loginSource=prompt
com.ibm.SOAP.krb5ConfigFile=
com.ibm.SOAP.krb5CcacheFile=
com.ibm.SOAP.krb5Service=
com.ibm.SOAP.requestTimeout=180
com.ibm.ssl.alias=DefaultSSLSettings

ssl.client.props

com.ibm.ssl.defaultAlias=DefaultSSLSettingscom.ibm.ssl.performURLHostNameVerification=false
com.ibm.ssl.validationEnabled=false
com.ibm.security.useFIPS=false
com.ibm.jsse2.checkRevocation=false
com.ibm.security.enableCRLDP=false
com.ibm.ssl.alias=DefaultSSLSettings
com.ibm.ssl.protocol=TLSv1.2
com.ibm.ssl.securityLevel=HIGH
com.ibm.ssl.trustManager=IbmPKIX
com.ibm.ssl.keyManager=IbmX509
com.ibm.ssl.contextProvider=IBMJSSE2
com.ibm.ssl.enableSignerExchangePrompt=gui
com.ibm.ssl.enabledCipherSuites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
com.ibm.ssl.keyStoreName=ClientDefaultKeyStore
com.ibm.ssl.keyStore=/home/wasadmin/key.p12
com.ibm.ssl.keyStorePassword=WebAS
com.ibm.ssl.keyStoreType=PKCS12
com.ibm.ssl.keyStoreProvider=IBMJCE
com.ibm.ssl.keyStoreFileBased=true

com.ibm.ssl.trustStoreName=ClientDefaultTrustStore
com.ibm.ssl.trustStore=/home/wasadmin/trust.p12
com.ibm.ssl.trustStorePassword=WebAS
com.ibm.ssl.trustStoreType=PKCS12
com.ibm.ssl.trustStoreProvider=IBMJCE
com.ibm.ssl.trustStoreFileBased=true
com.ibm.ssl.trustStoreReadOnly=false
Note that the latter references: -
  1. the security settings, including TLS 1.2 and the two ECDHE/GCM ciphers
  2. a pair of PKCS12 ( .p12 ) files, copied from the Deployment Manager
In the case of the .p12 files, the first ( key.p12 ) contains a personal certificate, signed by the Deployment Manager, which is used to authenticate to the Deployment Manager ( hence Mutual Authentication or Client Authentication ).

The second .p12 file ( trust.p12 ) contains the WAS cell's signer certificate, which allows the client code to decrypt what's returned from the DM.

Finally, this is how I compiled the code: -

source /opt/ibm/WebSphereProfiles/Dmgr01/bin/setupCmdLine.sh
javac -cp /opt/ibm/WebSphere/AppServer/runtimes/com.ibm.ws.admin.client_8.5.0.jar:/opt/ibm/WebSphere/AppServer/plugins/com.ibm.ws.security.crypto.jar:/opt/ibm/WebSphere/AppServer/plugins/com.ibm.ffdc.jar adminclient.java

( the first command updates the Linux shell to use the WAS Java SDK etc. )

and this is how I execute the code: -

java -Dcom.ibm.SSL.ConfigURL=file:/home/wasadmin/ssl.client.props -Dcom.ibm.SOAP.ConfigURL=file:/home/wasadmin/soap.client.props -cp /opt/ibm/WebSphere/AppServer/runtimes/com.ibm.ws.admin.client_8.5.0.jar:/opt/ibm/WebSphere/AppServer/plugins/com.ibm.ws.security.crypto.jar:/opt/ibm/WebSphere/AppServer/plugins/com.ibm.ffdc.jar:/home/wasadmin adminclient bpm857.uk.ibm.com 8879

and this is what it returns: -

Nov 15, 2016 7:29:58 AM com.ibm.ws.management.connector.interop.JMXClassLoader
WARNING: Could not find tmx4jTransform.jar in null/etc/tmx4jTransform.jar - Interoperability to older versions of WebSphere is disabled
Nov 15, 2016 7:29:58 AM com.ibm.ws.ssl.config.SSLConfigManager
INFO: CWPKI0027I: Disabling default hostname verification for HTTPS URL connections.
Nov 15, 2016 7:29:58 AM com.ibm.ws.security.config.SecurityObjectLocator
INFO: CWSCF0002I: The client code is attempting to load the security configuration the server and this operation is not allowed.
Nov 15, 2016 7:29:59 AM com.ibm.ws.security.config.SecurityObjectLocator
INFO: CWSCF0002I: The client code is attempting to load the security configuration the server and this operation is not allowed.
Number of servers: 5
dmgr
MEClusterMember1
SupClusterMember1
AppClusterMember1
nodeagent


Not the most exciting class - it's just a list of nodes - but it allows me to prove the plumbing.

Sidebar - having enabled Mutual Authentication (MA), I've now locked myself out of the Deployment Manager via a web browser, as my browser doesn't have a personal certificate that WAS trusts. Therefore, I see this: -



which is nice :-)

No comments:

Note to self - use kubectl to query images in a pod or deployment

In both cases, we use JSON ... For a deployment, we can do this: - kubectl get deployment foobar --namespace snafu --output jsonpath="{...