Skip to content
Open
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
344 changes: 344 additions & 0 deletions docs/cmds/values.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,344 @@
# safe values

The `values` command searches through your Vault secrets to find all secrets that contain specific values. This is particularly useful when you need to audit where certain values (like passwords, API keys, or tokens) are being used across your infrastructure.

## Usage

```
safe values [--keys] VALUE [VALUE ...] [PATH ...]
```

### Arguments

- `VALUE` - One or more exact values to search for (required)
- `PATH` - One or more paths to search under (optional, defaults to "secret")

### Options

- `--keys` - Show the specific keys containing the values (format: `<path>:<key>`)

### Output Format

**Without --keys (default):**
```
<path>
```
Shows only the paths of secrets containing any of the specified values.

**With --keys:**
```
<path>:<key>
```
Shows the specific location of each key containing a matching value.

Results are sorted alphabetically for consistent output.

## Examples

### Basic Search (Paths Only)

Search for a value across all secrets under the default path:

```bash
$ safe values "us-east-1"
secret/app/backend
secret/app/frontend
```

### Show Specific Keys

Use `--keys` to see which keys contain the values:

```bash
$ safe values --keys "prod-api-key-123"
secret/app/backend:region
secret/app/frontend:region
```

### Search Multiple Values

Search for any of several values at once:

```bash
$ safe values "postres" "admin" "root"
secret/app/db
secret/backup/db/username
secret/users/admin
secret/root/username
```

With keys:
```bash
$ safe values --keys "password123" "admin123"
secret/app/db:password
secret/backup/postgresql:admin_pass
secret/users/admin:password
secret/users/admin:old_password
```

### Search Specific Paths

Search only within specific paths:

```bash
$ safe values "admin" secret/users secret/admins
secret/admins/root
secret/users/alice
secret/users/bob
```

With keys:
```bash
$ safe values --keys "admin" secret/users secret/admins
secret/admins/root:username
secret/users/alice:role
secret/users/bob:permission
```

### Search with Special Characters

Values containing special characters work as expected:

```bash
$ safe values "[email protected]"
secret/config/smtp
secret/users/profile

$ safe values --keys "pass:word:123"
secret/test/creds:complex_password
```

### Empty Results

When no matches are found, the command returns empty output:

```bash
$ safe values "nonexistent-value"
```

## Common Use Cases

### 1. Password Audit

Find all locations where specific passwords are used:

```bash
$ safe values "MyOldPassword123" "MyOtherOldPass"
secret/app/db
secret/backup/postgresql
secret/legacy/system
```

Get specific details with --keys:
```bash
$ safe values --keys "MyOldPassword123"
secret/app/db:password
secret/backup/postgresql:admin_pass
secret/legacy/system:pwd
```

This helps identify secrets that need to be rotated.

### 2. API Key Management

Track where API keys are configured:

```bash
$ safe values "sk_live_4242424242424242" "pk_live_5353535353535353"
secret/production/stripe
secret/billing/processor
```

With details:
```bash
$ safe values --keys "sk_live_4242424242424242"
secret/production/stripe:secret_key
secret/billing/processor:api_key
```

### 3. Configuration Values

Find all services using specific configurations:

```bash
$ safe values "https://api.internal.company.com" "https://legacy-api.company.com"
secret/app/config
secret/services/auth
secret/monitoring/config
```

### 4. Compliance Checks

Verify that sensitive values aren't stored in unexpected locations:

```bash
$ safe values --keys "SSN-123-45-6789"
secret/test/data:sample_ssn # This shouldn't be in test!
```

### 5. Bulk Search

Search for multiple related values at once:

```bash
$ safe values "prod-db-pass" "staging-db-pass" "dev-db-pass" secret/databases/
secret/databases/production
secret/databases/staging
secret/databases/development
```

## Behavior Notes

### Version Handling

- Only searches the latest version of each secret
- Ignores deleted or destroyed secret versions
- For versioned backends (KV v2), only the current version is checked

### Performance

- The command walks the entire tree under the specified paths
- For large Vaults, consider searching specific paths rather than the entire tree
- Results are collected in memory and sorted before output

### Permissions

- Requires read access to the paths being searched
- Secrets you don't have permission to read will be silently skipped
- No error is shown for inaccessible paths during the search

### Special Characters

- The search values must match exactly (case-sensitive)
- Special characters in paths and keys are properly escaped in output
- Use quotes around values containing spaces or shell metacharacters
- Multiple values are searched with OR logic (finds secrets containing ANY of the values)

### Argument Parsing

- Values are specified first, followed by optional paths
- Paths are identified by containing "/" or being common mount points (secret, cubbyhole, sys)
- The command works backwards through arguments to identify paths
- Everything before the paths is treated as values to search for

## Examples with Setup

Here's a complete example showing setup and search:

```bash
# Create some test data
$ safe set secret/app/prod database_url="postgres://prod.db" api_key="abc123"
$ safe set secret/app/staging database_url="postgres://staging.db" api_key="abc123"
$ safe set secret/app/dev database_url="postgres://dev.db" api_key="xyz789"

# Search for the shared API key (paths only)
$ safe values "abc123"
secret/app/prod
secret/app/staging

# Search with key details
$ safe values --keys "abc123"
secret/app/prod:api_key
secret/app/staging:api_key

# Search for multiple values
$ safe values "abc123" "xyz789"
secret/app/dev
secret/app/prod
secret/app/staging

# Search for database URLs in production
$ safe values --keys "postgres://prod.db" secret/app/prod
secret/app/prod:database_url

# Clean up
$ safe delete secret/app/prod secret/app/staging secret/app/dev
```

## Comparison with Other Commands

- Use `safe find` or `safe search` (if available) to search by key names
- Use `safe tree --keys` to see all keys and their values in a tree format
- Use `safe paths` to list all secret paths without values
- Use `safe get` to retrieve specific secrets once found

## Error Handling

The command will return an error if:
- No value arguments are provided
- A specified path doesn't exist
- You don't have permission to access a specified path

Errors are reported to stderr, while results go to stdout, allowing for proper scripting:

```bash
# Redirect errors while capturing results
results=$(safe values "api-key" 2>/dev/null)
```

## Security Considerations

- The search values are provided on the command line and may be visible in process listings
- Consider using this command from scripts rather than interactively for sensitive values
- Results show paths (and optionally keys) but not the full secret values
- Command history may contain the searched values

## Integration Examples

### Bash Script for Rotation

```bash
#!/bin/bash
# Find all secrets using old API keys

OLD_KEYS=("sk_old_123" "sk_old_456" "sk_old_789")
echo "Secrets using old API keys:"
safe values "${OLD_KEYS[@]}" | while read -r path; do
echo " - $path"
done
```

With specific key details:
```bash
#!/bin/bash
# Find and list all keys using old API keys

OLD_KEY="sk_old_1234567890"
echo "Keys using old API key:"
safe values --keys "$OLD_KEY" | while read -r location; do
echo " - $location"
done
```

### Migration Helper

```bash
#!/bin/bash
# Find all database URLs pointing to old servers

OLD_DBS=("postgres://old1.company.com" "postgres://old2.company.com")
NEW_DB="postgres://new-server.company.com"

echo "Secrets to migrate:"
safe values "${OLD_DBS[@]}" | while read -r path; do
echo "Processing: $path"
# Would need to get, modify, and set the secret
done
```

### Audit Script

```bash
#!/bin/bash
# Audit for common weak passwords

WEAK_PASSWORDS=("password" "123456" "admin" "default" "changeme")
echo "Checking for weak passwords..."
results=$(safe values --keys "${WEAK_PASSWORDS[@]}" 2>/dev/null)
if [ -n "$results" ]; then
echo "WARNING: Weak passwords found:"
echo "$results"
else
echo "No weak passwords found."
fi
```
Loading