Georg Kalus
/

Scaleway Secret Types Decoded

Scaleway Secret Manager

The Scaleway Secret Manager allows us to define a type for a secret. This type determines the required formatting of the secret data when writing it and how it will be interpreted when reading it.

The following Scaleway secret types are available:

  • Opaque: this secret type is used for storing any kind of sensitive data. This is the default if no type is given when creating a secret.
  • Key/value: this secret type is used to store arbitrary values in a simple dictionary-like structure, where each secret is represented as a key-value pair.
  • Basic credentials: this secret type is used for authentication purposes. It typically includes two pieces of information: a username and a corresponding password. The username property is optional.
  • Database credentials: this secret type is used to store and manage the credentials required for accessing a database. The properties are username, password, engine, host, database name, port. All properties are required.
  • SSH key: this secret type is used to store SSH keys. Only the private key is required.
  • SSL/TLS certificate: this secret type is used to store and manage SSL/TLS certificates, which are used to establish secure, encrypted connections between clients and servers over the internet. The value is a chain of PEM blocks.

The secret type must be specified when creating the secret. It cannot be changed afterwards and applies to all versions of the secret.

More information on other features of the Secret Manager, for example about scheduled deletion, secret protection, and ephemeral secrets, can be found in the Scaleway Documentation about Secret Manager Concepts.

The JSON formats of all secret types is also described here: Scaleway documentation: Understanding secret types.

Let’s go through the Scaleway secret types one by one.

Secret Type: Opaque

The opaque secret type is the default option when no specific type is provided. It essentially indicates that the secret data can be in any arbitrary format.

Create an Opaque Secret with Terraform

When creating a secret with Terraform, the data can be any string (with a maximum length of 64KiB).

secret_opaque.tf
resource "scaleway_secret" "secret_test_opaque" {
  name        = "test-opaque"
  path        = "/terraform-test" 
  description = "A test secret of opaque type"
  type        = "opaque"
  tags        = ["terraform", "test"]
}

resource "scaleway_secret_version" "secret_test_opaque_v1" {
  description = "V1 of the opaque secret"
  secret_id   = scaleway_secret.secret_test_opaque.id
  data        = "Hello, this is a test secret!"
}

Create an Opaque Secret with CLI

Creating an opaque secret with the Scaleway CLI follows the same pattern:

secret_opaque.sh
id=$(scw secret secret create path="/cli-test" name="test-opaque" tags.0="cli" tags.1="test" description="A test secret of opaque type" -o json | jq -r '.id')
  
scw secret version create $id data="Hello, this is a test secret!"

Similar to Terraform, there are two CLI calls necessary to create a secret with data. The first call creates the secret itself, including it’s type, tags, description and other properties.

The second command creates a version holding the actual secret data. When a secret is rotated, the secret itself remains unchanged. Only a new version is created.

Create an Opaque Secret with API

When creating a secret through the API, the pattern remains: One API call for creating the secret itself and a second call for creating the secret version with data.

secret_opaque.sh
curl -q \
  -H "X-Auth-Token: $SECRET_KEY" \
  -H 'Content-Type: application/json' \
  -X POST \
  -d '{
        "name": "my-secret",
        "project_id": "'$SCW_PROJECT_ID'",
        "type": "opaque"
  }' \
  https://api.scaleway.com/secret-manager/v1beta1/regions/fr-par/secrets
  
curl "https://api.scaleway.com/secret-manager/v1beta1/regions/$REGION/secrets/<SECRET_ID>/versions" \
  -H "X-Auth-Token: $SCW_SECRET_KEY" \
  -d "Hello, this is a test secret!"

Secret Type: Key-Value

The Key-Value secret type expects the secret data to be formatted as a json-formatted key-value list.

Create a Key-Value Secret with Terraform

secret_key_value.tf
resource "scaleway_secret" "secret_test_key_value" {
  name        = "test-key-value"
  path        = "/terraform-test" 
  description = "A test secret of key_value type"
  type        = "key_value"
  tags        = ["terraform", "test"]
}

resource "scaleway_secret_version" "secret_test_key_value_v1" {
  description = "V1 of the key_value secret"
  secret_id   = scaleway_secret.secret_test_key_value.id
  data        = jsonencode({
    key1 = "value1",
    key2 = "value2"
  })
}

The following image shows a key-value secret value in the Scaleway Console.

Secret type Key-Value in Scaleway Console.

Create a Key-Value Secret with CLI

Creating a key-value secret with the Scaleway CLI looks exactly the same as with the opaque secret type. The only difference is the value of the type property and the value of the data property when creating the version.

secret_key_value.sh
id=$(scw secret secret create path="/cli-test" name="test-key-value" type="key_value" tags.0="cli" tags.1="test" description="A test secret of key_value type" -o json | jq -r '.id')
  
scw secret version create $id data="{ \"key1\": \"value\", \"key2\": \"value\" }"

Secret Type: Basic Credentials

Basic credentials look almost the same as the key-value secret type. The speciality here is that the keys must be username and password. The username property is optional, so you can create a basic credential secret with only setting the password.

secret_basic_credentials.tf
resource "scaleway_secret" "secret_test_basic_credentials" {
  name        = "test-basic-credentials"
  path        = "/terraform-test" 
  description = "A test secret of basic_credentials type"
  type        = "basic_credentials"
  tags        = ["terraform", "test"]
}

resource "scaleway_secret_version" "secret_test_basic_credentials_v1" {
  description = "V1 of the Basic-Credentials secret"
  secret_id   = scaleway_secret.secret_test_basic_credentials.id
  data        = jsonencode(
    {
      username = "bobbytables",
      password = "passw0rd"
    }
  )
}

When creating a secret through the API, we are Base64 encoding the data value ourselves.

secret_basic_credentials.sh
curl "https://api.scaleway.com/secret-manager/v1beta1/regions/$REGION/secrets" \
  -H "Content-Type: application/json" \
  -H "X-Auth-Token: $SCW_SECRET_KEY" \
  -d '{
    "name": "my-secret",
    "type": "basic_credentials",
    "project_id": "$PROJECT_ID"
  }
  
curl "https://api.scaleway.com/secret-manager/v1beta1/regions/$REGION/secrets/<SECRET_ID>/versions" \
  -H "Content-Type: application/json" \
  -H "X-Auth-Token: $SCW_SECRET_KEY" \
  -d '{
   "data": "'"$(echo -n "{\"username\": \"bobbytables\", \"password\": \"passw0rd\"}" | base64)"'"}'

Secret Type: Database Credentials

The database credentials secret type is a key-value type again with a set of expected keys. Good to know about the values in the database credentials type is that the value of port must be a string containing a number.

secret_database_credentials.tf
resource "scaleway_secret" "secret_test_database_credentials" {
  name        = "test-database-credentials"
  path        = "/terraform-test" 
  description = "A test secret of Database-Credentials type"
  type        = "database_credentials"
  tags        = ["terraform", "test"]
}

resource "scaleway_secret_version" "secret_test_database_credentials_v1" {
  description = "V1 of the Database-Credentials secret"
  secret_id   = scaleway_secret.secret_test_database_credentials.id
  data        = jsonencode(
    {
      engine   = "value",
      username = "value",
      password = "value",
      host     = "value",
      dbname   = "value",
      port     = "1234"
    }
  )
}

Below is a screenshot of the Terraform output if the data is not correctly formatted. As you can see, all properties are expected and unrecognized properties are not allowed.

Scaleway Database Credentials secret with wrong data.

Secret Type: SSH Key

The SSH Key secret type is expecting a property called ssh_private_key.

secret_ssh_key.tf
resource "scaleway_secret" "secret_test_ssh_key" {
  name        = "test-ssh-key"
  path        = "/terraform-test" 
  description = "A test secret of SSH-Key type"
  type        = "ssh_key"
  tags        = ["terraform", "test"]
}

resource "scaleway_secret_version" "secret_test_ssh_key_v1" {
  description = "V1 of the SSH-Key secret"
  secret_id   = scaleway_secret.secret_test_ssh_key.id
  data        = "{\"ssh_private_key\": \"value\"}"
}

Secret Type: Certificate

The Certificate secret type expects a chain of PEM blocks.

secret_certificate.tf
resource "scaleway_secret" "secret_test_certificate" {
  name        = "test-certificate"
  path        = "/terraform-test" 
  description = "A test secret of Certificate type"
  type        = "certificate"
  tags        = ["terraform", "test"]
}

resource "scaleway_secret_version" "secret_test_certificate_v1" {
  description = "V1 of the Certificate secret"
  secret_id   = scaleway_secret.secret_test_certificate.id
  data        = <<EOF
-----BEGIN OPENSSH PRIVATE KEY-----
1111111111111111111111111111111111111111111111111111111111111111111111
3333333333333333333333333333333333333333333333333333333333333333333333
3333333333333333333333333333333333333333333333333333333333333333333333
7777777777777777777777777777777777777777777777777777777777777777777777
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-----END OPENSSH PRIVATE KEY-----
EOF
}

Conclusion

The Scaleway secret types are not absolutely necessary, as we could keep track of the formatting of secret values ourselves. They are however a nice feature that makes sure that secret values adhere to the expected format.

To top