Securing your internal traffic by configuring the Gravitee API Management Gateway for HTTPS

Jeoffrey Haeyaert
graviteeio
Published in
10 min readApr 8, 2022

When you’re running the Gravitee API Management (APIM) Gateway, you’ll normally not worry about HTTPS as you’ll rely on a reverse proxy such as Nginx to manage that for you. However, if you’re after end-to-end security, or using approaches such as zero trust, then it becomes an important matter.

In this article we will show you how to configure the APIM Gateway to expose HTTPS. We will explain key concepts around certificates, and show different ways to configure the Gateway accordingly.

Olieman.eth on Unsplash

Why secure your internal network?

A ‘typical’ scenario

For many use cases and scenarios that use the APIM Gateway for your internal network, you are normally not concerned with managing encrypted traffic. This is because you’ll allow reverse proxies, such as Nginx to manage the securing of traffic on your behalf. Effectively, responses leaving the gateway would be in plain text (via HTTP), and then your reverse proxy takes care of the securing task (via HTTPS) on your behalf. This is a great solution that, for most of the time, meets expectations.

HTTPS managed by Nginx

Never trust, always verify

However, deferring to other systems to manage your network security is not always good enough. For example, if security is at the heart of your platform, you will want to encrypt everything, with end-to-end secured communications across your internal network. A great example of this is using the zero trust model.

It is possible to get this scenario up and running on APIM Gateway, and requires the Gateway to be securing the traffic itself. You can then configure your reverse proxy, such as Nginx to operate in “passthrough” mode. This way, even Nginx will not have sight of what is inside the encrypted traffic.

So we now know that it is possible to configure the Gateway to secure internal network traffic but, to do that, we will require a certificate.

HTTPS managed by the Gateway

All about certificates

What are certificates and how to get one?

Not sure what certificates are? Don’t panic, let’s start by explaining exactly what they are. We also may refer to them as a Transport Layer Security (TLS) certificate. There is a lot of information on the web that explains exactly how certificates work along with the technical implementation details. We’ve taken the liberty to distill the essence of certificates for the purpose of explaining what they are for this section.

TLS is based on a public / private key concept. It is basically a couple of keys that can only work together (encrypt / decrypt). The public key is what you provide to anybody you want to send you encrypted data. The public key will allow the sender of information to encrypt the data, but they cannot use the same key to decrypt it. Only your private key will be able to do this.

Now, try to think of a certificate as just a type of wrapper that contains the public key, some information about the issuer (who created this certificate), the subject (who will use this certificate, i.e.: the domain name) and an official signature that anyone is able to recognize. To create a real world certificate, you must ask an official Certificate Authority (CA) to apply its official signature. A Certificate Authority is a trusted organization that issues these certificates.

Simplified Certificate creation workflow

Of course, the CA will require that you prove your identity before giving you a certificate for my-domain.com, but that is a story for another day!

How to securely store a certificate?

Let’s summarize what we have so far. We have:

  • A certificate: basically the public key, in a wrapper, officially signed by a Certificate Authority and containing information about the domain my-domain.com that I want to secure the traffic on.
  • A private key: the only key that works with the above certificate that will be used on the Gateway to secure the traffic.

It is more convenient and secure to put these items in a single secured location, protected by a password. Such a location is often called a key store. There are multiple store formats the APIM Gateway supports:

  • JKS: Java Key Store. It is a deprecated format, but still widely used in old java systems.
  • PKCS12: also called P12, it is a de-facto standard, generally used to replace JKS.
Key store

It is also possible to provide the certificate and the private key without bundling them in a key store, but we recommend relying on the PKCS12 key store as much as possible.

You can also store multiple certificates and private keys inside a single key store by defining an alias, allowing you to easily identify each entry.

Multiple certificates

Self-signed certificate

For simplicity, and because real certificates are expensive, you can create your own certificate and private key. This type of certificate is often called a self-signed certificate. Of course, nobody trusts self-signed certificates in real life, and they are mainly used for test purposes.

You can easily generate your own certificate and private key and bundle them in a key store with the following commands:

  1. Generate a fake Certificate Authority
openssl req -newkey rsa:4096 -keyform PEM -keyout ca.key -x509 -days 36500 -subj "/emailAddress=unit.tests@graviteesource.com/CN=unit-tests/OU=GraviteeSource/O=GraviteeSource/L=Lille/ST=France/C=FR" -passout pass:ca-secret -outform PEM -out ca.pem
openssl pkcs12 -export -inkey ca.key -in ca.pem -out ca.p12 -passin pass:ca-secret -passout pass:ca-secret -name ca

2. Generate a self-signed certificate and private key for localhost domain

openssl genrsa -out localhost.key 4096
openssl req -new -key localhost.key -out localhost.csr -sha256 -subj "/emailAddress=unit.tests@graviteesource.com/CN=localhost/OU=GraviteeSource/O=GraviteeSource/L=Lille/ST=France/C=FR"
openssl x509 -req -in localhost.csr -CA ca.pem -CAkey ca.key -set_serial 100 -extensions server -days 36500 -outform PEM -out localhost.cer -sha256 -passin pass:ca-secret

3. Bundle certificate and private key into a PKCS12 key store

openssl pkcs12 -export -inkey localhost.key -in localhost.cer -out localhost.p12 -passout pass:server-secret -name localhost

These commands generate a number of intermediary files. The ones that you are interested in are:

  • localhost.cer: this is your certificate that will be used for exposing HTTPS on your local APIM Gateway.
  • localhost.key: this is your private key.

Here we generated a self-signed certificate manually. However, the Gateway can make our lives easier, and rather than generating the self-signed certificate ourselves, we can allow the Gateway to do this on our behalf. This is especially useful when you want to quickly test HTTPS in a local environment. All you need to do is to specify the following configuration on the APIM Gateway: http.ssl.keystore.type: self-signed.

Getting it all up and running

Configuring the Gateway

Now you have your certificate and your private key bundled into a P12 key store, great! This is the perfect moment to configure the Gateway. The only thing we need to do now is to switch the Gravitee APIM Gateway to secured mode, and provide the key store configuratio:

# Gateway HTTP server
http:
secured: true # Turn on the https
ssl:
keystore:
type: pkcs12
path: ${gravitee.home}/security/localhost.p12
password: server-secret
sni: true # Enable SNI
openssl: true # Used to rely on OpenSSL Engine instead of default JDK SSL Engine

You’ll now need to restart the Gateway. Once restarted, you will notice that all of the deployed APIs are now exposed through HTTPS.

TLS using file key store

Dealing with multiple certificates

By default, if you provide a key store with multiple certificates to the Gateway, only the first certificate will be used. In the previous example, by default, the my-domain.com certificate will be presented even if you try to access the HTTPS://other-domain.com/price-api API.

Bad certificate exposure

So why does this happen? When using the TLS, the secured session needs to be established before the HTTP session, which means the server does not see the Host header until later in the communication process. To make the Gateway able to serve the right certificate, depending on the requested domain, you have to set the http.sni: true option.

SNI (Server Name Indication) is an extension of the TLS handshake, where the TLS communication is initiated with an SNI field to specify the hostname to which to connect. The Gateway can then parse this request and send back the relevant certificate.

Gateway SNI enabled

The Gateway is also able to deal with SAN certificates (Subject Alternative Name). This allows you to expose (and pay for) a single certificate for multiple different domains.

Detecting key store updates

Exposing HTTPS is just as simple as configuring a key store. To do this, specify the path and the secret needed to open the key store.

Once everything is in place and is working well, we will need to make some changes:

  • Renew certificates that will soon expire.
  • Add new certificates for other domains.
  • Replace existing certificates (ex: add a new SAN).
  • And so forth.

By default, the Gateway will watch for any changes on the key store. When changes are detected, the gateway will instantly reload the whole key store and replace the old one without any interruption.

This is rather powerful — you can easily imagine advanced feature such as:

  • Fully automate certificate renewal strategies.
  • Dynamically deploy new API security domain with its own certificate.
  • Extend these capabilities to the trust store in order to dynamically trust client certificates.
  • And much more!

Wait… aren’t we supposed to talk about k8s ?

When dealing with Kubernetes (k8s) installations, the Gateway is able to retrieve the key store directly from Kubernetes. The APIM Gateway currently supports retrieving the key store from either a ConfigMap or a Secret.

It is highly recommended to rely on a Kubernetes Secretinstead of ConfigMap as it offers a stronger security when configured appropriately.

The APIM Gateway can support two different types of secret:

  • Opaque secret: from Kubernetes’s point of view the contents of this Secret is unstructured, it can contain arbitrary key-value pairs.
  • TLS secret: a built-in secret type kubernetes.io/tls for storing a certificate and its associated key that are typically used for TLS. This built-in secret allows only one certificate and private key. If you need to manage multiple certificates you can configure multiple TLS secrets, or you may consider using an Opaque Secret with a key store.
Kubernetes TLS Secret

Basically, to configure https using a Kubernetes secret, you have to provide the http.ssl.keystore.kubernetes setting. This setting is is structured as follows: /{namespace}/{type}/{name}/{key}:

  • namespace: the name of the targeted Kubernetes namespace.
  • type: can be either secret or ConfigMap, depending on the type of Kubernetes resources to retrieve.
  • name: the name of the secret or ConfigMap to retrieve.
  • key: the name of the key holding the value to retrieve. The key is optional when using a standard kubernetes.io/tls secret (note: it only supports PEM cert & key). The key is mandatory for any Opaque secret or ConfigMap (note: they only support JKS & PKC12 key store type).

Using a TLS secret:

You can easily create a TLS secret from a coupled certificate and private key by issuing the following command:

kubectl create secret tls my-tls-secret -n my-namespace — cert=localhost.cer — key=localhost.key

Then, in the Gravitee APIM Gateway config file, you just have to specify the right path to the Kubernetes secret:

# Gateway HTTP server
http:
secured: true # Turn on the https
ssl:
keystore:
kubernetes: /my-namespace/secrets/my-tls-secret
password: server-secret

Multiple certificates using TLS secrets:

# Gateway HTTP server
http:
secured: true # Turn on the https
ssl:
keystore:
kubernetes:
- /my-namespace/secrets/my-tls-secret
- /my-namespace/secrets/my-tls-secret2
password: server-secret

The password used to protect the private key specified for each TLS secret must be the same.

Using Opaque secret:

When using an Opaque Secret, you are constrained to use JKS or PKCS12 key store. The following command creates an opaque secret from the P12 key store:

kubectl create secret -n my-namespace generic my-opaque-secret — from-file=keystore=localhost.p12

Then, the corresponding Gateway configuration will be:

# Gateway HTTP server
http:
secured: true # Turn on the https
ssl:
keystore:
type: pkcs12
kubernetes: /my-namespace/secrets/my-opaque-secret/keystore
password: secret

Wrap up

In this blog post we’ve provided an overview of two common patterns used for API gateways, deferring traffic security to your reverse proxy, and securing internal network traffic, which is used in principles such as zero trust.

We have also provided an introduction to what are certificates, how they are used, and how to create your own for test purposes.

Last but not least, we have shown you how to set up the Gravitee API Management Gateway to secure internal network traffic, including how to manage multiple certificates.

--

--