Secrets
Set, replace, show and delete your secrets, the secrets of a team, and your own secrets in a team.
Last updated
On this page
Description and operation
General
A secret is a named value in a secret store. There is one store for you, one for each team, and one for you in each team that you are a member of. The name is the key in that store. A value goes into the store and never comes out: no call, list or log returns it. A resource uses a secret through a reference. See Env Vars.
| Part | Description |
|---|---|
| Name | The key of the secret, for example DB_URL. Unique for one owner. |
| Value | The text that a process gets in its variable. It is never shown. |
updated_at | The time of the last change. |
updated_by | The handle of who made the last change. |
You manage secrets with kloudlite secrets (alias kloudlite secret), the SDK or the API. The CLI reads the value only from standard input, never from an argument, because other processes and the shell history can read an argument. It removes one trailing line break, and it refuses an empty value.
| Store | CLI options | Set, replace and delete | Show the names |
|---|---|---|---|
| Your secrets | No --owner, or your handle | You | You |
| Your secrets in a team | --owner TEAM | You, as an active member of the team | You only |
| The secrets of a team | --owner TEAM --scope team | A member with the role admin or higher, whose access is not paused | Any member whose access is not paused |
| Another owner | Nobody. The call fails with 404. | Nobody. The call fails with 404. |
--owner TEAM alone sets YOUR secret in the team. To set the secret that all the team uses, add --scope team. The SDK has the same rule: give scope="team" for the secret of the team.
Your secrets in a team are for your own resources in that team. See Personal secrets in a team.
Parameters
| Parameter | Required | Description |
|---|---|---|
owner | Yes | Your handle or the slug of a team. The CLI uses your handle when you give no --owner. |
scope | No | team for the secret of the team. Without it, a team owner means your own secret in the team. It is refused without a team owner. |
name | Yes | A to Z, 0 to 9 and _. It does not start with a digit. |
value | Yes, to set | Up to 64 KiB (65536 bytes). From standard input in the CLI. |
Lifecycle
- Set. A new name adds a secret. The owner then has it for all its resources. Your secret in a team is for your own resources in that team only.
- Replace. Setting an existing name replaces its value. A workspace or a service that uses the secret gets the new value at its next start. Until then, it shows
restart_required. See When a new value takes effect. - Delete. A delete is refused with
409while a workspace, a sandbox or a service of the owner refers to the secret. The message names each one. A pipeline also stops the delete when its newest version, or a queued or running run, refers to the secret. - Delete your secret in a team. A delete is refused with
409while your resource in the team refers to the name, and the team has no such secret. When the team has the name, the reference reads the secret of the team. - Removed owner. When a team is deleted, its secrets and the secrets of its members in it are deleted. When you leave a team, your secrets in it are deleted after 7 days. If you join again in that time, they are kept.
Quota and limits
| Item | Limit |
|---|---|
| Secrets | 100 for each store. A new name above 100 fails with 409. |
| Value | 64 KiB. |
| Name | A to Z, 0 to 9 and _, not starting with a digit. |
Tasks
Set or replace a secret
Reason for the task: Store a value under a name, or change the value of an existing secret.
Job set-up
- Access: you. For a secret of the team, a team member with the role
adminor higher. - References:
PUT /v1/secrets/{owner}/{name},kloudlite secrets set.
A replaced value does not restart a resource. Restart each resource that shows restart_required to apply the value.
Procedure
Read the value into the shell variable
DB_URL. The terminal does not show what you type.read -rs DB_URL && export DB_URLSend the value of the secret
DB_URLof the teamacme. For your own secret, use your handle and no scope.import osfrom kloudlite import Kloudlitekl = Kloudlite()kl.secrets.set(owner="acme", name="DB_URL", value=os.environ["DB_URL"], scope="team")import { Kloudlite } from "./index.ts";const kl = new Kloudlite();await kl.secrets.set({ owner: "acme", name: "DB_URL", value: process.env.DB_URL!, scope: "team" });kl := kloudlite.New(kloudlite.Options{})if err := kl.Secrets.Set("acme", "DB_URL", os.Getenv("DB_URL"), kloudlite.SecretOptions{Scope: "team"}); err != nil { log.Fatal(err)}require_relative "kloudlite"kl = Kloudlite::Client.newkl.secrets.set(owner: "acme", name: "DB_URL", value: ENV.fetch("DB_URL"), scope: "team")var kl = new Kloudlite();kl.secrets().set("acme", "DB_URL", System.getenv("DB_URL"), "team");printf %s "$DB_URL" | kloudlite secrets set DB_URL --owner acme --scope teamRemove the value from the shell.
unset DB_URL
Close-out
- Show the secrets as in task 002. Make sure that
DB_URLshows the time of this change.
Show the secrets
Reason for the task: Find the names of the secrets of an owner, and who changed each one and when.
Job set-up
- Access: you. For a team, a team member whose access is not paused.
- References:
GET /v1/secrets/{owner},kloudlite secrets list.
Procedure
Show the names of the secrets of the team
acme. The list never holds a value.for s in kl.secrets.list(owner="acme", scope="team"): print(s["name"], s["updated_at"], s["updated_by"])for (const s of await kl.secrets.list({ owner: "acme", scope: "team" })) { console.log(s.name, s.updated_at, s.updated_by);}secrets, err := kl.Secrets.List("acme", kloudlite.SecretOptions{Scope: "team"})if err != nil { log.Fatal(err)}for _, s := range secrets { fmt.Println(s["name"], s["updated_at"], s["updated_by"])}kl.secrets.list(owner: "acme", scope: "team").each do |s| puts "#{s["name"]} #{s["updated_at"]} #{s["updated_by"]}"endSystem.out.println(kl.secrets().list("acme", "team"));kloudlite secrets list --owner acme --scope team
Close-out
- Read the output. The CLI shows
nonefor an owner with no secret.
Delete a secret
Reason for the task: Remove a secret that nothing uses.
Job set-up
- Access: you. For a secret of the team, a team member with the role
adminor higher. - Conditions: no workspace, sandbox, service or pipeline of the owner refers to the secret.
- References:
DELETE /v1/secrets/{owner}/{name},kloudlite secrets delete.
A run of an older pipeline version that names the secret fails to start.
Procedure
Delete the secret
DB_URLof the teamacme.kl.secrets.delete(owner="acme", name="DB_URL", scope="team")await kl.secrets.delete({ owner: "acme", name: "DB_URL", scope: "team" });if err := kl.Secrets.Delete("acme", "DB_URL", kloudlite.SecretOptions{Scope: "team"}); err != nil { log.Fatal(err)}kl.secrets.delete(owner: "acme", name: "DB_URL", scope: "team")kl.secrets().delete("acme", "DB_URL", "team");kloudlite secrets delete DB_URL --owner acme --scope team
Close-out
- Show the secrets as in task 002. Make sure that
DB_URLis not in the list.
Set a personal secret in a team
Reason for the task: Keep your own value, such as an access token, for your resources in a team.
Job set-up
- Access: you, as an active member of the team.
- References:
PUT /v1/secrets/{owner}/mine/{name},kloudlite secrets set.
Your value replaces the secret of the team with the same name, but only in your own workspaces, benches and sandboxes of the team. See Personal secrets in a team.
Procedure
Read the value into the shell variable
GITHUB_TOKEN. The terminal does not show what you type.read -rs GITHUB_TOKEN && export GITHUB_TOKENSend the value. This example sets your secret
GITHUB_TOKENin the teamacme.import osfrom kloudlite import Kloudlitekl = Kloudlite()kl.secrets.set(owner="acme", name="GITHUB_TOKEN", value=os.environ["GITHUB_TOKEN"])import { Kloudlite } from "./index.ts";const kl = new Kloudlite();await kl.secrets.set({ owner: "acme", name: "GITHUB_TOKEN", value: process.env.GITHUB_TOKEN! });kl := kloudlite.New(kloudlite.Options{})if err := kl.Secrets.Set("acme", "GITHUB_TOKEN", os.Getenv("GITHUB_TOKEN")); err != nil { log.Fatal(err)}require_relative "kloudlite"kl = Kloudlite::Client.newkl.secrets.set(owner: "acme", name: "GITHUB_TOKEN", value: ENV.fetch("GITHUB_TOKEN"))var kl = new Kloudlite();kl.secrets().set("acme", "GITHUB_TOKEN", System.getenv("GITHUB_TOKEN"));printf %s "$GITHUB_TOKEN" | kloudlite secrets set GITHUB_TOKEN --owner acmeRemove the value from the shell.
unset GITHUB_TOKEN
Close-out
- Show your secrets in the team as in task 005. Make sure that
GITHUB_TOKENshows the time of this change.
Show your personal secrets in a team
Reason for the task: Find the names of your own secrets in a team.
Job set-up
- Access: you, as an active member of the team.
- References:
GET /v1/secrets/{owner}/mine,kloudlite secrets list.
Procedure
Show the names. The list holds only your names, and never a value.
for s in kl.secrets.list(owner="acme"): print(s["name"], s["updated_at"], s["updated_by"])for (const s of await kl.secrets.list({ owner: "acme" })) { console.log(s.name, s.updated_at, s.updated_by);}secrets, err := kl.Secrets.List("acme")if err != nil { log.Fatal(err)}for _, s := range secrets { fmt.Println(s["name"], s["updated_at"], s["updated_by"])}kl.secrets.list(owner: "acme").each do |s| puts "#{s["name"]} #{s["updated_at"]} #{s["updated_by"]}"endSystem.out.println(kl.secrets().list("acme"));kloudlite secrets list --owner acme
Close-out
- Read the output. The CLI shows
nonewhen you have no secret in the team.
Delete a personal secret in a team
Reason for the task: Remove your own secret in a team.
Job set-up
- Access: you, as an active member of the team.
- Conditions: none of your resources in the team refers to the name, or the team has a secret of that name.
- References:
DELETE /v1/secrets/{owner}/mine/{name},kloudlite secrets delete.
When the team has a secret of that name, your resources read the value of the team at their next start.
Procedure
Delete your secret
GITHUB_TOKENin the teamacme.kl.secrets.delete(owner="acme", name="GITHUB_TOKEN")await kl.secrets.delete({ owner: "acme", name: "GITHUB_TOKEN" });if err := kl.Secrets.Delete("acme", "GITHUB_TOKEN"); err != nil { log.Fatal(err)}kl.secrets.delete(owner: "acme", name: "GITHUB_TOKEN")kl.secrets().delete("acme", "GITHUB_TOKEN");kloudlite secrets delete GITHUB_TOKEN --owner acme
Close-out
- Show your secrets in the team as in task 005. Make sure that
GITHUB_TOKENis not in the list.
Troubleshooting
| Symptom | Possible cause | Corrective action |
|---|---|---|
the value is empty: pipe it in on stdin, e.g. ... | The value on standard input is empty. | Make sure that the variable holds the value, then set the secret again. |
422 with `db-url` is not a secret name: use A-Z, 0-9 and _, not starting with a digit | The name has lowercase letters, a hyphen or a leading digit. | Use a name such as DB_URL. |
422 with a secret value is at most 64 KiB | The value is larger than 65536 bytes. | Use a smaller value. |
409 with secrets: 100 of 100 in use | The owner has 100 secrets and the name is new. | Delete a secret that you do not use. |
409 with secrets are being changed; try again | Another change to the secrets of the owner ran at the same time. | Do the task again. |
409 with DB_URL is referenced by environment dev service api, workspace api | A resource still refers to the secret. | Remove the reference from each resource named, then delete again. |
403 with your access to acme is paused | An admin paused your access. | Ask a team admin to restore your access. |
404 with not found | The team or the secret does not exist, or you are not in the team (or you left it). | Check the value of --owner and the name. |
--scope team is the team's shared secret: pass --owner TEAM (your own handle has no team) | You gave --scope team with no team --owner. | Add --owner and the slug of the team. |
403 with only a team admin can change team secrets after --scope team | You tried to change the secret of the team, and your role is lower than admin. | Ask a team admin. For a value that only you use, set your own secret in the team. |
A secret that you set with --owner acme is not in the list of the team | Without --scope team, the secret is yours in the team. | Show your secrets in the team. To share the secret, set it with --scope team. |
409 with DB_URL is referenced by workspace api after a delete of your secret in a team | Your workspace refers to the name, and the team has no secret of that name. | Remove the reference from the workspace, then delete again. |