Compare commits
22 Commits
8105976066
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| bdddad694b | |||
| 4c489a05f5 | |||
| 742011ca86 | |||
| b887ade155 | |||
| ba8d65173b | |||
| aeb0080f7c | |||
| b93f47bd6c | |||
| 30eaccb1a3 | |||
| 6c5323025b | |||
| 5050963cd5 | |||
| 2c9cb6df90 | |||
| fe38e97e02 | |||
| aca9f4c5ab | |||
| 74a364c8e1 | |||
| 691bcf2bb4 | |||
| 1034231806 | |||
| 54dd1e4e4f | |||
| dfa2ab5334 | |||
| 1e96682d79 | |||
| a033498d45 | |||
| b116ebab61 | |||
| decda15318 |
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
/config
|
||||||
|
/data
|
||||||
|
/log
|
||||||
|
**/*.key
|
||||||
|
default_policy.hcl
|
||||||
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"[hcl]": {
|
||||||
|
"editor.tabSize": 2,
|
||||||
|
"editor.insertSpaces": true
|
||||||
|
}
|
||||||
|
}
|
||||||
147
README.md
147
README.md
@@ -37,6 +37,12 @@ export VAULT_ADDR='http://127.0.0.1:8200' VAULT_TOKEN='root-token'
|
|||||||
|
|
||||||
> **Warning:** Development mode is designed for experimentation only. Data is stored in-memory and will be lost when the Vault process is stopped.
|
> **Warning:** Development mode is designed for experimentation only. Data is stored in-memory and will be lost when the Vault process is stopped.
|
||||||
|
|
||||||
|
## Local Mode
|
||||||
|
|
||||||
|
The repository also contains a set of scripts to run a local Vault instance. That instance may be used for experimentation, but unlike the development mode, it uses a file storage backend located at `./data`.
|
||||||
|
|
||||||
|
Start it using `bin/vault-start`. The script will create necessary directories and configuration files if they do not exist. The output from the `vault operator init` is saved to `config/vault-init.json`. The single unseal key and the root token are encrypted using GPG key available on the host system. The `bin/vault-unseal` script decrypts the unseal key and unseals the Vault. `set-env` script sets the `VAULT_TOKEN` and `VAULT_ADDR` environment variables. It should be sourced before running any Vault commands.
|
||||||
|
|
||||||
## TLS Certificate
|
## TLS Certificate
|
||||||
|
|
||||||
Use standard Lego ACME installation instructions available at [Let's Encrypt directory](../letsencrypt/README.md) for both the main and the KMS Vault servers.
|
Use standard Lego ACME installation instructions available at [Let's Encrypt directory](../letsencrypt/README.md) for both the main and the KMS Vault servers.
|
||||||
@@ -89,18 +95,16 @@ The default Vault unseal method uses Shamir's Secret Sharing, which requires man
|
|||||||
4. Apply the policy:
|
4. Apply the policy:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
vault policy write transit-unseal-policy transit-unseal-policy.hcl
|
vault policy write transit-unseal transit_unseal_policy.hcl
|
||||||
```
|
```
|
||||||
|
|
||||||
5. Create a token with the policy attached:
|
5. Create a token with the policy attached:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
vault token create -policy="transit-unseal-policy"
|
vault token create -orphan -policy="transit-unseal" -wrap-ttl=120 -period=24h -field=wrapping_token > wrapping-token.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
Save the generated token for later use.
|
6. Copy the `wrapping-token.txt` file securely to the main Vault server. It can be copied using `scp` or any other secure method.
|
||||||
|
|
||||||
6. Verify connectivity from the main Vault to the KMS Vault.
|
|
||||||
|
|
||||||
7. Store the KMS Vault unseal key and root token securely. Make an offline backup of the KMS Vault.
|
7. Store the KMS Vault unseal key and root token securely. Make an offline backup of the KMS Vault.
|
||||||
|
|
||||||
@@ -110,9 +114,9 @@ To enhance security and monitoring, enable audit logging on the KMS Vault:
|
|||||||
|
|
||||||
```shell
|
```shell
|
||||||
mkdir -p /var/log/vault
|
mkdir -p /var/log/vault
|
||||||
chown -R vault:vault /var/log/vault
|
chown -R vault:adm /var/log/vault
|
||||||
chmod 750 /var/log/vault
|
chmod 02750 /var/log/vault
|
||||||
vault audit enable file file_path=/var/log/vault/audit.log
|
vault audit enable file file_path="/var/log/vault/audit.log" mode="0640"
|
||||||
```
|
```
|
||||||
|
|
||||||
Then monitor the audit log online:
|
Then monitor the audit log online:
|
||||||
@@ -127,22 +131,80 @@ or offline:
|
|||||||
jq -r '. | select(.type == "response") | [ .time, .request.path, .request.operation, .request.remote_address] | @tsv' /var/log/vault/audit.log | column -t -N "time,path,operation,remote_addr"
|
jq -r '. | select(.type == "response") | [ .time, .request.path, .request.operation, .request.remote_address] | @tsv' /var/log/vault/audit.log | column -t -N "time,path,operation,remote_addr"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
or using Alloy and Grafana. To use Alloy, add the following configuration to `config.alloy`:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
loki.source.file "vault_audit_log" {
|
||||||
|
targets = [
|
||||||
|
{"__path__" = "/var/log/vault/audit.log", "log_name" = "vault_audit"},
|
||||||
|
]
|
||||||
|
forward_to = [loki.write.default.receiver]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Check the auditing configuration:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
vault audit list -detailed
|
||||||
|
```
|
||||||
|
|
||||||
### Main Vault Configuration
|
### Main Vault Configuration
|
||||||
|
|
||||||
Depending on main Vault state (new or existing), some of the following steps are mutually exclusive.
|
Depending on main Vault state (new or existing), some of the following steps are mutually exclusive.
|
||||||
|
|
||||||
1. If the main Vault is already initialized, shut it down and back up its data directory and configuration file.
|
1. If the main Vault is already initialized, shut it down and back up its data directory and configuration file.
|
||||||
|
|
||||||
2. Update the main Vault configuration file (usually located at `/etc/vault.d/vault.hcl`) to include the Auto Unseal configuration:
|
2. Verify connectivity from the main Vault to the KMS Vault.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
VAULT_ADDR=https://kms.koszewscy.waw.pl:8200 vault status
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -s https://kms.koszewscy.waw.pl:8200/v1/sys/seal-status | jq .
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
3. Update the main Vault configuration file (usually located at `/etc/vault.d/vault.hcl`) to include the Auto Unseal configuration:
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
|
ui = true
|
||||||
|
|
||||||
|
storage "file" {
|
||||||
|
path = "/opt/vault/data"
|
||||||
|
}
|
||||||
|
|
||||||
|
# HTTP listener
|
||||||
|
listener "tcp" {
|
||||||
|
address = "127.0.0.1:8200"
|
||||||
|
tls_disable = "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
# HTTPS listener
|
||||||
|
listener "tcp" {
|
||||||
|
address = "192.168.2.10:443"
|
||||||
|
tls_cert_file = "/opt/vault/tls/tls.crt"
|
||||||
|
tls_key_file = "/opt/vault/tls/tls.key"
|
||||||
|
}
|
||||||
|
|
||||||
seal "transit" {
|
seal "transit" {
|
||||||
address = "https://pbs.koszewscy.waw.pl:8200"
|
address = "https://kms.koszewscy.waw.pl:8200"
|
||||||
key_name = "transit-unseal"
|
disable_renewal = "false"
|
||||||
mount_path = "transit/"
|
key_name = "unseal-key"
|
||||||
|
mount_path = "transit/"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
3. Put the KMS Vault token created earlier into the environment file `/etc/vault.d/vault.env`:
|
|
||||||
|
|
||||||
|
4. Unwrap the token to get the KMS Vault token:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
VAULT_ADDR=https://kms.koszewscy.waw.pl:8200 vault unwrap -field=token $(cat wrapping-token.txt) > kms-vault-token.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Put the unwrapped KMS Vault token into the environment file `/etc/vault.d/vault.env`:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
VAULT_TOKEN="s.xxxxxxx"
|
VAULT_TOKEN="s.xxxxxxx"
|
||||||
@@ -155,6 +217,17 @@ Depending on main Vault state (new or existing), some of the following steps are
|
|||||||
EnvironmentFile=/etc/vault.d/vault.env
|
EnvironmentFile=/etc/vault.d/vault.env
|
||||||
```
|
```
|
||||||
|
|
||||||
|
5. Add systemd override `/etc/systemd/system/vault.service.d/override.conf` if not already present:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Service]
|
||||||
|
AmbientCapabilities=CAP_IPC_LOCK CAP_NET_BIND_SERVICE
|
||||||
|
CapabilityBoundingSet=CAP_SYSLOG CAP_IPC_LOCK CAP_NET_BIND_SERVICE
|
||||||
|
NoNewPrivileges=yes
|
||||||
|
```
|
||||||
|
|
||||||
|
That will allow the vault process to bind to low-numbered ports (443) and lock memory.
|
||||||
|
|
||||||
5. If the main Vault was already initialized, start it and unseal with `-migrate` parameter.
|
5. If the main Vault was already initialized, start it and unseal with `-migrate` parameter.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
@@ -166,6 +239,8 @@ Depending on main Vault state (new or existing), some of the following steps are
|
|||||||
|
|
||||||
7. Uninitialized main Vault will automatically encrypt the root key with the transit key from the KMS Vault during initialization and present recovery keys for Shamir's Secret Sharing.
|
7. Uninitialized main Vault will automatically encrypt the root key with the transit key from the KMS Vault during initialization and present recovery keys for Shamir's Secret Sharing.
|
||||||
|
|
||||||
|
If for any reason the Auto Unseal method fails, you can always unseal the main Vault using the recovery keys provided during initialization. If the token expires, generate a new one using the KMS Vault, and transfer it to the main Vault as described above.
|
||||||
|
|
||||||
## Offline Backup
|
## Offline Backup
|
||||||
|
|
||||||
Vault installs the following directories:
|
Vault installs the following directories:
|
||||||
@@ -229,3 +304,49 @@ systemctl start vault
|
|||||||
# Unseal the Vault
|
# Unseal the Vault
|
||||||
VAULT_ADDR=http://127.0.0.1:8200 vault operator unseal
|
VAULT_ADDR=http://127.0.0.1:8200 vault operator unseal
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 1Password Setup
|
||||||
|
|
||||||
|
Install 1Password CLI using the commands below:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
VERSION="v2.32.0" # I don't know how to get the latest version dynamically
|
||||||
|
# Repleace aarch with arm64
|
||||||
|
ARCH=${ARCH/aarch64/arm64}
|
||||||
|
echo "Installing 1Password CLI version ${VERSION} manually..."
|
||||||
|
TMP="/tmp/$(mktemp -d 1password-cli-installtion.XXXXXX)"
|
||||||
|
mkdir -p $TMP/extracted
|
||||||
|
curl -vsSL "https://cache.agilebits.com/dist/1P/op2/pkg/${VERSION}/op_linux_${ARCH}_${VERSION}.zip" -o $TMP/op.zip
|
||||||
|
unzip $TMP/op.zip -d $TMP/extracted
|
||||||
|
sudo groupadd -f onepassword-cli
|
||||||
|
sudo install -g onepassword-cli $TMP/extracted/op /usr/local/bin/op
|
||||||
|
sudo chmod g+s /usr/local/bin/op
|
||||||
|
if [[ -d $TMP ]]; then rm -rf $TMP; fi
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** Adjust the `VERSION` variable to install a different version of the 1Password CLI.
|
||||||
|
|
||||||
|
Create a `.vault.env` file in the home directory with the following content:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
VAULT_ADDR=http://localhost:8200
|
||||||
|
VAULT_TOKEN=op://Private/root KMS Koszewscy/password
|
||||||
|
```
|
||||||
|
|
||||||
|
add the following line to your shell profile (e.g., `~/.bashrc` or `~/.zshrc`):
|
||||||
|
|
||||||
|
```shell
|
||||||
|
alias op_vault='op run --env-file="$HOME/.vault.env" -- vault'
|
||||||
|
```
|
||||||
|
|
||||||
|
Run Vault CLI as follows:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
op_vault token lookup
|
||||||
|
```
|
||||||
|
|
||||||
|
Eventually, set both `VAULT_ADDR` and `VAULT_TOKEN` environment variables in your shell:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
export $(cat $HOME/.vault.env | op inject)
|
||||||
|
```
|
||||||
|
|||||||
10
bin/unwrap.sh
Executable file
10
bin/unwrap.sh
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Usage: ./unwrap.sh <VAULT_TOKEN>
|
||||||
|
# This script unwraps a wrapped secret in HashiCorp Vault using the provided token.
|
||||||
|
|
||||||
|
curl -s -X PUT \
|
||||||
|
-H "X-Vault-Token: $1" \
|
||||||
|
-H "X-Vault-Request: true" \
|
||||||
|
-d 'null' \
|
||||||
|
https://vault.koszewscy.waw.pl/v1/sys/wrapping/unwrap | jq '.data'
|
||||||
7
bin/vault-clear
Executable file
7
bin/vault-clear
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd .. && pwd)"
|
||||||
|
|
||||||
|
rm -rf $REPO_ROOT/{config,data,log}
|
||||||
20
bin/vault-init
Executable file
20
bin/vault-init
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd .. && pwd)"
|
||||||
|
GPG_KEY_ID="slawek@koszewscy.waw.pl"
|
||||||
|
GPG_PUB_KEY_FILE="$REPO_ROOT/slawek.key"
|
||||||
|
|
||||||
|
if [[ ! -f "$GPG_PUB_KEY_FILE" ]]; then
|
||||||
|
gpg --export "$GPG_KEY_ID" > "$GPG_PUB_KEY_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Initialize the Vault and store the initialization output in a JSON file
|
||||||
|
# The single unseal key and the root token will be PGP-encrypted using the provided GPG public key
|
||||||
|
VAULT_ADDR='http://127.0.0.1:8200' vault operator init \
|
||||||
|
-key-shares=1 \
|
||||||
|
-key-threshold=1 \
|
||||||
|
-pgp-keys="$GPG_PUB_KEY_FILE" \
|
||||||
|
-root-token-pgp-key="$GPG_PUB_KEY_FILE" \
|
||||||
|
-format=json > $REPO_ROOT/config/vault-init.json
|
||||||
17
bin/vault-login
Executable file
17
bin/vault-login
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
# Check, if we are sourced, that's a requirement for this script
|
||||||
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
|
echo "This script must be sourced, not executed directly."
|
||||||
|
echo "Use: source bin/vault-login"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# v_login function may be added to .bashrc, .zprofile, etc.
|
||||||
|
function v_login() {
|
||||||
|
local VAULT_USERNAME=${1:-adminslawek}
|
||||||
|
vault login -format=json -method=userpass username="$VAULT_USERNAME" |
|
||||||
|
jq -r '.auth | [.client_token, .accessor] | @tsv' | read -r VAULT_TOKEN TOKEN_ACCESSOR
|
||||||
|
echo "Logged in as $VAULT_USERNAME (Token accessor: $TOKEN_ACCESSOR)"
|
||||||
|
export VAULT_TOKEN TOKEN_ACCESSOR
|
||||||
|
}
|
||||||
|
|
||||||
|
v_login "$@"
|
||||||
12
bin/vault-start
Executable file
12
bin/vault-start
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd .. && pwd)"
|
||||||
|
|
||||||
|
mkdir -p $REPO_ROOT/{config,data,log}
|
||||||
|
sed -e "s|{{VAULT_DATA_DIR}}|$REPO_ROOT/data|g" \
|
||||||
|
-e "s|{{VAULT_LOG_DIR}}|$REPO_ROOT/log|g" \
|
||||||
|
$REPO_ROOT/vault.hcl > $REPO_ROOT/config/vault.hcl
|
||||||
|
|
||||||
|
vault server -config=$REPO_ROOT/config/vault.hcl -log-file=$REPO_ROOT/log/vault.log
|
||||||
9
bin/vault-unseal
Executable file
9
bin/vault-unseal
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd .. && pwd)"
|
||||||
|
|
||||||
|
UNSEAL_KEY_ENC=$(jq -r .unseal_keys_b64[0] $REPO_ROOT/config/vault-init.json)
|
||||||
|
vault operator unseal $(echo "$UNSEAL_KEY_ENC" | base64 -d | gpg -qd)
|
||||||
|
VAULT_ADDR='http://127.0.0.1:8200'
|
||||||
10
bin/wrap.sh
Executable file
10
bin/wrap.sh
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
DEFAULT_TTL="60"
|
||||||
|
|
||||||
|
curl \
|
||||||
|
--header "X-Vault-Token: $VAULT_TOKEN" \
|
||||||
|
--header "X-Vault-Wrap-TTL: $DEFAULT_TTL" \
|
||||||
|
--request POST \
|
||||||
|
--data "$1" \
|
||||||
|
$VAULT_ADDR/v1/sys/wrapping/wrap | jq
|
||||||
69
docs/ENV_VARS.md
Normal file
69
docs/ENV_VARS.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# Environment Variables
|
||||||
|
|
||||||
|
> Note: This list was generated by an AI Agent from a limited code search of the repository and may be incomplete.
|
||||||
|
>
|
||||||
|
> For the full code search results, see: https://github.com/hashicorp/vault/search?q=VAULT_&type=code.
|
||||||
|
|
||||||
|
| Environment Variable | Purpose (short) |
|
||||||
|
|-------------------------------------------|-------------------------------------------------------------------------|
|
||||||
|
| `VAULT_ADDR` | Client/server address (API target) |
|
||||||
|
| `VAULT_AGENT_ADDR` | Agent address (deprecated usage/const) |
|
||||||
|
| `VAULT_ALLOW_PENDING_REMOVAL_MOUNTS` | Allow Pending Removal builtins to be mounted |
|
||||||
|
| `VAULT_CACERT_BYTES` | CA certificate bytes provided via env |
|
||||||
|
| `VAULT_CACERT` | CA certificate file for TLS verification |
|
||||||
|
| `VAULT_CAPATH` | CA path for TLS verification |
|
||||||
|
| `VAULT_CLI_NO_COLOR` | Toggle colored CLI output |
|
||||||
|
| `VAULT_CLIENT_CERT` | Client TLS certificate path |
|
||||||
|
| `VAULT_CLIENT_KEY` | Client TLS key path |
|
||||||
|
| `VAULT_CLIENT_TIMEOUT` | Client timeout configuration |
|
||||||
|
| `VAULT_CLUSTER_ADDR` | Cluster address for inter-node comms |
|
||||||
|
| `VAULT_CLUSTER_INTERFACE` | Interface name used to derive VAULT_CLUSTER_ADDR |
|
||||||
|
| `VAULT_DETAILED` | Output detailed CLI information |
|
||||||
|
| `VAULT_DEV_LISTEN_ADDRESS` | Dev-mode listen address (entrypoint default) |
|
||||||
|
| `VAULT_DEV_ROOT_TOKEN_ID` | Dev-mode root token ID (used by entrypoint) |
|
||||||
|
| `VAULT_DISABLE_FILE_PERMISSIONS_CHECK` | Disable strict file permission checks (OpenShift/UBI entrypoint) |
|
||||||
|
| `VAULT_DISABLE_LOCAL_AUTH_MOUNT_ENTITIES` | Disable entities for local auth mounts via env |
|
||||||
|
| `VAULT_DISABLE_REDIRECTS` | Disable HTTP redirects for client |
|
||||||
|
| `VAULT_DISABLE_RSA_DRBG` | Disable RSA DRBG path in cryptoutil (feature flag) |
|
||||||
|
| `VAULT_ENABLE_RATE_LIMIT_AUDIT_LOGGING` | Enable audit logging for rate-limited rejections |
|
||||||
|
| `VAULT_EXPERIMENTS` | Comma-separated experiments enabled on startup |
|
||||||
|
| `VAULT_FORMAT` | CLI output format |
|
||||||
|
| `VAULT_HEADERS` | Additional headers for API client |
|
||||||
|
| `VAULT_HTTP_PROXY` | HTTP proxy configuration for client |
|
||||||
|
| `VAULT_LDAP_PASSWORD` | LDAP password fallback for CLI LDAP credential provider |
|
||||||
|
| `VAULT_LICENSE_CI` | CI license helper for tests |
|
||||||
|
| `VAULT_LICENSE_PATH` | Path to enterprise license file |
|
||||||
|
| `VAULT_LICENSE` | Provide enterprise license blob |
|
||||||
|
| `VAULT_LOCAL_CONFIG` | Pass Vault JSON config via env (entrypoint writes to config dir) |
|
||||||
|
| `VAULT_LOG_FORMAT` | Control logger format (standard/json) |
|
||||||
|
| `VAULT_LOG_LEVEL` | Logging level for Vault |
|
||||||
|
| `VAULT_MAX_RETRIES` | Max retries for client operations |
|
||||||
|
| `VAULT_MESSAGE_TYPE` | Serialization format for forwarded requests (json/json_compress/proto3) |
|
||||||
|
| `VAULT_MFA` | MFA selection for client |
|
||||||
|
| `VAULT_MYSQL_PASSWORD` | MySQL password override for physical MySQL backend |
|
||||||
|
| `VAULT_MYSQL_USERNAME` | MySQL username override for physical MySQL backend |
|
||||||
|
| `VAULT_NAMESPACE` | Default namespace header for client requests |
|
||||||
|
| `VAULT_PLUGIN_AUTOMTLS_ENABLED` | Enable plugin AutoMTLS (plugin helper) |
|
||||||
|
| `VAULT_PLUGIN_METADATA_MODE` | Control plugin metadata bootstrapping mode |
|
||||||
|
| `VAULT_PLUGIN_TMPDIR` | Folder for Unix sockets for containerized plugins |
|
||||||
|
| `VAULT_POSTUNSEAL_FUNC_CONCURRENCY` | Concurrency for post-unseal functions (sets worker count) |
|
||||||
|
| `VAULT_PROXY_ADDR` | Proxy address configuration |
|
||||||
|
| `VAULT_RAFT_DISABLE_MAP_POPULATE` | Disable MAP_POPULATE behaviour on Linux |
|
||||||
|
| `VAULT_RAFT_FREELIST_SYNC` | BoltDB freelist sync toggle |
|
||||||
|
| `VAULT_RAFT_FREELIST_TYPE` | BoltDB freelist type (array/map) |
|
||||||
|
| `VAULT_RAFT_INITIAL_MMAP_SIZE` | Initial mmap size for Bolt DB |
|
||||||
|
| `VAULT_RAFT_MAX_BATCH_ENTRIES` | Override Raft max batch entries |
|
||||||
|
| `VAULT_RAFT_MAX_BATCH_SIZE_BYTES` | Override Raft max batch size bytes |
|
||||||
|
| `VAULT_RAFT_NODE_ID` | Raft node ID from environment |
|
||||||
|
| `VAULT_RAFT_PATH` | Raft data path from environment |
|
||||||
|
| `VAULT_RAFT_RETRY_JOIN_AS_NON_VOTER` | Join Raft as non-voter via env |
|
||||||
|
| `VAULT_RATE_LIMIT` | Configure client-side or server rate limiting |
|
||||||
|
| `VAULT_REDIRECT_ADDR` | API redirect address (can be set directly) |
|
||||||
|
| `VAULT_REDIRECT_INTERFACE` | Interface name used to derive VAULT_REDIRECT_ADDR |
|
||||||
|
| `VAULT_SKIP_LOGGING_LEASE_EXPIRATIONS` | Toggle logging of lease expirations |
|
||||||
|
| `VAULT_SKIP_VERIFY` | Skip TLS verification (insecure) |
|
||||||
|
| `VAULT_SRV_LOOKUP` | Enable SRV DNS lookup behavior |
|
||||||
|
| `VAULT_TLS_SERVER_NAME` | TLS server name for verification |
|
||||||
|
| `VAULT_TOKEN` | Default Vault token for client auth |
|
||||||
|
| `VAULT_UNWRAP_TOKEN` | Pass unwrap tokens to plugin (plugin helper) |
|
||||||
|
| `VAULT_WRAP_TTL` | Default wrap TTL for client operations |
|
||||||
140
docs/Identity.md
Normal file
140
docs/Identity.md
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
# Identity and Authentication
|
||||||
|
|
||||||
|
## Token Authentication
|
||||||
|
|
||||||
|
Setup `VAULT_ADDR` and `VAULT_TOKEN` environment variables to authenticate with Vault using a token.
|
||||||
|
|
||||||
|
Store the root token in 1Password and retrieve it when needed using CLI commands.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export OP_VAULT_TOKEN="op://Private/root Vault Koszewscy/password"
|
||||||
|
export VAULT_ADDR="https://vault.koszewscy.waw.pl" VAULT_TOKEN="${OP_VAULT_TOKEN}"
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, run the vault using:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
op run -- vault login $VAULT_TOKEN
|
||||||
|
```
|
||||||
|
|
||||||
|
1Password CLI will fetch the token from the specified path in your 1Password vault and replace the secret reference with the actual token value when executing the command. However, that method adds a delay due to the `op run` command.
|
||||||
|
|
||||||
|
Alternatively, you can directly set the `VAULT_TOKEN` environment variable by reading the token from 1Password:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export VAULT_TOKEN=$(op read "op://Private/root Vault Koszewscy/password")
|
||||||
|
```
|
||||||
|
|
||||||
|
With VAULT_TOKEN set, `vault` authenticates directly.
|
||||||
|
|
||||||
|
## Userpass Authentication Method
|
||||||
|
|
||||||
|
### Login with Userpass
|
||||||
|
|
||||||
|
Userpass authentication allows users to log in with a username and password.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault login -method=userpass username="your-username"
|
||||||
|
```
|
||||||
|
|
||||||
|
The token is stored in a file located at `~/.vault-token` by default. Although, the token file is secured with file permissions, it contains a plaintext token. Change the token time-to-live (TTL) to limit its validity period.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault write auth/userpass/users/your-username max_token_ttl="12h" token_ttl="1h"
|
||||||
|
```
|
||||||
|
|
||||||
|
Limit the token's usage to known IP addresses for added security.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault write auth/userpass/users/your-username token_bound_cidrs="192.168.2.0/24"
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also set VAULT_TOKEN with the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export VAULT_TOKEN=$(vault login -token-only -method=userpass username="your-username")
|
||||||
|
```
|
||||||
|
|
||||||
|
or a function like this:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
function v_login() {
|
||||||
|
local VAULT_USERNAME=${1:-"your-username"}
|
||||||
|
vault login -format=json -method=userpass username="$VAULT_USERNAME" |
|
||||||
|
jq -r '.auth | [.client_token, .accessor] | @tsv' | read -r VAULT_TOKEN TOKEN_ACCESSOR
|
||||||
|
echo "Logged in as $VAULT_USERNAME (Token accessor: $TOKEN_ACCESSOR)"
|
||||||
|
export VAULT_TOKEN TOKEN_ACCESSOR
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** The `-token-only` is an equivalent of `-field=token -no-store` options.
|
||||||
|
|
||||||
|
You can then use the `TOKEN_ACCESSOR` to look up token details without exposing the actual token.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault token lookup -accessor $TOKEN_ACCESSOR
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the `vault token renew` command to renew the token before it expires.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault token renew
|
||||||
|
```
|
||||||
|
|
||||||
|
### User Management
|
||||||
|
|
||||||
|
List all users:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault list auth/userpass/users
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a new user:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault write auth/userpass/users/new-username password="new-password" policies="default"
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** key="value" pairs may contain scalars or lists (comma-separated values).
|
||||||
|
|
||||||
|
Read user details:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault read auth/userpass/users/username
|
||||||
|
```
|
||||||
|
|
||||||
|
## Entities and Groups
|
||||||
|
|
||||||
|
### Entities
|
||||||
|
|
||||||
|
Docs: [https://developer.hashicorp.com/vault/api-docs/secret/identity/entity](https://developer.hashicorp.com/vault/api-docs/secret/identity/entity)
|
||||||
|
|
||||||
|
List entities by id:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault list identity/entity/id
|
||||||
|
```
|
||||||
|
|
||||||
|
or by name:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault list identity/entity/name
|
||||||
|
```
|
||||||
|
|
||||||
|
[Read entity details by id](https://developer.hashicorp.com/vault/api-docs/secret/identity/entity#read-entity-by-id)
|
||||||
|
or [by name](https://developer.hashicorp.com/vault/api-docs/secret/identity/entity#read-entity-by-name):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault read identity/entity/id/<entity-id>
|
||||||
|
vault read identity/entity/name/<entity-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
[Create a new entity](https://developer.hashicorp.com/vault/api-docs/secret/identity/entity#create-an-entity):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault write identity/entity name="entity-name" policies="default" metadata=key1=value1 metadata=key2=value2
|
||||||
|
```
|
||||||
|
|
||||||
|
### Entity Aliases
|
||||||
|
|
||||||
|
Docs: [https://developer.hashicorp.com/vault/api-docs/secret/identity/entity-alias](https://developer.hashicorp.com/vault/api-docs/secret/identity/entity-alias)
|
||||||
39
docs/README.md
Normal file
39
docs/README.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# General Vault Links and Commands
|
||||||
|
|
||||||
|
## Useful commands
|
||||||
|
|
||||||
|
Display the `curl` equivalent of a Vault CLI command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault <any_command> -output-curl-string
|
||||||
|
```
|
||||||
|
|
||||||
|
The following are equivalent:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s -H "X-Vault-Request: true" -H "X-Vault-Token: $VAULT_TOKEN" "https://vault.koszewscy.waw.pl/v1/auth/userpass/users?list=true"
|
||||||
|
```
|
||||||
|
|
||||||
|
and
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s -X LIST -H "X-Vault-Request: true" -H "X-Vault-Token: $VAULT_TOKEN" https://vault.koszewscy.waw.pl/v1/auth/userpass/users
|
||||||
|
```
|
||||||
|
|
||||||
|
because the Vault uses non-standard HTTP method `LIST` for listing resources.
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
| Environment Variable | Purpose (short) |
|
||||||
|
|-------------------------------------------|-------------------------------------------------------------------------|
|
||||||
|
| `VAULT_ADDR` | Client/server address (API target) |
|
||||||
|
| `VAULT_DETAILED` | Output detailed CLI information |
|
||||||
|
| `VAULT_FORMAT` | CLI output format |
|
||||||
|
| `VAULT_LOG_FORMAT` | Control logger format (standard/json) |
|
||||||
|
| `VAULT_LOG_LEVEL` | Logging level for Vault |
|
||||||
|
| `VAULT_TOKEN` | Default Vault token for client auth |
|
||||||
|
| `VAULT_UNWRAP_TOKEN` | Pass unwrap tokens to plugin (plugin helper) |
|
||||||
|
| `VAULT_WRAP_TTL` | Default wrap TTL for client operations |
|
||||||
|
|
||||||
|
> The list above is a small subset of all available environment variables, that I see most useful.
|
||||||
|
> The rest can be found in the [ENV_VARS.md](ENV_VARS.md) file.
|
||||||
97
policies/README.md
Normal file
97
policies/README.md
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
# HashiCorp Vault Policies
|
||||||
|
|
||||||
|
## Defualt Policy
|
||||||
|
|
||||||
|
The **default** policy is created automatically when Vault is initialized, but can be modified as needed. It provides basic access to Vault features for authenticated users.
|
||||||
|
|
||||||
|
To restore the default policy to the newest default version, launch a development Vault server and copy the default policy from there:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault policy read default > default_policy.hcl
|
||||||
|
vault policy write default default_policy.hcl
|
||||||
|
```
|
||||||
|
|
||||||
|
## Policy Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault policy list
|
||||||
|
vault policy read <policy-name>
|
||||||
|
vault policy write <policy-name> <policy-file.hcl>
|
||||||
|
vault policy delete <policy-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
Format a policy file using `vault policy fmt <policy-file.hcl>`.
|
||||||
|
|
||||||
|
Display required capabilities for a given path with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault <anycommand> -output-policy
|
||||||
|
```
|
||||||
|
|
||||||
|
## Auditing
|
||||||
|
|
||||||
|
To enable auditing, use the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault audit enable file file_path=/var/log/vault_audit.log mode=0640
|
||||||
|
```
|
||||||
|
|
||||||
|
Configure Alloy to read the audit logs from the specified file path.
|
||||||
|
|
||||||
|
Add the following configuration to your Alloy setup:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
loki.source.file "vault_audit_log" {
|
||||||
|
targets = [
|
||||||
|
{"__path__" = "/var/log/vault/audit.log", "log_name" = "vault_audit", "level" = "info", "service" = "vault"},
|
||||||
|
]
|
||||||
|
tail_from_end = true
|
||||||
|
forward_to = [loki.process.vault_audit.receiver]
|
||||||
|
}
|
||||||
|
|
||||||
|
loki.process "vault_audit" {
|
||||||
|
stage.json {
|
||||||
|
expressions = {error = "error"}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage.labels {
|
||||||
|
values = { __has_error = "error" }
|
||||||
|
}
|
||||||
|
|
||||||
|
stage.match {
|
||||||
|
selector = "{__has_error!=\"\"}"
|
||||||
|
|
||||||
|
stage.static_labels {
|
||||||
|
values = {level = "error"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage.label_drop {
|
||||||
|
values = ["__has_error"]
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_to = [loki.write.default.receiver]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** `tail_from_end = true` ensures that only new log entries are read, preventing the ingestion of old lines/entries.
|
||||||
|
> It is (probably) required because the audit log file does not contain timestamps and only entry guids.
|
||||||
|
> Without this setting, Alloy may re-ingest old log entries upon restart.
|
||||||
|
>
|
||||||
|
> `loki.process` extracts message level from the `error` field in the JSON log entry.
|
||||||
|
|
||||||
|
Check auditing configuration with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault audit list -detailed
|
||||||
|
```
|
||||||
|
|
||||||
|
To disable auditing, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault audit disable file
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [RSoP Tool](https://github.com/threatkey-oss/hvresult) - **hvresult** computes the Resultant Set of Policy (RSoP) for Hashicorp Vault ACLs.
|
||||||
43
policies/admin_policy.hcl
Normal file
43
policies/admin_policy.hcl
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Read system health check
|
||||||
|
path "sys/health" {
|
||||||
|
capabilities = ["read", "sudo"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create and manage ACL policies broadly across Vault
|
||||||
|
|
||||||
|
# List existing policies
|
||||||
|
path "sys/policies/acl" {
|
||||||
|
capabilities = ["list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create and manage ACL policies
|
||||||
|
path "sys/policies/acl/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Enable and manage authentication methods broadly across Vault
|
||||||
|
|
||||||
|
# Manage auth methods broadly across Vault
|
||||||
|
path "auth/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create, update, and delete auth methods
|
||||||
|
path "sys/auth/*" {
|
||||||
|
capabilities = ["create", "update", "delete", "sudo"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# List auth methods
|
||||||
|
path "sys/auth" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Manage secrets engines
|
||||||
|
path "sys/mounts/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# List existing secrets engines.
|
||||||
|
path "sys/mounts" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
19
policies/app_role_admin.hcl
Normal file
19
policies/app_role_admin.hcl
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Mount the AppRole auth method
|
||||||
|
path "sys/auth/approle" {
|
||||||
|
capabilities = [ "create", "read", "update", "delete", "sudo" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Configure the AppRole auth method
|
||||||
|
path "sys/auth/approle/*" {
|
||||||
|
capabilities = [ "create", "read", "update", "delete" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create and manage roles
|
||||||
|
path "auth/approle/*" {
|
||||||
|
capabilities = [ "create", "read", "update", "delete", "list" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Write ACL policies
|
||||||
|
path "sys/policies/acl/*" {
|
||||||
|
capabilities = [ "create", "read", "update", "delete", "list" ]
|
||||||
|
}
|
||||||
13
policies/identity_admin_policy.hcl
Normal file
13
policies/identity_admin_policy.hcl
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Add identity admin role to the token
|
||||||
|
path "identity/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Override default policies for identity management
|
||||||
|
path "identity/entity/id/{{identity.entity.id}}" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "identity/entity/name/{{identity.entity.name}}" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list"]
|
||||||
|
}
|
||||||
7
policies/transit_unseal_policy.hcl
Normal file
7
policies/transit_unseal_policy.hcl
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
path "transit/decrypt/unseal-key" {
|
||||||
|
capabilities = ["update"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "transit/encrypt/unseal-key" {
|
||||||
|
capabilities = ["update"]
|
||||||
|
}
|
||||||
10
set-env
Normal file
10
set-env
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Check, if we have been sourced
|
||||||
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
|
echo "This script must be sourced, not executed!" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
export VAULT_ADDR='http://127.0.0.1:8200'
|
||||||
|
export VAULT_TOKEN=$(jq -r .root_token config/vault-init.json | base64 -d | gpg -qd)
|
||||||
Reference in New Issue
Block a user