Managing SSL Certificates for Custom Routes

When a client makes an HTTPS request for a application route, the Apcera router presents the SSL certificate used to configure and install the cluster. This certficiate is typically configured for the cluster domain (*.example.apcera-platform.io, for example), which means that only routes that share that domain can have a secure connection to the Apcera router (app.example.apcera-platform.io, for example).

To use a custom (or "vanity") URL for an application route (www.mycoolapp.com, for example) you can import an SSL certificate and private key into your cluster's secret storage, then install the certificate to the Apcera router for your custom domain.

Your cluster must have required policy for you to create, read, and delete certifiates/private keys, as well as install a cert/key pair to the Apcera router for a particular domain.

Importing and deleting certificates and private keys

You use the apc secret import <file> command to import a PEM file that contains one of the following:

  • An SSL certificate
  • A private key
  • An SSL certificate and private key

For example, suppose you have a PEM file named cert_key.pem file that contains both an SSL certificate and a private key:

cert_key.pem

-----BEGIN CERTIFICATE-----
MIIE2TCCA8GgAwIBAgIJAOcYWlnmlPnXMA0GCSqGSIb3DQEBBQUAMIGjMQswCQYD
....
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAscV+HJP/0IwUhkmk02UMEqHwegcgTQnMPpeEZ5bmwa+eGT9m
...
-----END RSA PRIVATE KEY-----

To import this certificate and private key as a single secret resource you would use the following command:

apc secret import /path/to/cert_key.pem \
--namespace /certs/mywebsite --description 'Test certificate/key pair'

This creates a new secret resource type named cert_key in the /certs/mywebsite namespace. You can use the apc secret list command to list the newly imported secret.

apc secret list
Working in /certs/mywebsite
╭──────────┬─────────────────────────────┬──────────────────┬───────────────────────────╮
│ Name     │ Type                        │ Namespace        │ Description               │
├──────────┼─────────────────────────────┼──────────────────┼───────────────────────────┤
│ cert_key │ certificate_and_private_key │ /certs/mywebsite │ Test certificate/key pair │
╰──────────┴─────────────────────────────┴──────────────────┴───────────────────────────╯

In this case, note that the Type column indicates that the imported secret type is certificate_and_private_key. You can also import certificates and keys as separate resources. For example, suppose you have a certificate and private key named certificate.pem and key.pem that contain an SSL certificate and private key, respectively.

certificate.pem

-----BEGIN CERTIFICATE-----
MIIE2TCCA8GgAwIBAgIJAOcYWlnmlPnXMA0GCSqGSIb3DQEBBQUAMIGjMQswCQYD
....
-----END CERTIFICATE-----

key.pem

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAscV+HJP/0IwUhkmk02UMEqHwegcgTQnMPpeEZ5bmwa+eGT9m
...
-----END RSA PRIVATE KEY-----

The following commands import the certificate and key:

apc secret import certificate.pem
apc secret import key.pem

Listing the imported secrets indicates the they have types of certificate and private_key, respectively.

apc secret list
Working in /certs/mywebsite
╭─────────────┬─────────────┬──────────────────┬─────────────╮
│ Name        │ Type        │ Namespace        │ Description │
├─────────────┼─────────────┼──────────────────┼─────────────┤
│ certificate │ certificate │ /certs/mywebsite │             │
│ key         │ private_key │ /certs/mywebsite │             │
╰─────────────┴─────────────┴──────────────────┴─────────────╯

By default, automaticaly determines the correct secret type (certificate, private_key, or certificate_and_private_key) by inspecting the PEM file contents. You can also specify the secret type explicitly with the --type (or -t) command option, for example:

apc secret import my_private_key.pem --type private_key

To view details about an imported cert, key, or cert-key pair you use the apc secret show <secret-name> command, which also shows details about the Issuer

apc secret show cert_key
╭─────────────────────────────┬────────────────────────────────────╮
│ secret:                     │ cert_key                           │
├─────────────────────────────┼────────────────────────────────────┤
│ FQN:                        │ secret::/certs/mywebsite::cert_key │
│                             │                                    │
│ Secret Type:                │ certificate_and_private_key        │
│                             │                                    │
│ Description:                │ Test certificate/key pair          │
│                             │                                    │
│ Created By:                 │ admin@example.com                  │
│ Created At:                 │ 1969-12-31 16:00:00 -0800 PST      │
│                             │                                    │
│ Updated By:                 │ admin@example.com                  │
│ Updated At:                 │ 1969-12-31 16:00:00 -0800 PST      │
│                             │                                    │
│ Certificate 1 IssuerCN      │ *.example.com                      │
│ Certificate 1 SubjectCN     │ *.example.com                      │
│ Certificate 1 Not After     │ 2018-06-08 22:38:48 +0000 UTC      │
│ Certificate 1 Serial Number │ 80e2ce1ac4ca1e0f                   │
│ Certificate 1 SANsNames     │ []                                 │
╰─────────────────────────────┴────────────────────────────────────╯

Importing password-protected keys

If the private key is password-protected you must include the --password option to the apc secret import command. APC prompts you to enter the password:

apc secret import password-protected-key.pem --password
Password: ********

An error is returned if you provide an incorrect password:

apc secret import password-protected-key.pem --password
Password: ***
Error: ERROR : Failure decrypting key "secret::/certs::password-protected-key":
x509: decryption password incorrect

If you don't include the --password option the private key is imported as a generic secret type not as a private_key type:

apc secret import password-protected-key.pem

apc secret list
Working in /sandbox/admin
╭────────────────────────┬─────────────┬──────────────────┬─────────────╮
│ Name                   │ Type        │ Namespace        │ Description │
├────────────────────────┼─────────────┼──────────────────┼─────────────┤
│ password-protected-key │ secret      │ /sandbox/admin   │             │
│ cert                   │ certificate │ /sandbox/admin   │             │
╰────────────────────────┴─────────────┴──────────────────┴─────────────╯

Installing and uninstalling certificates and private keys

Once you've imported an SSL certificate/private key pair you use the apc secret install command to install it to the Apcera router for a specific domain. Installing the certificate makes it available to the Apcera router to present to clients that make HTTPS request for an application on that domain.

Notes:

  • Certificate install requests are batched and executed every 30 seconds, by default. (This interval is configurable during cluster deployment, see Router batch update interval). This means that a domain will not be available immediately after installing a certificate, but will be available within 30 seconds (or the batch interval you have specified).
  • If a certificate was installed for a domain during deployment of the Apcera cluster, you cannot install the same certificate for the same domain using APC.

For example, suppose you've imported a combined certificate/key pair named "cert_key_combined". The SSL certificate's Common Name field is set to *.example.com. The following command installs the certificate to the Apcera router for that domain:

apc secret install cert_key_combined --domain "*.example.com"

To install a certificate there must a domain.allow policy claim on the specified secret resource (or parent namespace) that lists the domain specified in the --domain option to the apc secret install command, for example:

on secret::/sandbox/admin:cert_key_combined {
    {
         permit create, read, delete
         domain.allow "*.example.com"
    }
}

If you imported the certificate and key as separate secrets then you must specify the private key to use with the --privatekey command option, for example:

apc secret install mycert --privatekey mykey --domain app.example.com

You can allow use wildcards when specifying domains in domain.allow. For example, the following policy would also allow you to install the certificate for any host under the example.com domain, such as app1.example.com or app2.example.com.

on secret::/sandbox/admin:cert_key_combined {
    {
        permit create, read, delete
        domain.allow "*.example.com"
    }
}

You can also install a default domain certificate by specifying "*" as the domain. If the router receives a request for a domain that doesn't match one of its installed certificates, it returns the "default domain" certificate to the client. For example, the following installs a default domain certificate:

apc secret install cert1 -domain "*"

To uninstall a certificate you use the apc secret uninstall command, passing it the installed domain:

apc secret uninstall *.example.com

Listing certificates and private keys

By default, the apc secret list command lists all imported certificates and private keys in the working namespace, for example:

apc secret list -ns /certs/example.com
Working in /certs/example.com
╭─────────────────────────┬─────────────┬────────────────────┬─────────────╮
│ Name                    │ Type        │ Namespace          │ Description │
├─────────────────────────┼─────────────┼────────────────────┼─────────────┤
│ example.com-certificate │ certificate │ /certs/example.com │             │
│ example.com-key         │ private_key │ /certs/example.com │             │
╰─────────────────────────┴─────────────┴────────────────────┴─────────────╯

To only list installed certificates add the --installed command option. For example, the following lists installed certificates in all namespaces:

apc secret list -ns / --installed
Working in /
╭─────────────────┬──────────────────────────────────┬─────────────────────────────────────────────╮
│ Domain          │ Certificate                      │ Private-Key                                 │
├─────────────────┼──────────────────────────────────┼─────────────────────────────────────────────┤
│ app.example.com │ secret::/certs/example.com::cert │ secret::/certs/example.com::key             │
│ *.apcera.com    │ secret::/certs/apcera.com::cert  │ secret::/certs/apcera.com::key              │
╰─────────────────┴─────────────────────────────────────────────────────┴──────────────────────────╯

You can also only list secrets of a specific type. Valid type are "certificate", "private_key", "certificate_and_private_key", and "secret"

Deleting certificates and private keys

To delete a certificate or key, you use the apc secret delete <secret> command:

apc secret delete my-cert
apc secret delete my-privatekey

An error is generated if you attempt to delete a certificate that is currently installed for a domain:

Error: Secret "secret::/sandbox/certs::my-cert" installed on the cluster router

You must first uninstall the certificate for that domain, and then you can delete the certificate.

apc secret uninstall *.example.com

Policy requirements

To manage certificates and private keys on there must be policy that allows you to create, delete and read on the secret::/ realm. You also need policy that lets you install a certificate to the platform router. For example, the following permits secrets to be created, deleted, and read in the /sandbox/certs namespace. It also allows a certificate/key pair in that namespace to be installed on the cluster router for the domain "*.example.com".

on secret::/sandbox/certs {
    {
     permit create, read, delete
     domain.allow "*.example.com"
    }
}

Note: You must enclose the value assigned to domain.allow in quotes if the domain contains a wildcard character (*).

For more information see Secrets Permissions.

Configuring DNS for your custom domain

For your custom domain to resolve correctly you need to add a CNAME or A record to your DNS hosting service that points to your Apcera cluster’s router. If your router has a static IP address then you add an A record that points to the router’s IP address. For clusters on AWS the router is an Elastic Load Balancer (ELB) instance so you would create a CNAME record for your domain that points to that location (dualstack.cluster1-router-elb-19-294410475.us-west-1.elb.amazonaws.com, for example).