Enabling SSL for Stratos PostgreSQL Connections

Photo by Ricardo Gomez Angel on Unsplash

Adding the requirement for SSL to Stratos is a fairly easy process. This configuration is highly recommended for production deployments of Stratos on Cloud Foundry.

In the example manifest below, this option is enabled by adding DB_SSL_MODE: "verify-ca" to the bottom of the environment variables:

applications:
  - name: console
    memory: 1512M
    disk_quota: 1024M
    host: console
    timeout: 180
    buildpack: https://github.com/cloudfoundry-incubator/stratos-buildpack#v4.0
    health-check-type: port
    services:
    - console_db
    env:
      CF_API_URL: https://api.bosh-lite.com
      CF_CLIENT: stratos_client
      CF_CLIENT_SECRET: sssshhhitsasecret
      SSO_OPTIONS: "logout, nosplash"
      SSO_WHITELIST: "https://console.bosh-lite.com"
      SSO_LOGIN: true
      DB_SSL_MODE: "verify-ca"

Why this works

The example above relies on a CUPS service instance called console_db which points to a RDS PostgreSQL instance created manually. Creating the CUPS service is as easy as:

cf cups console_db -p '{"uri": "postgres://", "username":"myuser", "password":"mypass", "hostname":"something.xyx.us-west-2.rds.amazon.com", "port":"5432", "dbname":"console_db"}'

Once executed, you can use the console_db as the name of the service in manifest.yml for Stratos.

Also take note that I’m using a RDS instance which means I need the RDS CA in the trusted store of the CF app container which Stratos is running in. This is done by configuring the following ops file to be deployed against Cloud Foundry:

- type: replace
  path: /instance_groups/name=diego-cell/jobs/name=rep/properties/containers/trusted_ca_certificates/-
  value: &rds-uswest2-ca |-
    -----BEGIN CERTIFICATE-----
    MIIEBjCCAu6gAwIBAgIJAMc0ZzaSUK51MA0GCSqGSIb3DQEBCwUAMIGPMQswCQYD
    VQQGEwJVUzEQMA4GA1UEBwwHU2VhdHRsZTETMBEGA1UECAwKV2FzaGluZ3RvbjEi
    MCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNlcywgSW5jLjETMBEGA1UECwwKQW1h
    em9uIFJEUzEgMB4GA1UEAwwXQW1hem9uIFJEUyBSb290IDIwMTkgQ0EwHhcNMTkw
    ODIyMTcwODUwWhcNMjQwODIyMTcwODUwWjCBjzELMAkGA1UEBhMCVVMxEDAOBgNV
    BAcMB1NlYXR0bGUxEzARBgNVBAgMCldhc2hpbmd0b24xIjAgBgNVBAoMGUFtYXpv
    biBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMxIDAeBgNV
    BAMMF0FtYXpvbiBSRFMgUm9vdCAyMDE5IENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
    AQ8AMIIBCgKCAQEArXnF/E6/Qh+ku3hQTSKPMhQQlCpoWvnIthzX6MK3p5a0eXKZ
    oWIjYcNNG6UwJjp4fUXl6glp53Jobn+tWNX88dNH2n8DVbppSwScVE2LpuL+94vY
    0EYE/XxN7svKea8YvlrqkUBKyxLxTjh+U/KrGOaHxz9v0l6ZNlDbuaZw3qIWdD/I
    6aNbGeRUVtpM6P+bWIoxVl/caQylQS6CEYUk+CpVyJSkopwJlzXT07tMoDL5WgX9
    O08KVgDNz9qP/IGtAcRduRcNioH3E9v981QO1zt/Gpb2f8NqAjUUCUZzOnij6mx9
    McZ+9cWX88CRzR0vQODWuZscgI08NvM69Fn2SQIDAQABo2MwYTAOBgNVHQ8BAf8E
    BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUc19g2LzLA5j0Kxc0LjZa
    pmD/vB8wHwYDVR0jBBgwFoAUc19g2LzLA5j0Kxc0LjZapmD/vB8wDQYJKoZIhvcN
    AQELBQADggEBAHAG7WTmyjzPRIM85rVj+fWHsLIvqpw6DObIjMWokpliCeMINZFV
    ynfgBKsf1ExwbvJNzYFXW6dihnguDG9VMPpi2up/ctQTN8tm9nDKOy08uNZoofMc
    NUZxKCEkVKZv+IL4oHoeayt8egtv3ujJM6V14AstMQ6SwvwvA93EP/Ug2e4WAXHu
    cbI1NAbUgVDqp+DRdfvZkgYKryjTWd/0+1fS8X1bBZVWzl7eirNVnHbSH2ZDpNuY
    0SBd8dj5F6ld3t58ydZbrTHze7JJOd8ijySAp4/kiu9UfZWuTPABzDa/DSdz9Dk/
    zPW4CXXvhLmE02TA9/HeCw3KEHIwicNuEfw=
    -----END CERTIFICATE-----
- type: replace
  path: /instance_groups/name=diego-cell/jobs/name=cflinuxfs3-rootfs-setup/properties/cflinuxfs3-rootfs/trusted_certs/-
  value: *rds-uswest2-ca

The RDS certs for other AWS regions are documented at https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html

Verifying that Database Connections is using SSL

Trust but verify. By making a psql connection to the RDS instance you can verify the connections from Stratos are indeed leveraging SSL. Run the following:

SELECT 
  datid.datname,
  pg_stat_ssl.pid,
  usesysid,
  usename,
  application_name,
  client_addr,
  client_hostname,
  client_port,
  ssl,
  cipher,
  bits,
  compression
FROM
  pg_stat_activity,
  pg_stat_ssl
WHERE
  pg_stat_activity.pid = pg_stat_ssl.pid
  AND pg_stat_activity.usename = 'myuser';  # Name of the user you configured in CUPS


 dataid |  datname   |  pid  | usesysid | username | application_name | client_addr  | client_hostname | client_port | ssl |           cipher            | bits | compression
 -------+------------+-------+----------+----------+------------------+--------------+-----------------+-------------+-----+-----------------------------+------+------------
  16104 | console_db |  3518 |    16939 | myuser   |                  | 10.244.0.20  |                 |       43104 | t   | ECDHE-RSA-AES256-GCM-SHA384 |  256 | f
  16104 | console_db | 22334 |    16939 | myuser   |                  | 10.244.0.20  |                 |       56321 | t   | ECDHE-RSA-AES256-GCM-SHA384 |  256 | f
  16104 | console_db | 25259 |    16939 | myuser   | psql             | 10.244.0.99  |                 |       58990 | t   | ECDHE-RSA-AES256-GCM-SHA384 |  256 | f

In the example above, the third connection is the psql client we are running this query from, the other two connections are coming from the Stratos app on the Diego cell.

What doesn’t work

If you are attempting to set the SSL Mode via the URI, while a valid assumption, configuring the CUPS connection will be ignored:

cf cups console_db -p '{"uri": "postgres://", "username":"myuser", "password":"mypass", "hostname":"something.xyx.us-west-2.rds.amazon.com", "port":"5432", "dbname":"console_db", "sslmode":"verify-ca" }'

This is because the Stratos configuration is specifically looking for an environment variable:

db.SSLMode = env.String(“DBSSLMODE”, “disable”)

From https://github.com/cloudfoundry/stratos/blob/master/src/jetstream/datastore/databasecfconfig.go#L81

Enjoy!

Spread the word

twitter icon facebook icon linkedin icon