Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vault-5619: Transit BYOK Documentation #15817

Merged
merged 11 commits into from
Jun 17, 2022
160 changes: 157 additions & 3 deletions website/content/api-docs/secret/transit.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,155 @@ $ curl \
http://127.0.0.1:8200/v1/transit/keys/my-key
```

## Import Key

This endpoint imports existing key material into a new transit-managed encryption key.
To import key material into an existing key, see the `import_version/` endpoint.

### Parameters
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we are missing the context parameter.


- `name` `(string: <required>)` – Specifies the name of the encryption key to
create. This is specified as part of the URL.

- `ciphertext` `(string: <required>)` - A base64-encoded string that contains
two values: an ephemeral AES key wrapped using the wrapping key
returned by Vault and the encryption of the import key material under the
provided AES key. The wrapped AES key should be the first 512 bytes of the
ciphertext, and the encrypted key material should be the remaining bytes.

- `hash_function` `(string: "SHA-256")` - The hash function used for the
Copy link
Contributor

@stevendpclark stevendpclark Jun 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comparing against the code looks like we are expecting non-dashed versions of the hash function names such as SHA256...

Note the same issue exists below for the import version hash_function doc.

RSA-OAEP step of creating the ciphertext. Supported hash functions are:
`SHA-1`, `SHA-224`, `SHA-256`, `SHA-384`, and `SHA-512`. If not specified,
the hash function defaults to SHA-256.

- `type` `(string: <required>)` – Specifies the type of key to create. The
currently-supported types are:

- `aes128-gcm96` – AES-128 wrapped with GCM using a 96-bit nonce size AEAD
(symmetric, supports derivation and convergent encryption)
- `aes256-gcm96` – AES-256 wrapped with GCM using a 96-bit nonce size AEAD
(symmetric, supports derivation and convergent encryption, default)
- `chacha20-poly1305` – ChaCha20-Poly1305 AEAD (symmetric, supports
derivation and convergent encryption)
- `ed25519` – ED25519 (asymmetric, supports derivation). When using
derivation, a sign operation with the same context will derive the same
key and signature; this is a signing analogue to `convergent_encryption`.
- `ecdsa-p256` – ECDSA using the P-256 elliptic curve (asymmetric)
- `ecdsa-p384` – ECDSA using the P-384 elliptic curve (asymmetric)
- `ecdsa-p521` – ECDSA using the P-521 elliptic curve (asymmetric)
- `rsa-2048` - RSA with bit size of 2048 (asymmetric)
- `rsa-3072` - RSA with bit size of 3072 (asymmetric)
- `rsa-4096` - RSA with bit size of 4096 (asymmetric)

- `allow_rotation` `(bool: false)` - If set, the imported key can be rotated
within Vault by using the `rotate` endpoint.

~> **NOTE**: Once an imported key is rotated within Vault, it will no longer
support importing key material with the `import_version` endpoint.

- `derived` `(bool: false)` – Specifies if key derivation is to be used. If
enabled, all encrypt/decrypt requests to this named key must provide a context
which is used for key derivation.

- `exportable` `(bool: false)` - Enables keys to be exportable. This
allows for all the valid keys in the key ring to be exported. Once set, this
cannot be disabled.

- `allow_plaintext_backup` `(bool: false)` - If set, enables taking backup of
named key in the plaintext format. Once set, this cannot be disabled.

- `auto_rotate_period` `(duration: "0", optional)` – The period at which
this key should be rotated automatically. Setting this to "0" (the default)
will disable automatic key rotation. This value cannot be shorter than one
hour.

### Sample Payload

```json
{
"type": "ed25519",
"ciphertext": "..."
}
```

### Sample Request

```shell-session
$ curl \
--header "X-Vault-Token: ..." \
--request POST \
--data @payload.json \
http://127.0.0.1:8200/v1/transit/keys/my-key/import
```

## Import Key Version

This endpoint imports new key material into an existing imported key.

~> **Note**: Keys whose material was generated by Vault do not support
importing key material. Only keys that were previously imported into
Vault can import new key material from an external source.

### Parameters

- `name` `(string: <required>)` – Specifies the name of the encryption key to
create. This is specified as part of the URL.

- `ciphertext` `(string: <required>)` - A base64-encoded string that contains
two values: an ephemeral AES key wrapped using the wrapping key
returned by Vault and the encryption of the import key material under the
provided AES key. The wrapped AES key should be the first 512 bytes of the
ciphertext, and the encrypted key material should be the remaining bytes.
See the BYOK section of the [Transit secrets engine documentation](/docs/secret/transit)
for more information on constructing the ciphertext.

- `hash_function` `(string: "SHA-256")` - The hash function used for the
RSA-OAEP step of creating the ciphertext. Supported hash functions are:
`SHA-1`, `SHA-224`, `SHA-256`, `SHA-384`, and `SHA-512`. If not specified,
the hash function defaults to SHA-256.

### Sample Payload

```json
{
"ciphertext": "..."
}
```

### Sample Request

```shell-session
$ curl \
--header "X-Vault-Token: ..." \
--request POST \
--data @payload.json \
http://127.0.0.1:8200/v1/transit/keys/my-key/import_version
```

## Get Wrapping Key

This endpoint is used to retrieve the wrapping key to use for importing keys.
The returned key will be a 4096-bit RSA public key.

### Sample Request

```shell-session
$ curl \
--header "X-Vault-Token: ..." \
--request GET \
http://127.0.0.1:8200/v1/transit/wrapping_key
```

### Sample Response

```json
{
"data": {
"public_key": "..."
},
}
```

## Read Key

This endpoint returns information about a named encryption key. The `keys`
Expand Down Expand Up @@ -135,7 +284,8 @@ $ curl \
"supports_encryption": true,
"supports_decryption": true,
"supports_derivation": true,
"supports_signing": false
"supports_signing": false,
"imported": false
}
}
```
Expand Down Expand Up @@ -266,6 +416,10 @@ ciphertext to be encrypted with the latest version of the key, use the `rewrap`
endpoint. This is only supported with keys that support encryption and
decryption operations.

~> **Note**: For imported keys, rotation is only supported if the
`allow_rotation` field was set to `true` on import. Once an imported key is
rotated within Vault, it will not support further import operations.

| Method | Path |
| :----- | :--------------------------- |
| `POST` | `/transit/keys/:name/rotate` |
Expand Down Expand Up @@ -398,7 +552,7 @@ will be returned.
all nonces are unique for a given context. Failing to do so will severely
impact the ciphertext's security.

**NOTE:** All plaintext data **must be base64-encoded**. The reason for this
~>**NOTE:** All plaintext data **must be base64-encoded**. The reason for this
requirement is that Vault does not require that the plaintext is "text". It
could be a binary file such as a PDF or image. The easiest safe transport
mechanism for this data as part of a JSON payload is to base64-encode it.
Expand Down Expand Up @@ -668,7 +822,7 @@ This endpoint returns high-quality random bytes of the specified length.
are `hex` or `base64`.

- `source` `(string: "platform")` - Specifies the source of the requested bytes.
`platform`, the default, sources bytes from the platform's entropy source.
`platform`, the default, sources bytes from the platform's entropy source.
`seal` sources from entropy augmentation (enterprise only).
`all` mixes bytes from all available sources.

Expand Down
52 changes: 52 additions & 0 deletions website/content/docs/secrets/transit.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,58 @@ the proper permission, it can use this secrets engine.
data, since the process would not be able to get access to the plaintext
data.

## Bring Your Own Key (BYOK)

~> **Note:** Key import functionality supports cases in which there is a need to bring
in an existing key from an HSM or other outside system. It is more secure to
have Transit generate and manage a key within Vault.

First, the wrapping key needs to be read from transit:

```text
$ vault read transit/wrapping_key
```

The wrapping key will be a 4096-bit RSA public key.

Then the wrapping key is used to create the ciphertext input for the `import` endpoint,
as described below. In the below, the target key refers to the key being imported.

### HSM

If the key is being imported from an HSM that supports PKCS#11, there are
two possible scenarios:

- If the HSM supports the CKM_AES_KEY_WRAP_KWP mechanism, that can be used to wrap the
target key using the wrapping key.

- Otherwise, two mechanisms can be combined to wrap the target key. First, an AES key should
be generated and then used to wrap the target key using the CKM_AES_KEY_WRAP_PAD mechanism.
Then the AES key should be wrapped under the wrapping key using the CKM_RSA_PKCS_OAEP mechanism
using MGF1 and either SHA-1, SHA-224, SHA-256, SHA-384, or SHA-512.

The ciphertext is constructed by appending the wrapped target key to the wrapped AES key.

The ciphertext bytes should be base64-encoded.

### Manual Process

If the target key is not stored in an HSM or KMS, the following steps can be used to construct
the ciphertext for the input of the `import` endpoint:

- Generate an ephemeral AES key.

- Wrap the target key using the ephemeral AES key with AES-KWP.

- Wrap the AES key under the Vault wrapping key using RSAES-OAEP with MGF1 and
either SHA-1, SHA-224, SHA-256, SHA-384, or SHA-512.

- Delete the ephemeral AES key.

- Append the wrapped target key to the wrapped AES key.

- Base64 encode the result.

## Tutorial

Refer to the [Encryption as a Service: Transit Secrets
Expand Down