Securing services

When Akka Serverless services are exposed to the internet using routes, all requests are served using Transport Layer Security (TLS). This ensures that a client can trust that the server they are connecting to is the server that they intended to connect to, and ensures that the connection is encrypted and can’t be tampered with. However, the default configuration doesn’t offer the server any guarantees about the identity of the client. By default, anyone on the internet can connect to your exposed services.

Akka Serverless offers two different mechanisms for controlling who can invoke your services and what they can do with your services, the first being JSON Web Tokens (JWTs), the second being client certificates, also known as Mutual TLS (mTLS). Which mechanism is right for you depends on your use case.

Client certificates

Client certificates allow you to control who can connect to your services, by requiring all clients to present a certificate when they connect. This is a very course grained level of authentication, and is ideal for situations where you only want your service to be accessible to other services that you control.

To enable this, you will need a Certificate Authority (CA) that is capable of issuing client certificates to the clients that you want to consume your Akka Serverless services. Akka Serverless will trust any client certificates issued by that CA, so it’s important to only issue certificates to people or services that you trust.

Many organisations will already have a CA that they can use for this, perhaps using products like HashiCorp Vault or Kubernetes cert-manager. If you already have a way of issuing client certificates from a CA, then to enable this feature, you just need that CA’s certificate, and you can skip the next step.

Creating your own CA

If you don’t have a mechanism for issuing client certificates with a CA, this guide will walk you through the process. We will use the smallstep CLI, a tool that makes it very easy.

First you will need to install the CLI using the instructions linked above.

Then we’ll create a CA certificate and key:

step certificate create --profile root-ca "My Root CA" \
  my-root-ca.crt my-root-ca.key --insecure --no-password

Now that we have the CA, we’ll also create a client certificate. We don’t actually need this to configure the client certificate support in Akka Serverless. Only the CA certificate is needed for that. The client certificate will be used by our client when we try to connect to the service:

step certificate create "My Client" my-client.crt my-client.key \
  --ca my-root-ca.crt --ca-key my-root-ca.key --insecure --no-password

Configuring the CA secret

Now that we have a CA certificate, we can configure it as a secret in Akka Serverless. The type of secret we’re creating is called a TLS CA secret:

akkasls secret create tls-ca my-root-ca --cert ./my-root-ca.crt

Configuring a route to use the secret

We now need to configure a route to use a secret. Routes can be created by following the instructions in exposing services to the internet. If you haven’t yet created your route, then using the akkasls route create command, you can pass the flag --client-ca-secret my-root-ca when you create it. Otherwise, you can update it:

akkasls route update my-route --client-ca-secret my-root-ca

Testing that the service is secured

Your service should now be secured. You can test that it’s secured using curl. Let’s say the URL that your service is exposed on is spring-tooth-3406.us-east1.akkaserverless.app. Try issuing a simple curl request on it:

$ curl https://spring-tooth-3406.us-east1.akkaserverless.app -I
curl: (56) OpenSSL SSL_read: error:1409445C:SSL routines:ssl3_read_bytes:tlsv13 alert certificate required, errno 0

You can see that curl is reporting that a certificate is required to connect to this service. Now if you have a client certificate issued by the CA handy, like the one created above using smallstep, you can try the same request with the client certificate:

$ curl https://spring-tooth-3406.us-east1.akkaserverless.app -I --key my-client.key --cert my-client.crt
HTTP/2 404
content-length: 0
date: Wed, 10 Nov 2021 05:00:59 GMT
server: envoy
x-envoy-upstream-service-time: 19

Unless you have defined HTTP transcoding rules for the root path, your service is expected to respond with 404, as shown above. This verifies that the client certificate was accepted and the service is secured.