Using API keys securely in your OpenShift microservices and applications

In the microservices landscape, the API provides an essential form of communication between components. To allow secure communication between microservices components, as well as third-party applications, it's important to be able to consume API keys and other sensitive data in a manner that doesn't place the data at risk. Secret objects are specifically designed to hold sensitive information, and OpenShift makes exposing this information to the applications that need it easy.

In this post, I'll demonstrate securely consuming API keys in OpenShift Enterprise 3. We'll deploy a Sinatra application that uses environment variables to interact with the Twitter API; create a Kubernetes Secret object to store the API keys; expose the secret to the application via environment variables; and then perform a rolling update of the environment variables across our pods.

Prerequisites

For this post, I'm assuming you have access to an OpenShift Enterprise deployment. If you don't have access to OpenShift Enterprise, you can get a local OpenShift 3 deployment with the Red Hat Container Development Kit (CDK)

Application deployment

We're going to use a pre-built Sinatra application to demonstrate interacting with the Twitter API, and you can find the source code on GitHub.  To deploy the app, simply create a new project in your OpenShift project from the GitHub repository:

$ oc new-app https://github.com/jockey10/tripper

Create a route to your application, and list the route in the terminal.

$ oc expose service tripper
$ oc get route

NAME      HOST/PORT             PATH      SERVICE            TERMINATION   LABELS
tripper   <url-to-app>                    tripper:8080-tcp                 app=tripper

 

If you navigate to the application's URL, you'll see that it's up and running. However, any searches return the error "Unable to verify your credentials", as shown below. Time to grab some API keys!

twitter-app-running

Grab some API keys

Our application is deployed and running, but it can't access the Twitter API without any keys. To get a key, navigate to https://apps.twitter.com, and sign in using your Twitter account (create one if required).

Select "Create New App", and give your new app a name, description, and website. You can use a place-holder such as www.example.com for now if you don't have a domain name for your app.

Read the Twitter Developer Agreement, select the checkbox, and then select "Create your Twitter Application".

Once your application has been created you will be redirected to the application management page. Click the "Keys and Access Tokens" tab to view your API keys.

You'll see two keys listed on this page: the consumer key, which identifies your app to the Twitter API, and the secret, which grants your application access. For now, just leave this page open, and we'll create a Kubernetes Secret object with this data.

Create the Secret object

We can use a YAML file to create the Secret object that will hold our API keys.

Firstly, we need to encode our Twitter API keys into base64. We can do this easily using Ruby:

$ irb

irb(main):001:0> require 'base64'
=> true
irb(main):002:0> Base64.strict_encode64('consumer-key-from-twitter')
=> "Y29uc3VtZXIta2V5LWZyb20tdHdpdHRlcg=="
irb(main):003:0> Base64.strict_encode64('secret-key-from-twitter')
=> "c2VjcmV0LWtleS1mcm9tLXR3aXR0ZXI="

 

We can then create a YAML file representing the secret object with these parameters:

#twitter-secrets.yml
apiVersion: v1
kind: Secret
metadata:
name: twitter-secrets
type: Opaque
data:
consumer-key: Y29uc3VtZXIta2V5LWZyb20tdHdpdHRlcg==
secret-key: c2VjcmV0LWtleS1mcm9tLXR3aXR0ZXI=

 

OpenShift objects can be created from a file using the "-f" switch, like so:

$ oc create -f twitter-secrets.yml

To check that the object has been successfully created, you can use the oc command to get a list of Secret objects:

$ oc get secrets
builder-dockercfg-anc66    kubernetes.io/dockercfg               1         15d
builder-token-2fw2w        kubernetes.io/service-account-token   3         15d
builder-token-g7o4y        kubernetes.io/service-account-token   3         15d
default-dockercfg-ni33n    kubernetes.io/dockercfg               1         15d
default-token-b8hh3        kubernetes.io/service-account-token   3         15d
default-token-pwj6b        kubernetes.io/service-account-token   3         15d
deployer-dockercfg-bb0rp   kubernetes.io/dockercfg               1         15d
deployer-token-amtd3       kubernetes.io/service-account-token   3         15d
deployer-token-uc4o0       kubernetes.io/service-account-token   3         15d
twitter-secrets            Opaque                                2         21h

 

Consume the Secret object in your application

Our application is expecting the Twitter API consumer and secret keys to be available in environment variables. To deploy the secrets via environment variables, we need to edit the deployment configuration for our application.

Firstly, we need the name of the deployment configuration.

$ oc get dc

NAME       REVISION   REPLICAS   TRIGGERED BY
tripper    1          1          config,image(tripper:latest)

 

Now that we have a handle to the deployment configuration, we can edit it:

$ oc edit dc tripper

 

We can use the following YAML syntax for the environment variables, indicating they are derived from a Secret object:

env:
- name: TWITTER_KEY
  valueFrom:
    secretKeyRef:
      name: twitter-secrets
      key: consumer-key
- name: TWITTER_SECRET
  valueFrom:
    secretKeyRef:
      name: twitter-secrets
      key: secret-key

 

Simply inject this text into the YAML for the tripper deployment configuration:

apiVersion: v1
kind: DeploymentConfig
metadata:
.
.
.
spec:
.
.
 template:
 .
 .
 spec:
 .
 .
   containers:
   - env:
     - name: TWITTER_KEY
       valueFrom:
         secretKeyRef:
           name: twitter-secrets
           key: consumer-key
     - name: TWITTER_SECRET
       valueFrom:
         secretKeyRef:
           name: twitter-secrets
           key: secret-key
    image:
    imagePullPolicy:
.
.

 

And that's it! Once you save and exit the deployment configuration file, OpenShift will automatically perform a rolling update of the deployment.

Once the update has been performed, you can navigate back to your application see that it's now able to interact with the Twitter API.

screenshot-from-2016-09-27-16-31-19

Thanks for reading!

Last updated: March 20, 2023