Goal
Using public key infrastructure (PKI) on your Platform.sh project for authentication.
Background
PKI is used to:
- centralize the authentication process
- automatically provide new accounts for authentication
- avoid a dependency on a centralized authentication server which might not be available at all times
- automatically expire accounts for authentication after a given period (unless they refresh)
PKI starts with the root certificate authority who keeps a private key and a certificate. The certificate is public, and can be used to verify users’ certificates.
When a new user (automated or not) needs a new certificate, they:
- generate a private key
- generate a Certificate Signing Request (CSR) that is sent to the root certificate authority
The root certificate authority receives the CSR, validates that the user is valid, and returns a signed certificate to the user. The user can then use this signed certificate to authenticate.
When a server wants to authenticate a certificate, it uses the root certificate authority’s certificate to verify the signature in the user’s certificate. This verification can be done on Platform.sh, which is what this How-To will show.
Assumptions
You will need:
- A local git repository that has the Platform.sh project as a git remote
- A working application setup on the Platform.sh project
openssl
Steps
1. Create a PKI
Create the certificate authority private key and certificate
Create the private key that the certificate authority must keep private.
$ openssl genrsa -out /tmp/rootCA.key 4096
Generating RSA private key, 4096 bit long modulus
.....++
.................++
$
The key will look similar to this:
$ head -n2 /tmp/rootCA.key
-----BEGIN RSA PRIVATE KEY-----
MIIJJwIBAAKCAgEAyxCraEAvZUnGZ1OVAynDVCjp0qGZvI0nHPwHBxYH5eJ96pB6
$
Based on this, create the public certificate:
$ openssl req -x509 -new -nodes -key /tmp/rootCA.key -sha256 -days 365 -out /tmp/rootCA.crt
Pass the previously-created key.
openssl
will ask a few questions, they’re not important for the purpose of this How-To.
The public certificate will look similar to this:
$ head -n2 /tmp/rootCA.crt
-----BEGIN CERTIFICATE-----
MIIFXTCCA0WgAwIBAgIJAPs0rURM8vWtMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
$
Create the first user’s private key and CSR
Now that the certificate authority is setup, create a user’s private key and CSR.
This creates the private key:
$ openssl genrsa -out /tmp/user.key 4096
Generating RSA private key, 4096 bit long modulus
...........................++
.++
$
And this creates the CSR:
$ openssl req -new -key /tmp/user.key -out /tmp/user.csr
openssl
will ask again some questions that are not important for the purpose of this How-To.
Create the first user’s public certificate
Based on the explanation above, use the root certificate authority’s private key to sign the CSR, which creates a new public certificate for the user.
$ openssl x509 -req -in /tmp/user.csr -CA /tmp/rootCA.crt -CAkey /tmp/rootCA.key \
-CAcreateserial -out /tmp/user.crt -days 30 -sha256
This creates a public certificate that the user can use, valid for 30 days.
Note that only the user can use this certificate to authenticate, because it needs the private key (“user.key” above).
Et voila! We now have a PKI with one user.
2. Authenticate users of the PKI on Platform.sh
We’re now getting to the easy part of this How-To: we’re going to authenticate our user on Platform.sh using TLS client certificates.
For this test, we’re going to need 3 things:
- The root certificate authority’s public certificate (
rootCA.crt
above) - The user’s private key (
user.key
above) - The user’s public certificate (
user.crt
above)
The first step is configuring your Platform.sh project to authenticate users by providing the root certificate authority’s public certificate, as such in the .platform/routes.yaml
:
https://{default}/:
type: upstream
upstream: app:http
tls:
client_authentication: "require"
client_certificate_authorities:
- !include
type: string
path: rootCA.crt
Put the rootCA.crt
file in the .platform/
folder.
Commit and push these changes:
$ git add .platform/routes.yaml .platform/rootCA.crt
$ git commit -m "Enable TLS client certificates authentication"
$ git push platform master
And that’s it!
Test the changes:
$ curl https://my-project.com
curl: (35) error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate
$ curl --key user.key --cert user.crt https://my-project.com
It's working!
Conclusion
Setting up a Platform.sh project to authenticate users using PKI requires only a few lines of code added to the .platform/routes.yaml
file.