Skip to main content

Secrets

Secrets are used to provide data that is considered sensitive like passwords, keys, and other sensitive information. Acorn provides multiple secret types, and makes it easy to create closed loop systems where information can be kept within the defined Acorn.

To learn how to use secrets while deploying an Acorn image see Args and Secrets

Using secrets in an Acornfile

Secrets must be defined in the Acornfile. The values can be generated by Acorn or provided by an existing secret in the cluster. Secrets should not be assigned values from user arguments. Secrets can be consumed in containers by referencing them by the secret://<secret_name>/<key> URI syntax.

It is possible to define the behavior when the secret is updated to a new value. The default is to redeploy the containers one at a time. If that operation is unsafe, or requires more user intervention, you can add the ?onchange=no-action to the end of the secret reference URI.

Consume secret in an environment variable

Some containers use environment variables for secret bits of data. The MariaDB container for instance uses an environment variable to set the root password.

containers: {
db: {
image: "mysql"
// ...
env: {
"MYSQL_ROOT_PASSWORD": "secret://db-root-password/token"
}
}
}
// ...
secrets: {
"db-root-password": {
type: "token"
}
}

The example shows the secret db-root-password being consumed as an environment variable in the db container. The secret is of type token and will automatically be generated at runtime by Acorn. The user can then use the Acorn CLI to get the credential if needed.

Consuming secrets in templates

Secrets in templates are wrapped in ${}. It is possible to pass secret configuration data to a container in a pre-rendered form. This next example shows how you can add a configuration file with sensitive data.

containers: {
web: {
image: "nginx"
// ...
files: {
"/etc/nginx/conf.d/website.conf": "secret://website-conf/template"
}
}
}
// ...
secrets: {
"proxy-auth": {
type: "opaque"
data: {
"basic-auth-string": "credentialsgohere"
}
}
"website-conf": {
type: "template"
data: {
template: """
server {
listen 80;
// ...
location / {
// ...
proxy_set_header Authorization "Basic ${secret://proxy-auth/basic-auth-string}"
}
}
"""
}
}
}

The above example has a container that will use the website-conf secret to create a config file. Before rendering the config file, Acorn will substitute the basic-auth-string into the template. This technique makes it possible for the user to pass in the sensitive basic-auth-string at runtime by binding a pre-existing secret.

Populating a directory with files

You can populate a directory with sensitive data using a secret. The example below shows populating the ~/.ssh directory with private keys from a secret.

containers: {
git: {
image: "my-git"
dirs: {
"/home/user/.ssh": "secret://user-provided-ssh-keys"
}
}
}
secrets: {
"user-provided-ssh-keys": {
type: "opaque"
data: {
//Example content from bound secret.
//id_rsa: "-----BEGIN OPENSSH PRIVATE KEY-----...."
//id_rsa_aws: "-----BEGIN OPENSSH PRIVATE KEY-----..."
//Do not put private keys in Acornfile
}
}
}

The above will populate the /home/user/.ssh directory with the content of each item in files named after the key.

# inside the git container
ls /home/user/.ssh
id_rsa id_rsa_aws

Types of secrets

Acorn makes multiple types of secrets available to the Acorn author.

  1. Basic: Used to generate and/or store usernames and passwords.
  2. Template: Used to store configuration files that contain sensitive information.
  3. Token: Used to generate and/or store long secret strings.
  4. Generated: Used to take the output of a job and pass along as a secret bit of info.
  5. Opaque: A generic secret that can store defaults in the Acorn, or is meant to be overriden by the user to pass unknown/unstructured sensitive data.

Basic secrets

Basic secrets are defined in the secrets block with the type "basic".

// ...
secrets: {
"my-creds": {
type: "basic" // required
data: {
username: "" // optional
password: "" // optional
}
}
}

The basic secret type is used for username / password pairs. The key names must be username and password. If one or both of the fields are defined with a non-empty string, those values will be used. If the empty string, the default value, is used Acorn will generate random values for one or both.

Template secrets

The template secret can be used to render and store multiple secret values into a single output. It has the following format:

// ...
secrets: {
"password-file": {
type: "template" // required
data: {
"password.txt": """
password=${secret://token/token}
"""
}
}
"token": {
type: "token"
}
}

In the above example the secret renders a template secret with one key call "password.txt" the token from the secret named "token." See advanced topics for other uses for the template secret type.

Token secrets

Token secrets are useful for generating a password or secure string used for passwords when the user is already known or not required.

secrets: {
"my-token": {
type: "token" // required
params: {
length: 32 // optional
characters: "abcdedfhifj01234567890" // optional
}
}
data: {
token: "" // optional
}
}

The token secret type must be defined. The params allow customization of the generated token. By default tokens are 54 characters in length. By defining the length param the token can be customized to be within 0-256 characters long. The characters param allows the user to define the allowed character values within the token.

The token field in the data object is optional and needs to be left the default empty string if Acorn should generate the token. If the token is defined that value will always be used.

Generated secrets

Generated secrets allow storing sensitive data output from a job.

containers: {
"frontend-proxy": {
// ...
files: {
"/etc/htpasswd": "secret://htpasswd-file/content"
}
// ...
}
}
jobs: {
"htpasswd-create": {
env: {
"USER": "secret://user-creds/username"
"PASS": "secret://user-creds/password"
}
entrypoint: "/bin/sh -c"
image: "httpd:2"
// Output of a generated secret needs to be placed in the file /run/secrets/output.
cmd: ["htpasswd -Bbc /run/secrets/output $USER $PASS"]
}
}
secrets: {
"user-creds": {
type: "basic"
}
"htpasswd-file": {
type: "generated" // required
params: {
job: "htpasswd-create" // required
format: "text" // optional
}
}
}

In the above example, there is a basic secret that Acorn will generate a username and password for. The job will run with the basic secret data passed in as environment variables. When the job runs it will generate an htpasswd file and write the content out to the required /run/secrets/output target. The contents of the /run/secrets/output file will be placed into the secret htpasswd-file and consumed by the frontend-proxy container. The key content must be used when referencing the value.

The job parameter is always required, and is the name of the job that will generate the output. The format parameter is optional and defaults to text.

Opaque secrets

Opaque secrets have no defined structure and can have arbitrary key value pairs. These types of secrets are best used for allowing a user to input sensitive data at runtime. In some cases an unstructured secret can be used if the user will be passing data that will be used in user defined templates. Expected keys should be predefined with reasonable defaults to provide the user some context.

secrets: {
"user-secret-data": {
type: "opaque"
}
}