Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 102 additions & 7 deletions doc/plugin_server_keymanager_aws_kms.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

The `aws_kms` key manager plugin leverages the AWS Key Management Service (KMS) to create, maintain and rotate key pairs (as [Customer Master Keys](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys), or CMKs), and sign SVIDs as needed, with the private key never leaving KMS.

The plugin supports two modes of operation:

- **Standard Mode**: Each SPIRE server manages its own set of keys identified by a unique server ID
- **Shared Keys Mode**: Multiple SPIRE servers (including multi-region deployments) can discover and use the same signing keys based on configurable templates and regular expressions

## Configuration

The plugin accepts the following configuration options:
Expand All @@ -11,9 +16,15 @@ The plugin accepts the following configuration options:
| access_key_id | string | see [AWS KMS Access](#aws-kms-access) | The Access Key Id used to authenticate to KMS | Value of the AWS_ACCESS_KEY_ID environment variable |
| secret_access_key | string | see [AWS KMS Access](#aws-kms-access) | The Secret Access Key used to authenticate to KMS | Value of the AWS_SECRET_ACCESS_KEY environment variable |
| region | string | yes | The region where the keys will be stored | |
| key_identifier_file | string | Required if key_identifier_value is not set | A file path location where information about generated keys will be persisted | |
| key_identifier_value | string | Required if key_identifier_file is not set | A static identifier for the SPIRE server instance (used instead of `key_identifier_file`) | |
| key_identifier_file | string | See [Key Identifier](#key-identifier) | A file path location where information about generated keys will be persisted | |
| key_identifier_value | string | See [Key Identifier](#key-identifier) | A static identifier for the SPIRE server instance (used instead of `key_identifier_file`) | |
| key_policy_file | string | no | A file path location to a custom key policy in JSON format | "" |
| key_tags | map | no | A map of tags to apply to created keys | |
| shared_keys | object | no | Configuration for shared keys mode (see [Shared Keys Configuration](#shared-keys-configuration)) | |

### Key Identifier

In standard mode, either `key_identifier_file` or `key_identifier_value` is required. In shared keys mode, these are optional as keys are identified using templates and regex patterns instead.

### Alias and Key Management

Expand All @@ -40,7 +51,44 @@ The plugin attempts to detect and prune stale aliases. To facilitate stale alias

The plugin also attempts to detect and prune stale keys. All keys managed by the plugin are assigned a `Description` of the form `SPIRE_SERVER/{TRUST_DOMAIN}`. The plugin periodically scans the keys. Any key with a `Description` matching the proper form, that is both unassociated with any alias and has a `CreationDate` older than 48 hours, is removed.

### Key tagging
### Shared Keys Configuration

The plugin supports a shared keys mode that allows multiple SPIRE servers to discover and use the same signing keys. This is useful for multi-server and multi-region deployments where servers need to coordinate key usage.

When the `shared_keys` configuration block is present, the plugin operates in shared keys mode. This block accepts the following options:

| Key | Type | Required | Description |
|---------------------------|--------|----------|------------------------------------------------------------------------------------------------------------------------------|
| jwt_key_alias_template | string | yes | A Go template to generate the KMS alias for JWT keys |
| lock_alias_template | string | yes | A Go template to generate the KMS alias used for distributed locking during rotation |
| key_id_extraction_regex | string | yes | A regex with one capturing group to extract the SPIRE Key ID from KMS alias names |

> **Note**: Any existing keys cannot be used after turning on the shared keys feature.

#### Template Context

The alias templates support [Sprig v3](http://masterminds.github.io/sprig/) functions and have access to the following variables:

- `.Region`: The configured AWS region
- `.TrustDomain`: The configured trust domain
- `.ServerID`: The server ID (if configured)
- `.Env`: The value of the `SPIRE_ENV` environment variable
- `.KeyID`: The SPIRE Key ID being requested (e.g., `jwt-signer`, `x509-CA-A`)

#### Regex-based Discovery

The `key_id_extraction_regex` must include **one capturing group** that extracts the SPIRE Key ID from the KMS alias name.

Example: `^alias/spire/[^/]+/([^/]+)$` matches `alias/spire/us-east-1/jwt-signer` and extracts `jwt-signer`.

#### Distributed Locking and Coordination

When multiple servers share keys, they must coordinate to prevent race conditions during key rotation:

1. **Distributed Locking**: Before creating or rotating a key, the plugin acquires a distributed lock by creating a KMS alias determined by `lock_alias_template`
2. **Freshness Check**: If the lock is acquired, the plugin checks if the key was recently rotated (within the last 15 minutes) by another server. If so, it reuses the existing fresh key instead of generating a duplicate

### Key Tagging

The plugin supports tagging of KMS keys with user-defined tags using the `key_tags` configuration option. These tags are specified as key-value pairs and are applied to all KMS keys created by the plugin.

Expand Down Expand Up @@ -128,24 +176,26 @@ is set, the plugin uses the policy defined in the file instead of the default po

## Sample Plugin Configuration

### Basic configuration
### Standard Mode (Single Server)

Basic configuration for a single SPIRE server:

```hcl
KeyManager "aws_kms" {
plugin_data {
region = "us-east-2"
key_metadata_file = "./key_metadata"
key_identifier_file = "./server_id"
}
}
```

### Configuration with tags
### Standard Mode with Tags

```hcl
KeyManager "aws_kms" {
plugin_data {
region = "us-east-2"
key_metadata_file = "./key_metadata"
key_identifier_file = "./server_id"
key_tags = {
Environment = "production"
Team = "security"
Expand All @@ -155,6 +205,51 @@ KeyManager "aws_kms" {
}
```

### Shared Keys Mode (Multi-Server)

Configuration for multiple SPIRE servers sharing keys:

```hcl
KeyManager "aws_kms" {
plugin_data {
region = "us-east-1"

shared_keys {
# Template matches alias/spire/us-east-1/jwt-signer
jwt_key_alias_template = "alias/spire/{{ .Region }}/{{ .KeyID }}"

# Regex extracts 'jwt-signer' from the alias
key_id_extraction_regex = "^alias/spire/[^/]+/([^/]+)$"

# Lock alias for safe rotation coordination
lock_alias_template = "alias/spire/lock/{{ .Region }}/{{ .KeyID }}"
}
}
}
```

### Shared Keys Mode with Environment-based Keys

```hcl
KeyManager "aws_kms" {
plugin_data {
region = "us-west-2"

shared_keys {
# Use environment variable for multi-environment deployments
jwt_key_alias_template = "alias/spire/{{ .Env }}/{{ .Region }}/{{ .KeyID }}"
key_id_extraction_regex = "^alias/spire/[^/]+/[^/]+/([^/]+)$"
lock_alias_template = "alias/spire/lock/{{ .Env }}/{{ .Region }}/{{ .KeyID }}"
}

key_tags = {
Environment = "production"
Region = "us-west-2"
}
}
}
```

## Supported Key Types and TTL

The plugin supports all the key types supported by SPIRE: `rsa-2048`, `rsa-4096`, `ec-p256`, and `ec-p384`.
103 changes: 100 additions & 3 deletions doc/plugin_server_keymanager_azure_key_vault.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,29 @@ Microsoft Azure principal can view or export the raw cryptographic key material
represented by a key. Instead, Key Vault accesses the key material on behalf of
SPIRE.

The plugin supports two modes of operation:

- **Standard Mode**: Each SPIRE server manages its own set of keys identified by a unique server ID
- **Shared Keys Mode**: Multiple SPIRE servers (including multi-region deployments) can discover and use the same signing keys based on configurable templates and regular expressions

## Configuration

The plugin accepts the following configuration options:

| Key | Type | Required | Description | Default |
|----------------------|---------|---------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|
| key_identifier_file | string | Required if key_identifier_value is not set | A file path location where information about generated keys will be persisted. See "[Management of keys](#management-of-keys)" for more information. | "" |
| key_identifier_value | string | Required if key_identifier_file is not set | A static identifier for the SPIRE server instance (used instead of `key_identifier_file`). | "" |
| key_identifier_file | string | See [Key Identifier](#key-identifier) | A file path location where information about generated keys will be persisted. See "[Management of keys](#management-of-keys)" for more information. | "" |
| key_identifier_value | string | See [Key Identifier](#key-identifier) | A static identifier for the SPIRE server instance (used instead of `key_identifier_file`). | "" |
| key_vault_uri | string | Yes | The Key Vault URI where the keys managed by this plugin reside. | "" |
| subscription_id | string | [Optional](#authenticating-to-azure) | The subscription id. | "" |
| app_id | string | [Optional](#authenticating-to-azure) | The application id. | "" |
| app_secret | string | [Optional](#authenticating-to-azure) | The application secret. | "" |
| tenant_id | string | [Optional](#authenticating-to-azure) | The tenant id. | "" |
| shared_keys | object | no | Configuration for shared keys mode (see [Shared Keys Configuration](#shared-keys-configuration)) | "" |

### Key Identifier

In standard mode, either `key_identifier_file` or `key_identifier_value` is required. In shared keys mode, these are optional as keys are identified using templates and regex patterns instead.

### Authenticating to Azure

Expand All @@ -43,6 +53,39 @@ When a key is rotated, a new version is added to the Key.
Note that Azure does not support deleting individual key versions, instead, the key itself is deleted by the plugin
when it's no longer being used by a server in the trust domain the server belongs to.

### Shared Keys Configuration

The plugin supports a shared keys mode that allows multiple SPIRE servers to discover and use the same signing keys. This is useful for multi-server and multi-region deployments where servers need to coordinate key usage.

When the `shared_keys` configuration block is present, the plugin operates in shared keys mode. This block accepts the following options:

| Key | Type | Required | Description |
|--------------------------|--------|----------|------------------------------------------------------------------------------------------------------------------------------|
| jwt_key_template | string | yes | A Go template to generate the Key Vault key name for JWT keys |
| key_id_extraction_regex | string | yes | A regex with one capturing group to extract the SPIRE Key ID from Key Vault key names |

> **Note**: Any existing keys cannot be used after turning on the shared keys feature.

#### Template Context

The key name template supports [Sprig v3](http://masterminds.github.io/sprig/) functions and has access to the following variables:

- `.TrustDomain`: The configured trust domain
- `.ServerID`: The server ID (if configured)
- `.KeyID`: The SPIRE Key ID being requested (e.g., `jwt-signer`, `x509-CA-A`)

#### Regex-based Discovery

The `key_id_extraction_regex` must include **one capturing group** that extracts the SPIRE Key ID from the Key Vault key name.

Example: `^spire-[^-]+-(.+)$` matches `spire-example-com-jwt-signer` and extracts `jwt-signer`.

#### Freshness Check and Coordination

When multiple servers share keys, they coordinate to prevent unnecessary key creation:

1. **Freshness Check**: Before creating a new key version, the plugin checks if the key was recently created (within the last 15 minutes) by another server. If so, it reuses the existing fresh key instead of generating a duplicate

### Management of keys

The plugin assigns [tags](https://learn.microsoft.com/en-us/azure/key-vault/keys/about-keys-details#key-tags) to the
Expand Down Expand Up @@ -72,7 +115,7 @@ where a key identifier file can't be persisted.

The plugin attempts to detect and delete stale keys. To facilitate stale
keys detection, the plugin actively updates the `Updated` field of all keys managed by the server every 6 hours.
Within the Key Vault the plugin is configured to use (`key_vaut_uri`), the plugin periodically scans the keys looking
Within the Key Vault the plugin is configured to use (`key_vault_uri`), the plugin periodically scans the keys looking
for active keys within the trust domain that have their `Updated` field value older than two weeks and deletes them.

### Required permissions
Expand All @@ -96,6 +139,60 @@ Sign
Verify
```

## Sample Plugin Configuration

### Standard Mode (Single Server)

Basic configuration for a single SPIRE server:

```hcl
KeyManager "azure_key_vault" {
plugin_data {
key_vault_uri = "https://example-vault.vault.azure.net/"
key_identifier_file = "./server_id"
}
}
```

### Shared Keys Mode (Multi-Server)

Configuration for multiple SPIRE servers sharing keys:

```hcl
KeyManager "azure_key_vault" {
plugin_data {
key_vault_uri = "https://example-vault.vault.azure.net/"

shared_keys {
# Template matches spire-example-com-jwt-signer
jwt_key_template = "spire-{{ .TrustDomain | replace \".\" \"-\" }}-{{ .KeyID }}"

# Regex extracts 'jwt-signer' from the key name
key_id_extraction_regex = "^spire-[^-]+-(.+)$"
}
}
}
```

### Shared Keys Mode with Static Credentials

```hcl
KeyManager "azure_key_vault" {
plugin_data {
key_vault_uri = "https://example-vault.vault.azure.net/"
subscription_id = "subscription-id"
app_id = "app-id"
app_secret = "app-secret"
tenant_id = "tenant-id"

shared_keys {
jwt_key_template = "spire-{{ .TrustDomain | replace \".\" \"-\" }}-{{ .KeyID }}"
key_id_extraction_regex = "^spire-[^-]+-(.+)$"
}
}
}
```

## Supported Key Types

The plugin supports all the key types supported by SPIRE: `rsa-2048`,
Expand Down
12 changes: 12 additions & 0 deletions doc/plugin_server_keymanager_disk.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,25 @@ The plugin accepts the following configuration options:
| Configuration | Description |
|---------------|-------------------------------|
| keys_path | Path to the keys file on disk |
| shared_keys | Configuration for shared keys |

The `shared_keys` configuration block has the following members:

| Configuration | Description |
|---------------------|---------------------------------------------------------------------------------------------------------------------------------------|
| crypto_key_template | A golang text/template used to derive the ID keys are stored under in the file. `{{ .TrustDomain }}` and `{{ .KeyID }}` are available. |

> **Note**: Any existing keys cannot be used after turning on the shared keys feature. Additionally, using the `disk` key manager with the `shared_keys` feature requires a volume mount be shared between the SPIRE server instances sharing the key.

A sample configuration:

```hcl
KeyManager "disk" {
plugin_data = {
keys_path = "/opt/spire/data/server/keys.json"
shared_keys = {
crypto_key_template = "{{ .TrustDomain }}-key"
}
}
}
```
Loading
Loading