Nitro Enclave Signer
Nitro backend is used in conjunction with enclave-signer, its counterpart running inside AWS Nitro Enclave, a fortified container with no persistent storage and no connection to the outside world other than bidirectional hypervisor-local VSock link to its parent instance.
All keys imported into enclave-signer
or generated by it never leave the enclave in a plain text form. As the enclave has no storage all sensitive data is stored by the parent instance in encrypted form. The keystone of this model is a carefully chosen KMS policy which permits the decryption of such a data only by an actor possessing a signed attestation document generated by a hypervisor i.e. a code running inside the enclave. All TLS encrypted requests to KMS made by a code running inside the enclave are tunneled over VSock link to the parent and forwarded to the cloud by a proxy service (see below).
Prerequisites
Please refer to kmstool and enclave-signer documentation for KMS setup procedure. One must obtain an ID of a KMS symmetrical key tied to the enclave attestation document (or its zero placeholder if a debug mode is expected).
Configuration
Field | Environment variable | Type | Default | Required | Description |
---|---|---|---|---|---|
enclave_cid | ENCLAVE_CID | uint | ✅ | Context ID of an enclave running enclave-signer . It's changing on every restart of an enclave | |
enclave_port | ENCLAVE_PORT | uint | 2000 | Listening VSock port of enclave-signer | |
encryption_key_id | ENCRYPTION_KEY_ID | string | ✅ | KMS key ARN or ID used by enclave to decrypt private keys | |
storage | StorageConfig | Key storage configuration | |||
credentials | Credentials | KMS credentials | |||
proxy_local_port | PROXY_LOCAL_PORT | uint | 8000 | Local VSock port for the built in VSock proxy | |
proxy_remote_address | PROXY_REMOTE_ADDRESS | host:port | Setting this option enables the built in VSock proxy (see below). Usually it looks like "kms.${REGION}.amazonaws.com:443" |
Credentials
Field | Environment variable | Type |
---|---|---|
access_key_id | AWS_ACCESS_KEY_ID | string |
secret_access_key | AWS_SECRET_ACCESS_KEY | string |
session_token | AWS_SESSION_TOKEN | string |
region | AWS_REGION | string |
Credentials block is optional. If the user has a properly configured access to AWS the client code will pick it automatically.
StorageConfig
Encrypted keys may be stored locally or in AWS DynamoDB.
Field | Type | Description |
---|---|---|
driver | string | "file" or "aws" (the alias is "dynamodb") |
config | Driver specific |
This block is optional. Local file ${BASE_DIR}/enclave_keys.json
will be used if the block is omitted.
AWS Storage Configuration
Field | Environment variable | Type | Default |
---|---|---|---|
access_key_id | AWS_ACCESS_KEY_ID | string | |
secret_access_key | AWS_SECRET_ACCESS_KEY | string | |
session_token | AWS_SESSION_TOKEN | string | |
region | AWS_REGION | string | |
table | string | "encrypted_keys" |
This block is optional. If the user has a properly configured access to AWS the client code will pick it automatically.
Local storage
If local storage is specified then the config
field is expected to be a single string containing a full file path. Environment variables are allowed and will be expanded.
Example
base_dir: ${HOME}/.signatory
server:
# Address for the main HTTP server to listen on
address: :6732
# Address for the utility HTTP server to listen on
utility_address: :9583
vaults:
nitro:
driver: nitro
config:
proxy_remote_address: kms.us-west-2.amazonaws.com:443
encryption_key_id: 771dfdac-e8e9-4f40-9747-f56d0911fce4
Importing
Nitro backend supports importing of pre-existing plain text keys in either PEM, DER or Base58 format using signatory-cli import
command. The key will be passed to the enclave in open form and the latter will return its encrypted version.
Key Generation
More secure way of getting keys into the enclave is to generate them on the enclave side using signatory-cli generate
command:
Usage:
signatory-cli generate [flags]
Flags:
-h, --help help for generate
-n, --num int Number of keys to generate (default 1)
-t, --type string Key algorithm: [tz1, tz2, tz3, tz4, ed25519, secp256k1, p256, bls] (default "ed25519")
-v, --vault string Vault name for importing
Global Flags:
--base-dir string Base directory. Takes priority over one specified in config
-c, --config string Config file path (default "/etc/signatory.yaml")
--json-log Use JSON structured logs
--log string Log level: [error, warn, info, debug, trace] (default "info")
Example:
signatory-cli generate -v nitro
VSock Proxy
All requests to KMS from a signer are getting tunneled over VSock link to the parent instance which forwards them to the cloud. The recommended way of doing so is to use vsock_proxy supplied with nitro-cli
. The alternative way is to employ a built in proxy which is getting enabled by setting proxy_remote_address
configuration option (or alternatively PROXY_REMOTE_ADDRESS
environment variable) which usually takes form of kms.${REGION}.amazonaws.com:443