Open phoban01 opened 1 year ago
@phoban01 thanks for the proposal, this looks great to me.
Can you please include Bundles, as stated in the docs, Bundles are preferred over using Values and imperative commands.
@stefanprodan Updated proposal to take bundles into account.
I just started looking into timoni and was wondering what the status of sops integration is.
Is this proposal proceeding right now ?
Thank you
Is this proposal proceeding right now ?
This is a not top priority right now, or at least I personally have no plans to work on this in the near future. Decryption within the Timoni CLI has little value, it would make more sense to implement this for the timoni-controller, when that will be a thing.
Currently there are several ways of injecting secrets at apply time in Timoni Bundles using runtime attributes @timoni(runtime:string:SECRET-NAME)
(docs here: https://timoni.sh/bundle-runtime/).
When using a CI runner to deploy apps with Timoni, you can pass secrets from the runner secret store to Timoni's Bundles.
Example of a bundle that injects the GIT_TOKEN
secret:
bundle: {
apiVersion: "v1alpha1"
name: "flux-aio"
instances: {
"cluster-addons": {
module: url: "oci://ghcr.io/stefanprodan/modules/flux-git-sync"
namespace: "flux-system"
values: git: {
token: string @timoni(runtime:string:GIT_TOKEN)
url: "https://github.com/my-org/my-private-repo"
ref: "refs/head/main"
path: "./test/cluster-addons"
}
}
}
}
In a GitHub workflow, you can map secrets from GitHub secrets to env vars, that Timoni will use at apply-time:
export GIT_TOKEN=${{ secrets.GITHUB_TOKEN }}
timoni bundle apply -f flux-aio.cue --runtime-from-env
The same GIT_TOKEN
from the above example, can be injected from a Kubernetes Secret, assuming you're using some external-secret controller that syncs secrets from a Vault in etcd.
Example of a Timoni bundle runtime that fetches the GIT_TOKEN
from the cluster:
runtime: {
apiVersion: "v1alpha1"
name: "production"
values: [
{
query: "k8s:v1:Secret:infra:git-auth"
for: {
"GIT_TOKEN": "obj.data.token"
"GIT_CA": "obj.data.\"ca.crt\""
}
},
]
}
At apply-time you pass the runtime definition and Timoni will read the secret from the cluster and use it when applying the bundles:
timoni bundle apply -f flux-aio.cue --runtime runtime.cue
When using SOPS, you can decrypt the secrets and pipe those values to env vars then use --runtime-from-env
.
Another option is to extract the secret values of a Timoni Bundle to an YAML file, that you encrypt/decrypt with SOPS.
Main bundle file bundle.main.cue
:
bundle: {
apiVersion: "v1alpha1"
name: "flux-aio"
instances: {
"cluster-addons": {
module: url: "oci://ghcr.io/stefanprodan/modules/flux-git-sync"
namespace: "flux-system"
values: git: {
// The token is omitted here!
url: "https://github.com/my-org/my-private-repo"
ref: "refs/head/main"
path: "./test/cluster-addons"
}
}
}
}
Bundle partial in YAML format bundle.secret.yaml
:
bundle:
instances:
cluster-addons:
values:
git:
token: my-token
Assuming the bundle.secret.yaml
file is kept encrypted with SOPS, at apply-time you can run the SOPS decryption, and pass the plain YAML to Timoni's apply command like so:
sops -d bundle.secret.yaml > bundle.secret.plain.yaml
timoni bundle apply -f bundle.main.cue -f bundle.secret.plain.yaml
rm bundle.secret.plain.yaml
Thanks !!
Tomorrow I will have a look, if this is not in the docs I will add it
Context
The following is a proposal for supporting the encryption of Timoni values (based on prior art, see: https://github.com/phoban01/cue-sops).
The proposal was first mooted in #71.
Proposal
Timoni enables the encryption of sensitive values via built-in SOPS support.
Given the following config definition:
A values file providing an API key is marked as sensitive using the
@secret()
annotation:The plaintext value can then be encrypted in-place:
timoni encrypt -f api-values.cue
This will produce the following result:
Timoni will decrypt values before applying an instance to the cluster:
Timoni can also decrypt a file in-place:
timoni decrypt -f api-values.cue
Encrypt multiple fields
To encrypt all fields in a file (optionally matching field names via regex), it is possible to use a global annotation:
SOPS configuration
It is possible to specify the encryption service used by SOPs per field:
It is also possible to define encryption service providers globally using the
@sops()
annotation. Providers can subsequently be referenced using labels:If a single
@sops()
annotation is present then labels can be omitted and the specified service will be used to encrypt all values:Bundles
Values provided in a Bundle may also be encrypted. Encryption services can be defined as part of the bundle spec and then referenced by name in the
@secret
annotation.To encrypt a bundle use the bundle encrypt subcommand:
Sensitive values will be automatically decrypted when the bundle is applied:
Timoni bundle diffs will decrypt both previous and current sensitive values and display the diff in cleartext: