How to Configure SSL Encryption for Custom Domains on Pivotal CF

by Sergey BalashevichFebruary 8, 2016
This tutorial provides all the steps for creating a certificate and setting up the Pivotal SSL Service.

Where to start?

pivotal-cf-ssl-java-v3

The new Pivotal SSL Service has made it possible to use your own certificates in PCF—both domain-specific and wildcard. This means SSL/TLS encryption can now be added to apps in custom domains. However, if you work with Apache Tomcat and JKS, you may find that the official documentation provides the main instructions, but—unfortunately—does not cover the details.

As a Java developer, I am used to dealing with SSL certificates in the JKS format that can be used in Apache Tomcat configuration. Normally, you will need to have something similar to this connection definition in your server.xml:

    <Connector port="8443"
                protocol="org.apache.coyote.http11.Http11Protocol"
                keystoreFile="my.keystore"
                keystorePass="password"
                keyAlias="mysite"  URIEncoding="UTF-8"
              maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
            clientAuth="false" sslProtocol="TLS" />

If you already have a certificate, it is probably declared here. If not, below are step-by-step instructions on how to create it from scratch.

 

Generating a JKS certificate

The my.keystore file was created using the command:

  keytool -genkey -alias [youralias] -keyalg RSA -keystore [/preferred/keystore/path/my.keystore]

Keep in mind that the Common Name—which answers the question “What is your first and last name?”—should be your domain name:

    What is your first and last name?
      [Unknown]:  www.mysite.com
    What is the name of your organizational unit?
      [Unknown]:  Unit
    What is the name of your organization?
      [Unknown]:  Organization
    What is the name of your City or Locality?
      [Unknown]:  City
    What is the name of your State or Province?
      [Unknown]:  State
    What is the two-letter country code for this unit?
      [Unknown]:  US
    Is CN=www.mysite.com, OU=Unit, O=Organization, L=City, ST=State, C=US correct?
      [no]:  yes

 

Generating a CSR file

Then, the CSR file was generated with:

  keytool -certreq -keyalg RSA -alias [youralias] -file [my].csr -keystore [path/to/your/keystore/my.keystore]

 

Getting your certificates signed

The CSR file that you have just created needs to be submitted to a certification authority, like GoDaddy or Comodo. After domain validation, you will receive a ZIP archive with a set of *.crt files. In my case, it was gd_bundle-g2-g1.crt with root and intermediate certificates and 79bd1f68a63.crt with a certificate for the validated domain.

 

Creating a chain.crt file

All these *.crt files need to be copied to a single chain.crt file that looks like this:

      -----BEGIN CERTIFICATE-----
      ……..
      -----END CERTIFICATE-----
      -----BEGIN CERTIFICATE-----
      ……..
      -----END CERTIFICATE-----
      -----BEGIN CERTIFICATE-----
      ……...
      -----END CERTIFICATE-----
      (…and so on)

 

Converting JKS to RSA

With both my.keystore (the private key) and chain.crt (a set of certificates) in place, we are about to complete SSL service configuration. But first, our private key must be converted from JKS to the RSA format. That can be done in a number of different ways. Here is just one of them:

  1. convert JKS to p12:
  2.   keytool -importkeystore -srckeystore my.keystore -destkeystore my.p12 -srcstoretype jks -deststoretype pkcs12

  3. convert p12 to an encrypted .pem file:
  4.   openssl pkcs12 -in my.p12 -out my.pem

  5. create an RSA private key that can be used in PCF:
  6.   openssl rsa -in my.pem -out my.key 

     

    Creating a new SSL service

    Now we can create a new SSL service using the Pivotal CF GUI:

    • In step one, click the “Upload .crt” button and select the chain.crt file with all the certificates included.

    • In step two, click “Upload .key” and select the my.key file created by the openssl utility. Then, click “Submit.”

    Pivotal CF TLS for Custom Domains

    If everything was done correctly, you should see this page:

    TLS/SSL with JKS Certificates on Pivotal CF

     

    Creating a DNS CNAME record

    After your application has been deployed to Cloud Foundry, the domain needs to be registered with:

      cf create-domain Mysite mysite.com

    We also need to map a route with:

      cf map-route mysiteappname mysite.com -n "*"

    The final step is creating a DNS CNAME record. In Amazon Web Services, that can be done using the Route53 service:

    ssl-tls-custom-domains-pivotalcf-v2

    Now all requests to https://www.mysite.com will be encrypted using your own SSL certificate for the custom domain mysite.com, but http://mysite.cfapps.io is still working, providing access to your website via a non-encrypted connection.

     

    Redirecting HTTP traffic to HTTPS

    At this moment, there are no additional settings in the Pivotal SSL service and you cannot automatically redirect HTTP traffic to HTTPS. As a temporary workaround, that can be done using the following configuration in Spring Boot:

    @SpringBootApplication
    @RestController
    public class SslTestApplication {
    
        @Bean
        public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory(){
         return new TomcatEmbeddedServletContainerFactory() {
           @Override
           protected void postProcessContext(Context context) {
             SecurityConstraint securityConstraint = new SecurityConstraint();
             securityConstraint.setUserConstraint("CONFIDENTIAL");
             SecurityCollection collection = new SecurityCollection();
             collection.addPattern("/*");
             securityConstraint.addCollection(collection);
             context.addConstraint(securityConstraint);
           }
         };
        }
    
        public static void main(String[] args) {
         SpringApplication.run(SslTestApplication.class, args);
        }
    }
    

    If you add this code to your Spring Boot app, all requests will be forced to go through HTTPS—via a secure path.

     

    Further reading