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

Add HashiCorp Vault key manager plugin to SPIRE server #5500

Open
wants to merge 41 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
4623949
Create skeleton of HC Vault based server keymanager plugin (#5058)
InverseIntegral Sep 18, 2024
e0dbff7
Start implementing signing function for HC vault (#5058)
InverseIntegral Sep 18, 2024
8784293
Make SignData work with HC Vault keymanager plugin (#5058)
InverseIntegral Sep 18, 2024
beabe56
Rename transit key type constants (#5058)
InverseIntegral Sep 18, 2024
39e4803
Make vault client more robust by handling invariant violations (#5058)
InverseIntegral Sep 18, 2024
8d60d50
Move logic from plugin to vault client (#5058)
InverseIntegral Sep 18, 2024
90f68fd
Refactor logic to generate vault client (#5058)
InverseIntegral Sep 18, 2024
c6332a0
Use latest key version to sign data (#5058)
InverseIntegral Sep 18, 2024
8042877
Move data encoding to vault client (#5058)
InverseIntegral Sep 18, 2024
702193a
Add simple vault client auth test (#5058)
InverseIntegral Sep 18, 2024
0d78ffa
Remove unused test code (#5058)
InverseIntegral Sep 18, 2024
41b91e5
Support configuring vault namespace (#5058)
InverseIntegral Sep 18, 2024
c8e9b0b
Support AppRole authentication (#5058)
InverseIntegral Sep 18, 2024
573cca6
Make transit engine path configurable (#5058)
InverseIntegral Sep 18, 2024
7d3d9f7
Add comments to exported functions (#5058)
InverseIntegral Sep 18, 2024
53f5709
Support certificate authentication (#5058)
InverseIntegral Sep 18, 2024
9d6ea3e
Add missing app role auth test case (#5058)
InverseIntegral Sep 18, 2024
82f4be6
Support K8s auth (#5058)
InverseIntegral Sep 18, 2024
12fe8c4
Support verifying server certificate via CA (#5058)
InverseIntegral Sep 18, 2024
d15d8ff
Test vault client create key function (#5058)
InverseIntegral Sep 18, 2024
5c33e05
Test vault client get key function (#5058)
InverseIntegral Sep 18, 2024
1438bc4
Test vault client sign data function (#5058)
InverseIntegral Sep 18, 2024
c2879e2
Test vault key manager configure function (#5058)
InverseIntegral Sep 18, 2024
2a074d9
Test vault key manager generate key function (#5058)
InverseIntegral Sep 18, 2024
d739d8e
Load keys from Vault on configure (#5058)
InverseIntegral Sep 18, 2024
2ba4eb4
Test get key entry function (#5058)
InverseIntegral Sep 18, 2024
4f1b244
Test get keys function (#5058)
InverseIntegral Sep 18, 2024
307a2a7
Add simple plugin documentation (#5058)
InverseIntegral Sep 18, 2024
db491f3
Remove unused hooks (#5058)
InverseIntegral Sep 19, 2024
42bc673
Merge remote-tracking branch 'original/main'
InverseIntegral Sep 19, 2024
f57fd03
Fix hcl examples in documentation (#5058)
InverseIntegral Oct 20, 2024
7113b7b
Add KeyManager vault integration test (#5058)
InverseIntegral Nov 2, 2024
6f1e41f
Add warning when skipping TLS verification (#5058)
InverseIntegral Nov 27, 2024
057d62b
Prevent shadowing of variable (#5058)
InverseIntegral Nov 27, 2024
1b407c2
Improve comment (#5058)
InverseIntegral Nov 27, 2024
4ad4ee7
Add type assertion check (#5058)
InverseIntegral Nov 27, 2024
611741b
Remove TODO (#5058)
InverseIntegral Nov 27, 2024
d8f67f7
Remove TODO (#5058)
InverseIntegral Nov 27, 2024
426a992
Introduce unique server id for HA setup (#5058)
InverseIntegral Dec 1, 2024
5ecbc90
Make key names unique by adding a UUID (#5058)
InverseIntegral Dec 1, 2024
76e3c8d
Cleanup keys with same SPIRE key id (#5058)
InverseIntegral Dec 1, 2024
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
181 changes: 181 additions & 0 deletions doc/plugin_server_keymanager_hashicorp_vault.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# Server plugin: KeyManager "hashicorp_vault"

The `hashicorp_vault` key manager plugin leverages HashiCorp Vault to create, maintain, and rotate key pairs, signing
SVIDs as needed.

## 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`). | "" |
| vault_addr | string | | The URL of the Vault server. (e.g., <https://vault.example.com:8443/>) | `${VAULT_ADDR}` |
| namespace | string | | Name of the Vault namespace. This is only available in the Vault Enterprise. | `${VAULT_NAMESPACE}` |
| transit_engine_path | string | | Path of the transit engine that stores the keys. | transit |
| ca_cert_path | string | | Path to a CA certificate file used to verify the Vault server certificate. Only PEM format is supported. | `${VAULT_CACERT}` |
| insecure_skip_verify | bool | | If true, vault client accepts any server certificates. Should only be used for test environments. | false |
| cert_auth | struct | | Configuration for the Client Certificate authentication method | |
| token_auth | struct | | Configuration for the Token authentication method | |
| approle_auth | struct | | Configuration for the AppRole authentication method | |
| k8s_auth | struct | | Configuration for the Kubernetes authentication method | |

The plugin supports **Client Certificate**, **Token** and **AppRole** authentication methods.

- **Client Certificate** method authenticates to Vault using a TLS client certificate.
- **Token** method authenticates to Vault using the token in a HTTP Request header.
- **AppRole** method authenticates to Vault using a RoleID and SecretID that are issued from Vault.

The [`ca_ttl` SPIRE Server configurable](https://github.com/spiffe/spire/blob/main/doc/spire_server.md#server-configuration-file)
should be less than or equal to the Vault's PKI secret engine TTL.
To configure the TTL value, tune the engine.

e.g.

```shell
$ vault secrets tune -max-lease-ttl=8760h pki
```

The configured token needs to be attached to a policy that has at least the following capabilities:

```hcl
path "pki/root/sign-intermediate" {
capabilities = ["update"]
}
```

## Client Certificate Authentication

| key | type | required | description | default |
|:----------------------|:-------|:---------|:---------------------------------------------------------------------------------------------------------------------|:-----------------------|
| cert_auth_mount_point | string | | Name of the mount point where TLS certificate auth method is mounted | cert |
| cert_auth_role_name | string | | Name of the Vault role. If given, the plugin authenticates against only the named role. Default to trying all roles. | |
| client_cert_path | string | | Path to a client certificate file. Only PEM format is supported. | `${VAULT_CLIENT_CERT}` |
| client_key_path | string | | Path to a client private key file. Only PEM format is supported. | `${VAULT_CLIENT_KEY}` |

```hcl
KeyManager "hashicorp_vault" {
plugin_data {
vault_addr = "https://vault.example.org/"
pki_mount_point = "test-pki"
ca_cert_path = "/path/to/ca-cert.pem"
cert_auth {
cert_auth_mount_point = "test-tls-cert-auth"
client_cert_path = "/path/to/client-cert.pem"
client_key_path = "/path/to/client-key.pem"
}
// If specify the role to authenticate with
// cert_auth {
// cert_auth_mount_point = "test-tls-cert-auth"
// cert_auth_role_name = "test"
// client_cert_path = "/path/to/client-cert.pem"
// client_key_path = "/path/to/client-key.pem"
// }

// If specify the key-pair as an environment variable and use the modified mount point
// cert_auth {
// cert_auth_mount_point = "test-tls-cert-auth"
// }

// If specify the key-pair as an environment variable and use the default mount point, set the empty structure.
// cert_auth {}
}
}
```

## Token Authentication

| key | type | required | description | default |
|:------|:-------|:---------|:------------------------------------------------|:-----------------|
| token | string | | Token string to set into "X-Vault-Token" header | `${VAULT_TOKEN}` |

```hcl
KeyManager "hashicorp_vault" {
plugin_data {
vault_addr = "https://vault.example.org/"
pki_mount_point = "test-pki"
ca_cert_path = "/path/to/ca-cert.pem"
token_auth {
token = "<token>"
}
// If specify the token as an environment variable, set the empty structure.
// token_auth {}
}
}
```

## AppRole Authentication

| key | type | required | description | default |
|:-------------------------|:-------|:---------|:-----------------------------------------------------------------|:-----------------------------|
| approle_auth_mount_point | string | | Name of the mount point where the AppRole auth method is mounted | approle |
| approle_id | string | | An identifier of AppRole | `${VAULT_APPROLE_ID}` |
| approle_secret_id | string | | A credential of AppRole | `${VAULT_APPROLE_SECRET_ID}` |

```hcl
KeyManager "hashicorp_vault" {
plugin_data {
vault_addr = "https://vault.example.org/"
pki_mount_point = "test-pki"
ca_cert_path = "/path/to/ca-cert.pem"
approle_auth {
approle_auth_mount_point = "my-approle-auth"
approle_id = "<Role ID>" // or specified by environment variables
approle_secret_id = "<Secret ID>" // or specified by environment variables
}
// If specify the approle_id and approle_secret as an environment variable and use the modified mount point
// approle_auth {
// approle_auth_mount_point = "my-approle-auth"
// }

// If specify the approle_id and approle_secret as an environment variable and use the default mount point, set the empty structure.
// approle_auth {}
}
}
```

## Kubernetes Authentication

| key | type | required | description | default |
|:---------------------|:-------|:---------|:----------------------------------------------------------------------------------|:-----------|
| k8s_auth_mount_point | string | | Name of the mount point where the Kubernetes auth method is mounted | kubernetes |
| k8s_auth_role_name | string | ✔ | Name of the Vault role. The plugin authenticates against the named role | |
| token_path | string | ✔ | Path to the Kubernetes Service Account Token to use authentication with the Vault | |

```hcl
KeyManager "hashicorp_vault" {
plugin_data {
vault_addr = "https://vault.example.org/"
pki_mount_point = "test-pki"
ca_cert_path = "/path/to/ca-cert.pem"
k8s_auth {
k8s_auth_mount_point = "my-k8s-auth"
k8s_auth_role_name = "my-role"
token_path = "/path/to/sa-token"
}

// If specify role name and use the default mount point and token_path
// k8s_auth {
// k8s_auth_role_name = "my-role"
// }
}
}
```

### Management of keys

The plugin needs a way to identify the specific server instance where it's
running. For that, either the `key_identifier_file` or `key_identifier_value`
setting must be used. Setting a _Key Identifier File_ instructs the plugin to
manage the identifier of the server automatically, storing the server ID in the
specified file. This method should be appropriate for most situations.
If a _Key Identifier File_ is configured and the file is not found during server
startup, the file is recreated with a new auto-generated server ID.
Consequently, if the file is lost, the plugin will not be able to identify keys
that it has previously managed and will recreate new keys on demand.

If you need more control over the identifier that's used for the server, the
`key_identifier_value` setting can be used to specify a
static identifier for the server instance. This setting is appropriate in situations
where a key identifier file can't be persisted.
Loading