Skip to main content
Version: v0.13

Secrets

Secrets are used to store sensitive data like passwords, API keys, TLS certificates, tokens, or other credentials. Kusion provides multiple secret types, and makes it easy to be consumed in containers.

For application dependent cloud resources that are managed by Kusion, their credentials are automatically managed by Kusion (generated and injected into application runtime environment variable). You shouldn't have to manually create those.

Using secrets in workload

Secrets must be defined in AppConfiguration. The values can be generated by Kusion or reference existing secrets stored in third-party vault. Secrets can be consumed in containers by referencing them through the secret://<secret_name>/<key> URI syntax.

Consume secret in an environment variable

You can consume the data in Secrets as environment variable in your container. For example the db container uses an environment variable to set the root password.

import kam.v1.app_configuration as ac
import service
import service.container as c
import service.secret as sec

sampledb: ac.AppConfiguration {
workload: service.Service {
containers: {
"db": c.Container {
image: "mysql"
env: {
# Consume db-root-password secret in environment
"ROOT_PASSWORD": "secret://db-root-password/token"
}
}
}
# Secrets used to generate token
secrets: {
"init-info": sec.Secret {
type: "token"
}
}
}
}

The example shows the secret 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 Kusion.

Consume all secret keys as environment variables

Sometimes your secret contains multiple data that need to be consumed as environment variables. The example below shows how to consume all the values in a secret as environment variables named after the keys.

import kam.v1.app_configuration as ac
import service
import service.container as c
import service.secret as sec

sampledb: ac.AppConfiguration {
workload: service.Service {
containers: {
"db": c.Container {
image: "mysql"
env: {
# Consume all init-info secret keys as environment variables
"secret://init-info": ""
}
}
}
# Secrets used to init mysql instance
secrets: {
"init-info": sec.Secret {
type: "opaque"
data: {
"ROOT_PASSWORD": "admin"
}
}
}
}
}

This will set the environment variable "ROOT_PASSWORD" to the value "admin" in the db container.

Types of secrets

Kusion provides multiple types of secrets to application developers.

  1. Basic: Used to generate and/or store usernames and passwords.
  2. Token: Used to generate and/or store secret strings for password.
  3. Opaque: A generic secret that can store arbitrary user-defined data.
  4. Certificate: Used to store a certificate and its associated key that are typically used for TLS.
  5. External: Used to retrieve secret form third-party vault.

Basic secrets

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

import kam.v1.app_configuration as ac
import service
import service.container as c
import service.secret as sec

sampleapp: ac.AppConfiguration {
workload: service.Service {
# ...
secrets: {
"auth-info": sec.Secret {
type: "basic"
data: {
"username": "admin"
"password": "******"
}
}
}
}
}

The basic secret type is typically used for basic authentication. 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.

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.

import kam.v1.app_configuration as ac
import service
import service.container as c
import service.secret as sec

sampleapp: ac.AppConfiguration {
workload: service.Service {
# ...
secrets: {
"api-token": sec.Secret {
type: "token"
data: {
"token": "<the_api_token>"
}
}
}
}
}

The token secret type must be defined. The token field in the data object is optional and if left empty Kusion will generate the token, which is 54 characters in length by default. If the token is defined that value will always be used.

Opaque secrets

Opaque secrets have no defined structure and can have arbitrary key value pairs.

import kam.v1.app_configuration as ac
import service
import service.container as c
import service.secret as sec

sampleapp: ac.AppConfiguration {
workload: service.Service {
# ...
secrets: {
"my-secret": sec.Secret {
type: "opaque"
}
}
}
}

Certificate secrets

Certificate secrets are useful for storing a certificate and its associated key. One common use for TLS Secrets is to configure encryption in transit for an Ingress, but you can also use it with other resources or directly in your workload.

import kam.v1.app_configuration as ac
import service
import service.container as c
import service.secret as sec

sampleapp: ac.AppConfiguration {
workload: service.Service {
# ...
secrets: {
"server-cert": sec.Secret {
type: "certificate"
data: {
# Please do not put private keys in configuration files
"tls.crt": "The cert file content"
"tls.key": "The key file content"
}
}
}
}
}

External secrets

As a general principle, storing secrets in a plain text configuration file is highly discouraged, keeping secrets outside of Git is especially important for future-proofing, even encrypted secrets are not recommended to check into Git. The most common approach is to store secrets in a third-party vault (such as Hashicorp Vault, AWS Secrets Manager and Azure Key Vault, etc) and retrieve the secret in the runtime only. External secrets are used to retrieve sensitive data from external secret store to make it easy to be consumed in containers.

import kam.v1.app_configuration as ac
import service
import service.container as c
import service.secret as sec

sampleapp: ac.AppConfiguration {
workload: service.Service {
# ...
secrets: {
"api-access-token": sec.Secret {
type: "external"
data: {
# Please do not put private keys in configuration files
"accessToken": "ref://api-auth-info/accessToken?version=1"
}
}
}
}
}

The value field in data object follow ref://PATH[?version=<VERSION>] URI syntax. PATH is the provider-specific path for the secret to be retried. Kusion provides out-of-the-box integration with Hashicorp Vault, AWS Secrets Manager, Azure Key Vault and Alicloud Secrets Manager.

Immutable secrets

You can also declare a secret as immutable to prevent it from being changed accidentally.

To declare a secret as immutable:

import kam.v1.app_configuration as ac
import service
import service.container as c
import service.secret as sec

sampleapp: ac.AppConfiguration {
workload: service.Service {
# ...
secrets: {
"my-secret": sec.Secret {
# ...
immutable: True
}
}
}
}

You can change a secret from mutable to immutable but not the other way around. That is because the Kubelet will stop watching secrets that are immutable. As the name suggests, you can only delete and re-create immutable secrets but you cannot change them.