Compare commits
6 Commits
78dd48319c
...
master
Author | SHA1 | Date | |
---|---|---|---|
d1bccd385d | |||
857ebf865f | |||
6e0313a7b0 | |||
db1732d664 | |||
8d3ff2683a | |||
1980dceb73 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.idea
|
232
README.md
232
README.md
@@ -189,15 +189,15 @@ https://f.q.d.n/ui/vault/secrets/kv/list/for_rbacgroup_zabbix
|
||||
|
||||
The next example will explain orphan tokens. If you've followed examples above your Vault instance will have an `administrators` group with an `administrator` policy assigned to it. Users in that group will already have `write` access to `auth/token/create-orphan` so you can just use one of your `administrators` entities to follow along.
|
||||
|
||||
### Periodic and orphan tokens
|
||||
### Periodic orphan tokens
|
||||
|
||||
As an alternative to the Zabbix example above you may want a token that auto-renews itself as long as it gets regularly used and that can outlive its parent entity.
|
||||
As an alternative to the Zabbix example above you may want a token you can renew indefinitely which implies that it can outlive its parent entity.
|
||||
|
||||
By default a token is associated with the entity that created it, as a consequence a token cannot outlive the maximum time to live configured for its parent entity. In order to decouple a token from its parent entity and for a token to live longer than its parent entity you can make it an _orphan_ token.
|
||||
|
||||
A token created with a `period` - a time value indicating its maximum time to live - is considered a _periodic_ token. Unless a token is also orphaned its time to live still remains limited to that of its parent entity.
|
||||
A token created with a `period` on the other hand - a time value indicating its maximum time to live - is considered a _periodic_ token. Unless a token is also orphaned its time to live still remains limited to that of its parent entity.
|
||||
|
||||
The first few prep steps will sound familiar from the Zabbix paragraph above. For example's sake let's assume we want the `remco` file generator (see [github.com/HeavyHorst/remco](https://github.com/HeavyHorst/remco)) to have Vault access:
|
||||
For services that cannot handle renewal natively you will want both at the same time: a periodic orphan token. The first few prep steps will sound familiar from the Zabbix paragraph above. For example's sake let's assume we want the `remco` file generator (see [github.com/HeavyHorst/remco](https://github.com/HeavyHorst/remco)) to have Vault access:
|
||||
|
||||
* Create an entity `remco` without a policy
|
||||
* Add an alias of type `userpass` also named `remco` to the entity
|
||||
@@ -214,14 +214,23 @@ Log in to Vault with `userpass` and an account that has `write` access to `auth/
|
||||
```
|
||||
curl --silent --location --header 'X-Vault-Token: <token>' \
|
||||
--request POST \
|
||||
--data '{"policies":["remco"],"renewable":true,"ttl":"768h","display_name":"remco populates config files with secrets"}' \
|
||||
--data '{"policies":["remco"],"period":"768h","display_name":"remco populates config files with secrets"}' \
|
||||
'https://f.q.d.n/v1/auth/token/create-orphan'
|
||||
```
|
||||
|
||||
We're choosing our `ttl` of 768 hours on purpose. This equals 32 days which is the default server setting in `max_lease_ttl` that any token created by a non-`root` user can have. Feel free to reconfigure this server-side on your end and to pick a longer `ttl` value as needed. For our use case 32 days is plenty of time.
|
||||
Note that we do not specify `"renewable":true` as periodic tokens are implicitly renewable. We also don't specify `"ttl":"768h"` or similar values as the period in our periodic token will override a time-to-live value anyway rendering the time-to-live irrelevant. We can get our desired token by simply specifying for example `"period":"768h"`.
|
||||
|
||||
Write down the generated `client_token`.
|
||||
|
||||
Token renewal works like so via the `/auth/token/renew-self` endpoint:
|
||||
|
||||
```
|
||||
curl --silent --location --header 'X-Vault-Token: <token>' \
|
||||
--request POST \
|
||||
--data '{"token":"<token>"}' \
|
||||
'https://f.q.d.n/v1/auth/token/renew-self'
|
||||
```
|
||||
|
||||
Lastly don't forget to create some key value pairs underneath `kv/for_rbacgroup_remco` that the token can access.
|
||||
|
||||
#### Token lifecycle management
|
||||
@@ -258,6 +267,217 @@ Output will for example look like:
|
||||
|
||||
Where the `accessor` ID (here `66IzIsoOpXycYqF33JmfIb8G`) is what you're going to want to use in your CLI command `vault token revoke`.
|
||||
|
||||
### Auto-unseal with AWS Key Management Service
|
||||
|
||||
So far we've unsealed Vault after every daemon start with multiple Shamir's Secret Sharing unseal keys or Shamir unseal keys for short. We can have a Vault instance auto-unseal itself by accessing Amazon Web Services (AWS) Key Management Service (KMS) for example via public Internet. Vault supports other providers, we're going with AWS KMS as an example.
|
||||
|
||||
> [!WARNING]
|
||||
> Per [aws.amazon.com/kms/pricing](https://aws.amazon.com/kms/pricing) having one KMS key costs USD 1 per month pro-rated per hour of key existence. The following example assumes you're creating a symmetric encryption and decryption key with KMS as key material origin in a single region. As such API actions `kms:Encrypt`, `kms:Decrypt` and `kms:DescribeKey` (among others that we don't care about) are included in AWS KMS' Free Tier for up to 20,000 requests monthly. As long as Vault auto-unseals at most 20,000 times a month these operations won't cost you anything. A flat fee of USD 1 for the existence of a KMS key, however, applies.
|
||||
|
||||
#### Create resources
|
||||
|
||||
In AWS one way to get the necessary resources is to:
|
||||
|
||||
* In Key Management Service (KMS)
|
||||
* Create one key
|
||||
* Symmetric
|
||||
* Encryption and decryption
|
||||
* Key material origin KMS
|
||||
* Single region
|
||||
* Write down its Amazon Resource Name (ARN)
|
||||
* In Identity and Access Management (IAM)
|
||||
* Create an IAM policy in plain JSON, replace `<arn>` with ARN from above:
|
||||
```
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "EnableKMSForVaultAutoUnseal",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"kms:Encrypt",
|
||||
"kms:Decrypt",
|
||||
"kms:DescribeKey"
|
||||
],
|
||||
"Resource": "<arn>"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
* Create a user group, attach above customer-managed policy to it
|
||||
* Create a user
|
||||
* Add it to the user group
|
||||
* Create an access key and secret access key
|
||||
|
||||
#### Migrate Vault to auto-unseal with AWS KMS
|
||||
|
||||
The setup roughly goes like so:
|
||||
|
||||
* Configure Vault to use AWS KMS
|
||||
* (Re-)Start Vault daemon
|
||||
* Via CLI migrate unseal mechanism to AWS KMS
|
||||
|
||||
One way to configure Vault to do AWS KMS auto-unsealing is to specify the following environment variables. All but the fifth one (`VAULT_SEAL_TYPE=awskms`) depend on the KMS key you created so fill in the blanks with your specific key material. We're assuming that you have a Vault instance running with Docker Compose or a similar mechanism, we'll leave the implementation details to you for how to get these five environment variables into your Vault instance. Note that `VAULT_AWSKMS_SEAL_KEY_ID` is the key's Amazon Resource Name.
|
||||
|
||||
```
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_REGION=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
VAULT_AWSKMS_SEAL_KEY_ID=
|
||||
VAULT_SEAL_TYPE=awskms
|
||||
```
|
||||
|
||||
(Re-)Start Vault to make the variables take effect. Vault (for example in its Docker log) will then indicate that it's entering seal migration mode:
|
||||
|
||||
```
|
||||
core: entering seal migration mode; Vault will not automatically unseal even if using an autoseal: from_barrier_type=shamir to_barrier_type=awskms
|
||||
```
|
||||
|
||||
At first glance when in this mode Vault will appear to behave like normal in that its web UI will be up and available. However, any attempt to unseal Vault with your previous unseal keys will do nothing.
|
||||
|
||||
Log in to Vault with the `vault` CLI client, see [Authenticate against Vault](#authenticate-against-vault) above. Issue the migration command as many times as you have your required Shamir unseal keys configured, enter them one at a time.
|
||||
|
||||
```
|
||||
# vault operator unseal -migrate
|
||||
# Which will prompt for:
|
||||
Unseal Key (will be hidden):
|
||||
```
|
||||
|
||||
After each `vault operator unseal -migrate` command the `vault` binary will print the current migration status like so (here after entering one of two Shamir unseal keys):
|
||||
|
||||
```
|
||||
Key Value
|
||||
--- -----
|
||||
Seal Type awskms
|
||||
Recovery Seal Type shamir
|
||||
Initialized true
|
||||
--> Sealed true
|
||||
Total Recovery Shares 3
|
||||
Threshold 2
|
||||
--> Unseal Progress 1/2
|
||||
Unseal Nonce dc..86
|
||||
Seal Migration in Progress true
|
||||
Version 1.18.3
|
||||
Build Date 2024-12-16T14:00:53Z
|
||||
Storage Type file
|
||||
HA Enabled false
|
||||
```
|
||||
|
||||
After entering the last unseal key vault will be unsealed and migrated. This will look like so:
|
||||
|
||||
```
|
||||
# vault status
|
||||
|
||||
Key Value
|
||||
--- -----
|
||||
Seal Type awskms
|
||||
Recovery Seal Type shamir
|
||||
Initialized true
|
||||
--> Sealed false
|
||||
Total Recovery Shares 3
|
||||
Threshold 2
|
||||
Version 1.18.3
|
||||
Build Date 2024-12-16T14:00:53Z
|
||||
Storage Type file
|
||||
Cluster Name vault-cluster
|
||||
Cluster ID 9a..01
|
||||
HA Enabled false
|
||||
```
|
||||
|
||||
In its log output Vault will indicate that seal migration is complete. That's all there it to it: after every subsequent Vault daemon start it will attempt to access AWS KMS via public Internet and auto-unseal Vault.
|
||||
|
||||
#### Migrate back to Shamir unseal keys
|
||||
|
||||
Once a Vault instance is configured to auto-unseal with AWS KMS or any other key management provider Vault will not ever unseal via any other mechanism. If you lose Internet connectivity to AWS or the key gets deleted at AWS your Vault instance will remain locked. Your way out in this case is to migrate back to Shamir unseal keys.
|
||||
|
||||
The setup roughly goes like so:
|
||||
|
||||
* Configure Vault to **_not_** use AWS KMS
|
||||
* (Re-)Start Vault daemon
|
||||
* Via CLI migrate unseal mechanism to Shamir unseal keys
|
||||
|
||||
We'll assume that you're running Vault with Docker Compose and that you have environment variables set like so, obviously with real values instead of blanks:
|
||||
|
||||
```
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_REGION=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
VAULT_AWSKMS_SEAL_KEY_ID=
|
||||
VAULT_SEAL_TYPE=awskms
|
||||
```
|
||||
|
||||
Your container also has a bind-mounted HCL-formatted config file `/vault/config/vault.hcl`:
|
||||
|
||||
```
|
||||
backend "file" {
|
||||
path = "/vault/file"
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "0.0.0.0:8200"
|
||||
tls_disable = 1
|
||||
}
|
||||
|
||||
api_addr = "https://fully.qualified.domain.name"
|
||||
disable_clustering = true
|
||||
ui = true
|
||||
```
|
||||
|
||||
Add this section to the file:
|
||||
|
||||
```
|
||||
seal "awskms" {
|
||||
disabled = true
|
||||
}
|
||||
```
|
||||
|
||||
So that the end result looks like so:
|
||||
|
||||
```
|
||||
backend "file" {
|
||||
path = "/vault/file"
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "0.0.0.0:8200"
|
||||
tls_disable = 1
|
||||
}
|
||||
|
||||
api_addr = "https://fully.qualified.domain.name"
|
||||
disable_clustering = true
|
||||
ui = true
|
||||
|
||||
seal "awskms" {
|
||||
disabled = true
|
||||
}
|
||||
```
|
||||
|
||||
Also remove the environment variable `VAULT_SEAL_TYPE` from your container or at least change it to an empty string (`VAULT_SEAL_TYPE=`). Now (re-)start Vault and it'll report:
|
||||
|
||||
```
|
||||
core: entering seal migration mode; Vault will not automatically unseal even if using an autoseal: from_barrier_type=awskms to_barrier_type=shamir
|
||||
```
|
||||
|
||||
The rest is the reverse of [Migrate Vault to auto-unseal with AWS KMS](#migrate-vault-to-auto-unseal-with-aws-kms): log in to Vault via CLI `vault` binary and do a few incantations of `vault operator unseal -migrate`. Use your Shamir unseal keys. After successful migration `vault` binary will print:
|
||||
|
||||
```
|
||||
Key Value
|
||||
--- -----
|
||||
--> Seal Type shamir
|
||||
Initialized true
|
||||
Sealed false
|
||||
Total Shares 3
|
||||
Threshold 2
|
||||
Version 1.18.3
|
||||
Build Date 2024-12-16T14:00:53Z
|
||||
Storage Type file
|
||||
Cluster Name vault-cluster
|
||||
Cluster ID 9a..01
|
||||
HA Enabled false
|
||||
```
|
||||
|
||||
You now have decoupled Vault from AWS KMS and are back to using Shamir unseal keys. After every Vault daemon restart you'll have to manually unseal your instance again.
|
||||
|
||||
## Clean-up
|
||||
|
||||
If during any of the above steps you've used the Vault command-line client to authenticate against Vault with your `root` token make sure that client's `~/.vault-token` file is deleted. It contains the verbatim `root` token.
|
||||
|
@@ -6,16 +6,21 @@ path "sys/health"
|
||||
|
||||
# Create and manage ACL policies broadly across Vault
|
||||
|
||||
# Display the Policies tab in UI
|
||||
path "sys/policies" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
|
||||
# List existing policies
|
||||
path "sys/policies/acl"
|
||||
{
|
||||
capabilities = ["list"]
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
|
||||
# Create and manage ACL policies
|
||||
path "sys/policies/acl/*"
|
||||
{
|
||||
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
}
|
||||
|
||||
# Enable and manage authentication methods broadly across Vault
|
||||
@@ -29,13 +34,13 @@ path "auth/*"
|
||||
# Create, update, and delete auth methods
|
||||
path "sys/auth/*"
|
||||
{
|
||||
capabilities = ["create", "update", "delete", "sudo"]
|
||||
capabilities = ["create", "update", "read", "delete", "list", "sudo"]
|
||||
}
|
||||
|
||||
# List auth methods
|
||||
path "sys/auth"
|
||||
{
|
||||
capabilities = ["read"]
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
|
||||
# Enable and manage the key/value secrets engine at `secret/` path
|
||||
@@ -58,26 +63,7 @@ path "sys/mounts"
|
||||
capabilities = ["read"]
|
||||
}
|
||||
|
||||
# Allow creation of groups
|
||||
path "identity/group"
|
||||
{
|
||||
capabilities = ["update"]
|
||||
}
|
||||
|
||||
# Allow renaming of groups
|
||||
path "identity/group/+/+"
|
||||
{
|
||||
capabilities = ["update"]
|
||||
}
|
||||
|
||||
# Allow listing and reading of groups and group attributes
|
||||
path "identity/groups/+/+"
|
||||
{
|
||||
capabilities = ["list", "read"]
|
||||
}
|
||||
|
||||
# Allow listing and reading of entities and entity attributes
|
||||
path "identity/entity/+/+"
|
||||
{
|
||||
capabilities = ["list", "read"]
|
||||
# Create and manage entities and groups
|
||||
path "identity/*" {
|
||||
capabilities = [ "create", "read", "update", "delete", "list" ]
|
||||
}
|
Reference in New Issue
Block a user