Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Securing the AtSea App With Docker Secrets

DZone's Guide to

Securing the AtSea App With Docker Secrets

Docker secrets are a great way to pass config info without exposing sensitive data. Let's see how they can be applied to a sample storefront app.

· Cloud Zone ·
Free Resource

See why enterprise app developers love Cloud Foundry. Download the 2018 User Survey for a snapshot of Cloud Foundry users’ deployments and productivity.

Passing application configuration information as environmental variables was once considered best practice in 12-factor applications. However, this practice can expose information in logs, can be difficult to track how and when information is exposed, third-party applications can access this information. Instead of environmental variables, Docker implements secrets to manage configuration and confidential information.

Secrets are a way to keep information such as passwords and credentials secure in a Docker CE or EE with swarm mode. Docker manages secrets and securely transmits it to only those nodes in the swarm that needs access to it. Secrets are encrypted during transit and at rest in a Docker swarm. A secret is only accessible to those services which have been granted explicit access to it, and only while those service tasks are running.

The AtSea Shop is an example storefront application that can be deployed on different operating systems and can be customized to both your enterprise development and operational environments. The previous post showed how to use multi-stage builds to create small and efficient images. In this post, I’ll demonstrate how secrets are implemented in the application.

Creating Secrets

Secrets can be created using the command line or with a Compose file. The AtSea application uses Nginx as a reverse proxy secured with HTTPS. To accomplish this, I created a self-signed x509 certificate.

mkdir certs
openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key -x509 -days 365 -out certs/domain.crt


I then created secrets using the domain key and certificate for Nginx.

docker secret create revprox_cert certs/domain.crt
docker secret create revprox_key certs/domain.key


I also used secrets to hold the PostgreSQL database password and a token for the payment gateway by making files that contained the password and token. For example, the postgres_password file contains the password ‘gordonpass’. In the compose file, I added the secrets:

secrets:
    postgres_password:
        file: ./devsecrets/postgres_password
    payment_token:
        file: ./devsecrets/payment_token


 I then set the database password secret:

database:
    build: 
       context: ./database
    image: atsea_db
    environment:
      POSTGRES_USER: gordonuser
      POSTGRES_DB_PASSWORD_FILE: /run/secrets/postgres_password
      POSTGRES_DB: atsea
    ports:
      - "5432:5432" 
    networks:
      - back-tier
    secrets:
      - postgres_password


And I make the postgres_password secret available to the application server.

appserver:
    build:
       context: .
       dockerfile: app/Dockerfile
    image: atsea_app
    ports:
      - "8080:8080" 
      - "5005:5005"
    networks:
      - front-tier
      - back-tier
    secrets:
      - postgres_password


As you can see, you can set secrets at the command line and programmatically in the compose file.

Docker Enterprise Edition (formerly known as Docker Datacenter) fully incorporates secrets management through creation, update, and removal of secrets. In addition, Docker EE supports authorization, rotation, and auditing of secrets. Creating a secret in Docker Enterprise Edition is accomplished by clicking on the Resources tab and then the Secrets menu item.

Docker secrets

Create the secret by entering the name and the value and clicking Create. In this example, I’m using the secret for the PostgreSQL password in the AtSea application. 

Docker secrets

Docker secrets

Using Secrets

In order to use the Secret containing the certificate for Nginx, I configured the nginx.conf file to point at the secret in the Nginx container.

server {
        listen 443;
        ssl on;
        ssl_certificate /run/secrets/revprox_cert;
        ssl_certificate_key /run/secrets/revprox_key;
        server_name atseashop.com;
        access_log /dev/stdout;
        error_log /dev/stderr;

        location / {
            proxy_pass http://appserver:8080;
        }
    }


The AtSea application uses the postgres_password secret to connect to the database. This is done by reading the secret from the container and setting it to Spring-Boot’s DataSourceProperties class in the JpaConfiguration.java file.

// Set password to connect to postgres using Docker secrets.
try(BufferedReader br = new BufferedReader(new  FileReader("/run/secrets/postgres_password"))) 
{
      StringBuilder sb = new StringBuilder();
      String line = br.readLine();

      while (line != null) {
           sb.append(line);
           sb.append(System.lineSeparator());
           line = br.readLine();
      }
dataSourceProperties.setDataPassword(sb.toString());
      } catch (IOException e) {
         System.err.println("Could not successfully load DB password file");
      } 
return dataSourceProperties;
}


Learn more about Docker secrets:

Cloud Foundry saves app developers $100K and 10 weeks on average per development cycle. Download the 2018 User Survey for a snapshot of Cloud Foundry users’ deployments and productivity. Find out what people love about the industry standard cloud application platform.

Topics:
cloud ,docker secrets ,container security ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}