In addition to implementing Server Authentication, you can also implement mutual (client and server) authentication. Client authentication enables the Controller to ensure that only authorized and verified agents can establish connections. These procedures outline the workflow to implement mutual authentication. 

Before Starting

  • These agents support client authentication:
    • Java Agent
    • Database Agent
    • Machine Agent
    • .NET Agent for Windows 

      Excludes Azure PaaS environments, such as Azure App Services.

  • First, it is good practice to set up and verify client authentication on one agent. After confirming that the client authentication is working for that agent, proceed with configuring additional agents. 
  • If you have a "hybrid" environment, with Server Authentication only for some agents and Server and Client Authentication for others, you might want to set up and configure multiple HTTP Listeners in Glassfish: one for Server Authentication only, and another for both Server and Client Authentication. 
  • The procedures described on this page use the default key and keystore password (changeit) for the keystore. Before you proceed with this workflow, it is good practice to:

    1. Change this default password, as described in "Change Keystore Password" under Controller SSL and Certificates.
    2. Use the new password when you perform these procedures.
  • Instead of using plain text passwords in the procedures, you can specify encrypted or obscured passwords described in Encrypt Agent Credentials.  

Set Up Mutual Authentication

These steps describe how to set up Mutual Authentication:

  1. Set up server authentication on agents.
  2. Set up a client keystore on the agent.
  3. Configure agents to access the client keystore.
  4. Enable client authentication on the Controller

Set Up Server Authentication on Agents

To establish server authentication on agents, you must create an agent truststore that contains the root certificate for the authority that signed the Controller's certificate.

For each authorized agent:

  1. Obtain one of the following root certificates:
    • The root certificate for the publicly known certificate authority (CA) that signed the certificate for your on-premises Controller.
    • The root certificate for the internal CA that signed the Controller certificate for your on-premises Controller.
  2. Run the Java keytool command to create the agent truststore: 

    keytool -import -alias rootCA -file /usr/home/appdynamics/DigicertGlobalRootCA.pem -keystore cacerts.jks -storepass MySecurePassnword 
    CODE

    For example: 

    keytool -import -alias rootCA -file /usr/home/appdynamics/DigicertGlobalRootCA.pem -keystore cacerts.jks -storepass MySecurePassnword 
    BASH

    Note the truststore password because you will need this later to configure the authorized agent.

  3. Install the Agent truststore to the agent configuration directory: 

    <authorized_agent_home>/conf/ 
    CODE
  4. For each authorized agent, specify the following properties in the <agent-home>/conf/controller-info.xml file as follows:

    • <controller-ssl-enabled>true</controller-ssl-enabled>
    • <controller-port>8181</controller-port>
    • <controller-keystore-filename>cacerts.jks</controller-keystore-filename>
    • <controller-keystore-password>MySecurePassnword</controller-keystore-password>

Set Up a Client Keystore on the Agent

In this procedure, you create a signed certificate and import it into the client keystore. These steps use the Controller to sign the certificate, but you can also use a third-party Certificate Authority (CA).

  1. Create a new keypair in a new keystore, enter:

    <java-home>/bin/keytool -genkey -alias client-alias -keyalg RSA \
    -keystore clientkeystore.jks \
    -storepass changeit \
    -keypass changeit 
    BASH

    The keytool prompts you for your name, organization, and other information it needs to generate the key. AppDynamics App Agents use SunX509 as the default keystore factory algorithm. If keystores in your environment use something other than SunX509, you need to specify the algorithm to the App agent. You can do so using the system property appdynamics.agent.ssl.keymanager.factory.algorithm. For example, to set the algorithm to PKIX, add this to the startup command of the agent-monitored JVM: 

    -Dappdynamics.agent.ssl.keymanager.factory.algorithm=PKIX 
    BASH
  2. Generate a certificate signing request (client.csr) that can be signed by a Certificate Authority (CA). 

    <java-home>/bin/keytool -certreq -v -alias client-alias -file client.csr \
                            -keystore clientkeystore.jks \
                            -storepass changeit \
                            -keypass changeit 
    BASH
  3. Get the request  (client.csr) signed by a trusted CA. This command uses the Controller as a CA, which creates a new file (signedClient.cer) with the Controller-signed certificate.

    <java-home>/bin/keytool -gencert -infile ./client.csr -outfile signedClient.cer -alias s1as \
                            -keystore ./keystore.jks \
                            -storepass changeit \
                            -keypass changeit 
    BASH
  4. (Optional) To view information about the signed certificate, enter:

    <java-home>/bin/keytool -printcert -v -file ./signedClient.cer      
    BASH
  5. (Optional) To view the contents of clientkeystore.jks, enter: 

    <java-home>/bin/keytool -list -v -keystore clientkeystore.jks -storepass changeit
    BASH

    The keystore should show entries for client-alias (which is still unsigned).

  6. Import the signed public key certificate into the client keystore. This command imports signedClient.cer into clientkeystore.jks

    <java-home>/bin/keytool -importcert -v -alias client-alias -file ./signedClient.cer \
    -keystore clientkeystore.jks \
    -storepass changeit \
    -keypass changeit
    BASH

    You now have a password-protected clientkeystore.jks file on the agent with a signed certificate that verifies the Controller's authenticity. 

  7. If you get the error "Failed to establish chain from reply", install the issuing Certificate Authority's root and any intermediate certificates into the client keystore. The root CA chain establishes the validity of the CA signature on your certificate. Although most common root CA chains are included in the bundled JVM's trust store, you may need to import additional root certificates, such as certificates belonging to a private CA. To do so: 

    <java-home>/bin/keytool -import -alias [Any_alias] -file <path_to_root_or_intermediate_cert> -keystore clientkeystore.jks -storepass changeit
    CODE
  8. Verify that the trusted root certificate on the Controller includes the signing authority's public key. This procedure used the Controller as the Certificate Authority, so the public key is already included. To verify, enter: 

    <java-home>/bin/keytool -list -v -alias client-alias \
                            -keystore clientkeystore.jks -storepass changeit
    BASH

    The signing authority's public key should now be part of the agent's public key certificate.

Configure Agents to Access the Client Keystore

For each authorized agent:

  1. Copy the generated clientkeystore.jks file to the following directory on the agent:
    • Database agent: <database agent home>/conf
    • Java agent: <java-agent-home>/conf
    • Machine Agent:  <machine-agent-home>
  2. Specify these properties in the <agent-home>/conf/controller-info.xml file as follows:
    • <use-ssl-client-auth>true</use-ssl-client-auth>
    • <asymmetric-keystore-filename>clientkeystore.jks</asymmetric-keystore-filename>
    • <asymmetric-keystore-password>changeit</asymmetric-keystore-password>
    • <asymmetric-key-password>changeit</asymmetric-key-password>
    • <asymmetric-key-alias>client-alias</asymmetric-key-alias>

Enable Client Authentication on the Controller

From the Controller: 

  1. If it is not currently running, start the Controller.
  2. Open a CLI panel and cd to <controller-home>/appserver/glassfish/bin
  3. To start the AppServer Admin tool, enter: ./asadmin
    You should now see the asadmin prompt: asadmin>
  4. Enter: list-http-listeners
    This lists the available set of HTTP listeners. For example:
           http-listener-1
       http-listener-2
       admin-listener
  5. Configure one of these listeners by running the following commands. In this example, we are configuring http-listener-2:

    set configs.config.server-config.network-config.protocols.protocol.http-listener-2.ssl.key-store=keystore.jks
    set configs.config.server-config.network-config.protocols.protocol.http-listener-2.ssl.client-auth-enabled=true
    set configs.config.server-config.network-config.protocols.protocol.http-listener-2.ssl.trust-store=cacerts.jks
    CODE
  6. To verify that the properties are set correctly, run the following command. Again, this example assumes http-listener-2

     get configs.config.server-config.network-config.protocols.protocol.http-listener-2.*
    CODE
  7. Obtain one of the following root certificates:
    • The root certificate for the publicly known certificate authority (CA) that signed the certificate for your client that is the authorized agent.

    • The root certificate for the internal CA that signed the client certificate for the authorized agent.
  8. Run the Java keytool command to import the certificate into the Controller truststore: 

    <java-home>/bin/keytool -import -alias rootCA -file <root_certificate_file_name> -keystore <controller_home>/appserver/glassfish/domains/domain1/config/cacerts.jks -storepass <truststore_password> 
    CODE

    For example: 

    keytool -import -alias rootCA -file /usr/home/appdynamics/DigicertGlobalRootCA.pem -keystore /opt/appdynamics/platform/product/controller/appserver/glassfish/domains/domain1/config/cacerts.jks -storepass MySecurePassnword 
    CODE
  9. Restart the Controller.