Skip to content

Latest commit

 

History

History
216 lines (176 loc) · 8.3 KB

SEALED_SECRET.md

File metadata and controls

216 lines (176 loc) · 8.3 KB

Sealed Secrets

Introduction

In Confidential Containers, secrets can be protected with sealing. A sealed secret is a way to encapsulate confidential data such that it can be accessed only inside an enclave in conjunction with an attestation.

The Confidential Data Hub provides an API for unsealing secrets inside of a confidential guest.

You can also use the secret cli tool to generate a sealed secret:

cargo run -p confidential-data-hub --bin secret

Kubernetes Secrets

CoCo’s threat model excludes the Kubernetes Control Plane and Host components from the Trusted Compute Base (TCB). This means that CoCo workloads should not store sensitive data with traditional Kubernetes secrets.

Instead, Kubernetes secrets can be created from sealed secrets, allowing the control plane to orchestrate the secrets without being able to read them. This is shown in detail below.

The Kata Agent, in conjunction with the CDH, can transparently provision these secrets as environment variables.

Comparison to Resource URI

Confidential Containers also uses Resource URIs to refer to secrets. Unlike resource URIs, sealed secrets contain configuration metadata that partially decouples unsealing the secret from the general attestation configuration.

For example, a sealed secret can be unwrapped by an HSM while all other secret resources are fetched from the KBS. Sealed secrets can be used to create complex environments where multiple secrets, fulfilled by different parties, can all travel along with the workload.

Format

There are two main types of sealed secrets.

Envelope

This kind of secret uses envelope encryption scheme. An encryption key is used to encrypt the plaintext secret value. The wrapped secret is stored as part of the sealed secret. To unseal the secret, a KMS/KBS is used to unwrap the encryptd key.

$$Sealed Secret := {Enc_{Sealing key}(Encryption Key), Enc_{Encryption Key}(secret value)}$$

The format of the KMS type Sealed Secret is

{
	"version": "0.1.0",
	"type": "envelope",
	"provider": "xxx",
	"key_id": "xxx",
	"encrypted_key": "ab27dc=",
	"encrypted_data": "xxx",
	"wrap_type": "A256GCM",
	"iv": "xxx",
	"provider_settings": {
		...
	},
	"annotations": {
		...
	}
}

Here,

  • version: REQUIRED. indicates the format version of the Sealed Secret. Currently 0.1.0.
  • type: REQUIRED. MUST be envelope, indicating this is a Envelope type Sealed Secret
  • provider: REQUIRED. indicates the provider of the sealing key. This field determines how to use the annotations field and key_id field to decrypt the encrypted_key
  • key_id: REQUIRED. To uniquely distinguish the sealing key used to encrypt the encryption key, which is always used by the provider driver.
  • encrypted_key: REQUIRED. Encrypted encryption key by the provider. Base64 encoded.
  • encrypted_data: REQUIRED. Encrypted secret value by the encrypted_key. Base64 encoded.
  • wrap_type: REQUIRED. The algorithm used by encryption key to encrypt the secret value. A256GCM (AES256-GCM) preferred.
  • iv: REQUIRED. The Initial Vector used in the process of encryption key encrypting secret value. Base64 encoded.
  • provider_settings: REQUIRED. A key-value map. Provider specific information to create the KMS client.
  • annotations: OPTIONAL. A key-value Map. Provider specific information used by the driver to decrypt encrypted_key into a plaintext of encryption key.

Vault

A vault secret is simply a pointer to a secret that is stored elsewhere, either in a KMS or KBS. To fulfill a vault secret, the CDH will retrieve the secret itself from a secret provider.

Creating a vault secret does not require any encryption. Simply create the metadata below and provision your secret to the provider.

{
	"version" : "0.1.0",
	"type": "vault",
	"provider": "xxx",
	"name": "xxx",
	"provider_settings": {
		...
	},
	"annotations": {
		...
	}
}

Here,

  • version: REQUIRED. indicates the format version of the Sealed Secret. Currently 0.1.0.
  • type: REQUIRED. MUST be vault, indicating this is a Vault type Sealed Secret.
  • provider: REQUIRED. indicates the provider of the secret value. This field determines how to use the annotations field and name field to get the plaintext of secret value.
  • name: REQUIRED. To uniquely distinguish the secret value, which is always used by the provider driver.
  • provider_settings: REQUIRED. A key-value map. Provider specific information to create the vault client.
  • annotations: OPTIONAL. A key-value Map. Vault specific information used by the provider driver to get the plaintext of the secret value.

Integrity Protection of Sealed Secret

Widely used JWS is used to protect the integrity of a Sealed Secret. A Sealed Secret is the payload of a JWS. A signed Sealed Secret is as following

BASE64URL(UTF8(JWS Protected Header)) || '.
    || BASE64URL(JWS Payload) || '.'
    || BASE64URL(JWS Signature)

We can leverage the "kid" field to specify the public key used to verify this signature.

Signatures for secrets are not yet implemented, but sealed secrets are required to have a header and signature. A sealed secret should be of the form

sealed.JWS header.JWS body (secret content).signature

Since signature verification is not yet supported, dummy values can be used for the header and signature. A sealed secret could look like this.

secret=sealed.fakejwsheader.ewogICAgInZlcnNpb24iOiAiMC4xLjAiLAogICAgInR5cGUiOiAidmF1bHQiLAogICAgIm5hbWUiOiAia2JzOi8vL2RlZmF1bHQvc2VhbGVkLXNlY3JldC90ZXN0IiwKICAgICJwcm92aWRlciI6ICJrYnMiLAogICAgInByb3ZpZGVyX3NldHRpbmdzIjoge30sCiAgICAiYW5ub3RhdGlvbnMiOiB7fQp9Cg.fakesignature

Usage in CoCo

You can create a Kubernetes secret from a sealed secret and Kata will automatically expose it to your workload.

Start with a sealed secret such as

{
	"version": "0.1.0",
	"type": "envelope",
	"provider": "xxx",
	"key_id": "xxx",
	"encrypted_key": "ab27dc=",
	"encrypted_data": "xxx",
	"wrap_type": "A256GCM",
	"iv": "xxx",
	"provider_settings": {
		...
	},
	"annotations": {
		...
	}
}

Encode the payload in BASE64URL

ewoJInZlcnNpb24iOiAiMC4xLjAiLAoJInR5cGUiOiAiZW52ZWxvcGUiLAoJInByb3ZpZGVyIjogInh4eCIsCgkia2V5X2lkIjogInh4eCIsCgkiZW5jcnlwdGVkX2tleSI6ICJhYjI3ZGM9IiwgCgkiZW5jcnlwdGVkX2RhdGEiOiAieHh4IiwKCSJ3cmFwX3R5cGUiOiAiQTI1NkdDTSIsCgkiaXYiOiAieHh4IiwKCSJhbm5vdGF0aW9ucyI6IHsKCQkiY3J5cHRvX2NvbnRleHQiOiB7CgkJCSJhbGdvcml0aG0iOiAiQTI1NkdDTSIKCQl9LAoJCSJwcm92aWRlcl9zZXR0aW5nIjogewoJCQkia21zX2luc3RhbmNlX2lkIjogInh4eCIKCQl9Cgl9Cn0

Then add a prefix sealed. and JWS header and signature.

sealed.fakejwsheader.ewoJInZlcnNpb24iOiAiMC4xLjAiLAoJInR5cGUiOiAiZW52ZWxvcGUiLAoJInByb3ZpZGVyIjogInh4eCIsCgkia2V5X2lkIjogInh4eCIsCgkiZW5jcnlwdGVkX2tleSI6ICJhYjI3ZGM9IiwgCgkiZW5jcnlwdGVkX2RhdGEiOiAieHh4IiwKCSJ3cmFwX3R5cGUiOiAiQTI1NkdDTSIsCgkiaXYiOiAieHh4IiwKCSJhbm5vdGF0aW9ucyI6IHsKCQkiY3J5cHRvX2NvbnRleHQiOiB7CgkJCSJhbGdvcml0aG0iOiAiQTI1NkdDTSIKCQl9LAoJCSJwcm92aWRlcl9zZXR0aW5nIjogewoJCQkia21zX2luc3RhbmNlX2lkIjogInh4eCIKCQl9Cgl9Cn0.fakesignature

Create a Kubernetes secret

kubectl create secret generic sealed-secret --from-literal='secret=sealed.fakejwsheader.ewoJInZlcnNpb24i...'

Use this secret in a workload

...
    env:
    - name: PROTECTED_SECRET
      valueFrom:
        secretKeyRef:
          name: sealed-secret
          key: secret

Your secret will be provisioned to the PROTECTED_SECRET environment variable.

Supported Providers

Provider Name README Maintainer
aliyun aliyun Alibaba
ehsm ehsm Intel
kbs CoCo