Skip to main content

cloider_registry_token resource (Terraform)

The cloider_registry_token resource creates a registry token: a password that pushes and pulls images of some or all of your registry projects. You log in with docker login registry.cloider.com -u <username> -p <secret>. A token can be limited to pulling, and can expire after a number of days.

At a glance​

Required argumentslabel, and either projects or all_projects = true
Changes in placelabel, projects, all_projects, read_only
Changes that replace the tokenexpires_in_days
Sensitive attributessecret
TimeoutsNone, tokens are created immediately
Import IDThe token id
API/api/registry/tokens
CLI equivalentcloider registry token
The secret is only shown once

Cloider shows a token's secret only when the token is created, and Terraform saves it in state at that moment. An imported token has no secret. To have the secret in Terraform, create a new token with Terraform.

Example usage​

A push token for one project​

main.tf
resource "cloider_registry" "acme" {
name = "acme"
}

resource "cloider_registry_token" "ci" {
label = "CI push"
projects = [cloider_registry.acme.id]
}

output "registry_username" {
value = cloider_registry_token.ci.username
}

output "registry_password" {
value = cloider_registry_token.ci.secret
sensitive = true
}
terraform output -raw registry_password | docker login registry.cloider.com -u "$(terraform output -raw registry_username)" --password-stdin

--password-stdin keeps the secret out of your shell history.

A pull only token for every project​

main.tf
resource "cloider_registry_token" "pull_all" {
label = "clusters pull"
all_projects = true
read_only = true
}

all_projects = true includes projects created later.

Create an image pull secret in a cluster​

With the kubernetes provider configured from a cloider_cluster, a read only token becomes a kubernetes.io/dockerconfigjson Secret that pods reference in imagePullSecrets:

main.tf
resource "cloider_registry_token" "pull" {
label = "production cluster pull"
projects = [cloider_registry.acme.id]
read_only = true
}

resource "kubernetes_secret_v1" "registry" {
metadata {
name = "cloider-registry"
namespace = "default"
}

type = "kubernetes.io/dockerconfigjson"

data = {
".dockerconfigjson" = jsonencode({
auths = {
(cloider_registry.acme.host) = {
username = cloider_registry_token.pull.username
password = cloider_registry_token.pull.secret
auth = base64encode("${cloider_registry_token.pull.username}:${cloider_registry_token.pull.secret}")
}
}
})
}
}
deployment.yaml (excerpt)
spec:
template:
spec:
imagePullSecrets:
- name: cloider-registry
containers:
- name: web
image: registry.cloider.com/acme/web:1.4.2

See Pull private images.

Hand the token to GitHub Actions​

With the integrations/github provider:

main.tf
resource "github_actions_secret" "registry_username" {
repository = "web"
secret_name = "CLOIDER_REGISTRY_USERNAME"
plaintext_value = cloider_registry_token.ci.username
}

resource "github_actions_secret" "registry_password" {
repository = "web"
secret_name = "CLOIDER_REGISTRY_PASSWORD"
plaintext_value = cloider_registry_token.ci.secret
}

Rotate a token automatically​

expires_in_days can't change in place, and the secret can't be changed at all, so rotation means replacing the token. With the time provider's time_rotating, Terraform replaces the token every 90 days, a month before it would expire, and creates the new token before deleting the old one:

main.tf
resource "time_rotating" "ci" {
rotation_days = 90
}

resource "cloider_registry_token" "ci" {
label = "CI push"
projects = [cloider_registry.acme.id]
expires_in_days = 120

lifecycle {
create_before_destroy = true
replace_triggered_by = [time_rotating.ci]
}
}

Rotation happens on the first terraform apply after the 90 days are up, so run Terraform regularly (for example from a scheduled CI job). Anything that holds the secret, such as the GitHub secret or the Kubernetes Secret above, is updated in the same apply when it refers to cloider_registry_token.ci.secret.

To rotate by hand, run terraform apply -replace=cloider_registry_token.ci.

Argument reference​

ArgumentTypeRequiredDefaultChanging itDescription
labelStringYesIn placeWhat the token is for
projectsSet of StringOne of projects or all_projectsIn placeThe ids of the cloider_registry projects the token reaches, at least one
all_projectsBoolOne of projects or all_projectsfalseIn placeWhether the token reaches every project, those created later included
read_onlyBoolNofalseIn placeWhether the token may only pull. false allows pushing and pulling
expires_in_daysNumberNo0Replaces the tokenDays until the token stops working, 1 to 3650, or 0 for never

Setting both projects and all_projects = true fails with Conflicting scope: all_projects and projects don't go together. Setting neither fails with Missing scope: Set projects, or all_projects = true.

Attribute reference​

AttributeTypeSensitiveDescription
idStringNoThe token's id
usernameStringNoThe username to log in with. It is your account's registry username, the same for every token of the account
secretStringYesThe password to log in with. Only known for a token this configuration created, null after an import
expires_atStringNoWhen the token stops working, in RFC 3339. Null for a token that never expires
created_atStringNoWhen the token was created, in RFC 3339

Behavior notes​

  • In place changes keep the secret. Changing label, projects, all_projects or read_only updates the token without changing its secret, so whoever uses it keeps working.
  • Expiry is fixed. Cloider stores when a token expires, not the number of days, so expires_in_days can't change in place. Changing it creates a new token with a new secret.
  • Expired tokens stop working but stay in state. Replace them, or use the rotation example above.
  • Deleted outside Terraform. The next refresh removes the token from state and the plan creates a new one, with a new secret.

Import​

Import an existing token by its id. cloider registry token list -o wide shows the ids:

cloider registry token list -o wide

With an import block:

imports.tf
import {
to = cloider_registry_token.pull_all
id = "TOKEN_ID"
}

With the terraform import command:

terraform import cloider_registry_token.pull_all TOKEN_ID

Replace TOKEN_ID with the value of the ID column. On import, the provider works out expires_in_days from the token's creation and expiry times, rounded to whole days. The imported token has secret = null.

Frequently asked questions

How do I log in to the Cloider registry with a Terraform created token?

Use the token's username and secret attributes: docker login registry.cloider.com -u <username> --password-stdin, piping the secret in. Expose secret as a sensitive output and read it with terraform output -raw.

How do I create a Kubernetes image pull secret for the Cloider registry in Terraform?

Create a read only cloider_registry_token and a kubernetes_secret_v1 of type kubernetes.io/dockerconfigjson whose .dockerconfigjson has an auths entry for registry.cloider.com with the token's username and secret.

Can I change a registry token's expiry with Terraform?

Not in place. Changing expires_in_days replaces the token with a new one, which has a new secret.

Why is the username the same for all my registry tokens?

The username is your account's registry username, shared by every token of the account. The secret is what identifies each token.