531 lines
12 KiB
Markdown
531 lines
12 KiB
Markdown
|
|
# Secrets Management System - Configuration Guide
|
||
|
|
|
||
|
|
**Status**: Production Ready
|
||
|
|
**Date**: 2025-11-19
|
||
|
|
**Version**: 1.0.0
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
The provisioning system supports secure SSH key retrieval from multiple secret sources, eliminating hardcoded filesystem dependencies and enabling enterprise-grade security. SSH keys are retrieved from configured secret sources (SOPS, KMS, RustyVault) with automatic fallback to local-dev mode for development environments.
|
||
|
|
|
||
|
|
## Secret Sources
|
||
|
|
|
||
|
|
### 1. SOPS (Secrets Operations)
|
||
|
|
|
||
|
|
Age-based encrypted secrets file with YAML structure.
|
||
|
|
|
||
|
|
**Pros**:
|
||
|
|
|
||
|
|
- ✅ Age encryption (modern, performant)
|
||
|
|
- ✅ Easy to version in Git (encrypted)
|
||
|
|
- ✅ No external services required
|
||
|
|
- ✅ Simple YAML structure
|
||
|
|
|
||
|
|
**Cons**:
|
||
|
|
|
||
|
|
- ❌ Requires Age key management
|
||
|
|
- ❌ No key rotation automation
|
||
|
|
|
||
|
|
**Environment Variables**:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
PROVISIONING_SECRET_SOURCE=sops
|
||
|
|
PROVISIONING_SOPS_ENABLED=true
|
||
|
|
PROVISIONING_SOPS_SECRETS_FILE=/path/to/secrets.enc.yaml
|
||
|
|
PROVISIONING_SOPS_AGE_KEY_FILE=$HOME/.age/provisioning
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
**Secrets File Structure** (provisioning/secrets.enc.yaml):
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# Encrypted with sops
|
||
|
|
ssh:
|
||
|
|
web-01:
|
||
|
|
ubuntu: /path/to/id_rsa
|
||
|
|
root: /path/to/root_id_rsa
|
||
|
|
db-01:
|
||
|
|
postgres: /path/to/postgres_id_rsa
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
**Setup Instructions**:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 1. Install sops and age
|
||
|
|
brew install sops age
|
||
|
|
|
||
|
|
# 2. Generate Age key (store securely!)
|
||
|
|
age-keygen -o $HOME/.age/provisioning
|
||
|
|
|
||
|
|
# 3. Create encrypted secrets file
|
||
|
|
cat > secrets.yaml << 'EOF'
|
||
|
|
ssh:
|
||
|
|
web-01:
|
||
|
|
ubuntu: ~/.ssh/provisioning_web01
|
||
|
|
db-01:
|
||
|
|
postgres: ~/.ssh/provisioning_db01
|
||
|
|
EOF
|
||
|
|
|
||
|
|
# 4. Encrypt with sops
|
||
|
|
sops -e -i secrets.yaml
|
||
|
|
|
||
|
|
# 5. Rename to enc version
|
||
|
|
mv secrets.yaml provisioning/secrets.enc.yaml
|
||
|
|
|
||
|
|
# 6. Configure environment
|
||
|
|
export PROVISIONING_SECRET_SOURCE=sops
|
||
|
|
export PROVISIONING_SOPS_SECRETS_FILE=$(pwd)/provisioning/secrets.enc.yaml
|
||
|
|
export PROVISIONING_SOPS_AGE_KEY_FILE=$HOME/.age/provisioning
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
### 2. KMS (Key Management Service)
|
||
|
|
|
||
|
|
AWS KMS or compatible key management service.
|
||
|
|
|
||
|
|
**Pros**:
|
||
|
|
|
||
|
|
- ✅ Cloud-native security
|
||
|
|
- ✅ Automatic key rotation
|
||
|
|
- ✅ Audit logging built-in
|
||
|
|
- ✅ High availability
|
||
|
|
|
||
|
|
**Cons**:
|
||
|
|
|
||
|
|
- ❌ Requires AWS account/credentials
|
||
|
|
- ❌ API calls add latency (~50 ms)
|
||
|
|
- ❌ Cost per API call
|
||
|
|
|
||
|
|
**Environment Variables**:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
PROVISIONING_SECRET_SOURCE=kms
|
||
|
|
PROVISIONING_KMS_ENABLED=true
|
||
|
|
PROVISIONING_KMS_REGION=us-east-1
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
**Secret Storage Pattern**:
|
||
|
|
|
||
|
|
```plaintext
|
||
|
|
provisioning/ssh-keys/{hostname}/{username}
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
**Setup Instructions**:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 1. Create KMS key (one-time)
|
||
|
|
aws kms create-key \
|
||
|
|
--description "Provisioning SSH Keys" \
|
||
|
|
--region us-east-1
|
||
|
|
|
||
|
|
# 2. Store SSH keys in Secrets Manager
|
||
|
|
aws secretsmanager create-secret \
|
||
|
|
--name provisioning/ssh-keys/web-01/ubuntu \
|
||
|
|
--secret-string "$(cat ~/.ssh/provisioning_web01)" \
|
||
|
|
--region us-east-1
|
||
|
|
|
||
|
|
# 3. Configure environment
|
||
|
|
export PROVISIONING_SECRET_SOURCE=kms
|
||
|
|
export PROVISIONING_KMS_REGION=us-east-1
|
||
|
|
|
||
|
|
# 4. Ensure AWS credentials available
|
||
|
|
export AWS_PROFILE=provisioning
|
||
|
|
# or
|
||
|
|
export AWS_ACCESS_KEY_ID=...
|
||
|
|
export AWS_SECRET_ACCESS_KEY=...
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
### 3. RustyVault (Hashicorp Vault-Compatible)
|
||
|
|
|
||
|
|
Self-hosted or managed Vault instance for secrets.
|
||
|
|
|
||
|
|
**Pros**:
|
||
|
|
|
||
|
|
- ✅ Self-hosted option
|
||
|
|
- ✅ Fine-grained access control
|
||
|
|
- ✅ Multiple authentication methods
|
||
|
|
- ✅ Easy key rotation
|
||
|
|
|
||
|
|
**Cons**:
|
||
|
|
|
||
|
|
- ❌ Requires Vault instance
|
||
|
|
- ❌ More operational overhead
|
||
|
|
- ❌ Network latency
|
||
|
|
|
||
|
|
**Environment Variables**:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
PROVISIONING_SECRET_SOURCE=vault
|
||
|
|
PROVISIONING_VAULT_ENABLED=true
|
||
|
|
PROVISIONING_VAULT_ADDRESS=http://localhost:8200
|
||
|
|
PROVISIONING_VAULT_TOKEN=hvs.CAESIAoICQ...
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
**Secret Storage Pattern**:
|
||
|
|
|
||
|
|
```plaintext
|
||
|
|
GET /v1/secret/ssh-keys/{hostname}/{username}
|
||
|
|
# Returns: {"key_content": "-----BEGIN OPENSSH PRIVATE KEY-----..."}
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
**Setup Instructions**:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 1. Start Vault (if not already running)
|
||
|
|
docker run -p 8200:8200 \
|
||
|
|
-e VAULT_DEV_ROOT_TOKEN_ID=provisioning \
|
||
|
|
vault server -dev
|
||
|
|
|
||
|
|
# 2. Create KV v2 mount (if not exists)
|
||
|
|
vault secrets enable -version=2 -path=secret kv
|
||
|
|
|
||
|
|
# 3. Store SSH key
|
||
|
|
vault kv put secret/ssh-keys/web-01/ubuntu \
|
||
|
|
key_content=@~/.ssh/provisioning_web01
|
||
|
|
|
||
|
|
# 4. Configure environment
|
||
|
|
export PROVISIONING_SECRET_SOURCE=vault
|
||
|
|
export PROVISIONING_VAULT_ADDRESS=http://localhost:8200
|
||
|
|
export PROVISIONING_VAULT_TOKEN=provisioning
|
||
|
|
|
||
|
|
# 5. Create AppRole for production
|
||
|
|
vault auth enable approle
|
||
|
|
vault write auth/approle/role/provisioning \
|
||
|
|
token_ttl=1h \
|
||
|
|
token_max_ttl=4h
|
||
|
|
vault read auth/approle/role/provisioning/role-id
|
||
|
|
vault write -f auth/approle/role/provisioning/secret-id
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
### 4. Local-Dev (Fallback)
|
||
|
|
|
||
|
|
Local filesystem SSH keys (development only).
|
||
|
|
|
||
|
|
**Pros**:
|
||
|
|
|
||
|
|
- ✅ No setup required
|
||
|
|
- ✅ Fast (local filesystem)
|
||
|
|
- ✅ Works offline
|
||
|
|
|
||
|
|
**Cons**:
|
||
|
|
|
||
|
|
- ❌ NOT for production
|
||
|
|
- ❌ Hardcoded filesystem dependency
|
||
|
|
- ❌ No key rotation
|
||
|
|
|
||
|
|
**Environment Variables**:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
PROVISIONING_ENVIRONMENT=local-dev
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
**Behavior**:
|
||
|
|
|
||
|
|
Standard paths checked (in order):
|
||
|
|
|
||
|
|
1. `$HOME/.ssh/id_rsa`
|
||
|
|
2. `$HOME/.ssh/id_ed25519`
|
||
|
|
3. `$HOME/.ssh/provisioning`
|
||
|
|
4. `$HOME/.ssh/provisioning_rsa`
|
||
|
|
|
||
|
|
## Auto-Detection Logic
|
||
|
|
|
||
|
|
When `PROVISIONING_SECRET_SOURCE` is not explicitly set, the system auto-detects in this order:
|
||
|
|
|
||
|
|
```plaintext
|
||
|
|
1. PROVISIONING_SOPS_ENABLED=true or PROVISIONING_SOPS_SECRETS_FILE set?
|
||
|
|
→ Use SOPS
|
||
|
|
2. PROVISIONING_KMS_ENABLED=true or PROVISIONING_KMS_REGION set?
|
||
|
|
→ Use KMS
|
||
|
|
3. PROVISIONING_VAULT_ENABLED=true or both VAULT_ADDRESS and VAULT_TOKEN set?
|
||
|
|
→ Use Vault
|
||
|
|
4. Otherwise
|
||
|
|
→ Use local-dev (with warnings in production environments)
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
## Configuration Matrix
|
||
|
|
|
||
|
|
| Secret Source | Env Variables | Enabled in |
|
||
|
|
|---|---|---|
|
||
|
|
| **SOPS** | `PROVISIONING_SOPS_*` | Development, Staging, Production |
|
||
|
|
| **KMS** | `PROVISIONING_KMS_*` | Staging, Production (with AWS) |
|
||
|
|
| **Vault** | `PROVISIONING_VAULT_*` | Development, Staging, Production |
|
||
|
|
| **Local-dev** | `PROVISIONING_ENVIRONMENT=local-dev` | Development only |
|
||
|
|
|
||
|
|
## Production Recommended Setup
|
||
|
|
|
||
|
|
### Minimal Setup (Single Source)
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Using Vault (recommended for self-hosted)
|
||
|
|
export PROVISIONING_SECRET_SOURCE=vault
|
||
|
|
export PROVISIONING_VAULT_ADDRESS=https://vault.example.com:8200
|
||
|
|
export PROVISIONING_VAULT_TOKEN=hvs.CAESIAoICQ...
|
||
|
|
export PROVISIONING_ENVIRONMENT=production
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
### Enhanced Setup (Fallback Chain)
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Primary: Vault
|
||
|
|
export PROVISIONING_VAULT_ADDRESS=https://vault.primary.com:8200
|
||
|
|
export PROVISIONING_VAULT_TOKEN=hvs.CAESIAoICQ...
|
||
|
|
|
||
|
|
# Fallback: SOPS
|
||
|
|
export PROVISIONING_SOPS_SECRETS_FILE=/etc/provisioning/secrets.enc.yaml
|
||
|
|
export PROVISIONING_SOPS_AGE_KEY_FILE=/etc/provisioning/.age/key
|
||
|
|
|
||
|
|
# Environment
|
||
|
|
export PROVISIONING_ENVIRONMENT=production
|
||
|
|
export PROVISIONING_SECRET_SOURCE=vault # Explicit: use Vault first
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
### High-Availability Setup
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Use KMS (managed service)
|
||
|
|
export PROVISIONING_SECRET_SOURCE=kms
|
||
|
|
export PROVISIONING_KMS_REGION=us-east-1
|
||
|
|
export AWS_PROFILE=provisioning-admin
|
||
|
|
|
||
|
|
# Or use Vault with HA
|
||
|
|
export PROVISIONING_VAULT_ADDRESS=https://vault-ha.example.com:8200
|
||
|
|
export PROVISIONING_VAULT_NAMESPACE=provisioning
|
||
|
|
export PROVISIONING_ENVIRONMENT=production
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
## Validation & Testing
|
||
|
|
|
||
|
|
### Check Configuration
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Nushell
|
||
|
|
provisioning secrets status
|
||
|
|
|
||
|
|
# Show secret source and configuration
|
||
|
|
provisioning secrets validate
|
||
|
|
|
||
|
|
# Detailed diagnostics
|
||
|
|
provisioning secrets diagnose
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
### Test SSH Key Retrieval
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Test specific host/user
|
||
|
|
provisioning secrets get-key web-01 ubuntu
|
||
|
|
|
||
|
|
# Test all configured hosts
|
||
|
|
provisioning secrets validate-all
|
||
|
|
|
||
|
|
# Dry-run SSH with retrieved key
|
||
|
|
provisioning ssh --test-key web-01 ubuntu
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
## Migration Path
|
||
|
|
|
||
|
|
### From Local-Dev to SOPS
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 1. Create SOPS secrets file with existing keys
|
||
|
|
cat > secrets.yaml << 'EOF'
|
||
|
|
ssh:
|
||
|
|
web-01:
|
||
|
|
ubuntu: ~/.ssh/provisioning_web01
|
||
|
|
db-01:
|
||
|
|
postgres: ~/.ssh/provisioning_db01
|
||
|
|
EOF
|
||
|
|
|
||
|
|
# 2. Encrypt with Age
|
||
|
|
sops -e -i secrets.yaml
|
||
|
|
|
||
|
|
# 3. Move to repo
|
||
|
|
mv secrets.yaml provisioning/secrets.enc.yaml
|
||
|
|
|
||
|
|
# 4. Update environment
|
||
|
|
export PROVISIONING_SECRET_SOURCE=sops
|
||
|
|
export PROVISIONING_SOPS_SECRETS_FILE=$(pwd)/provisioning/secrets.enc.yaml
|
||
|
|
export PROVISIONING_SOPS_AGE_KEY_FILE=$HOME/.age/provisioning
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
### From SOPS to Vault
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 1. Decrypt SOPS file
|
||
|
|
sops -d provisioning/secrets.enc.yaml > /tmp/secrets.yaml
|
||
|
|
|
||
|
|
# 2. Import to Vault
|
||
|
|
vault kv put secret/ssh-keys/web-01/ubuntu key_content=@~/.ssh/provisioning_web01
|
||
|
|
|
||
|
|
# 3. Update environment
|
||
|
|
export PROVISIONING_SECRET_SOURCE=vault
|
||
|
|
export PROVISIONING_VAULT_ADDRESS=http://vault.example.com:8200
|
||
|
|
export PROVISIONING_VAULT_TOKEN=hvs.CAESIAoICQ...
|
||
|
|
|
||
|
|
# 4. Validate retrieval works
|
||
|
|
provisioning secrets validate-all
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
## Security Best Practices
|
||
|
|
|
||
|
|
### 1. Never Commit Secrets
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Add to .gitignore
|
||
|
|
echo "provisioning/secrets.enc.yaml" >> .gitignore
|
||
|
|
echo ".age/provisioning" >> .gitignore
|
||
|
|
echo ".vault-token" >> .gitignore
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
### 2. Rotate Keys Regularly
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# SOPS: Rotate Age key
|
||
|
|
age-keygen -o ~/.age/provisioning.new
|
||
|
|
# Update all secrets with new key
|
||
|
|
|
||
|
|
# KMS: Enable automatic rotation
|
||
|
|
aws kms enable-key-rotation --key-id alias/provisioning
|
||
|
|
|
||
|
|
# Vault: Set TTL on secrets
|
||
|
|
vault write -f secret/metadata/ssh-keys/web-01/ubuntu \
|
||
|
|
delete_version_after=2160h # 90 days
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
### 3. Restrict Access
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# SOPS: Protect Age key
|
||
|
|
chmod 600 ~/.age/provisioning
|
||
|
|
|
||
|
|
# KMS: Restrict IAM permissions
|
||
|
|
aws iam put-user-policy --user-name provisioning \
|
||
|
|
--policy-name ProvisioningSecretsAccess \
|
||
|
|
--policy-document file://kms-policy.json
|
||
|
|
|
||
|
|
# Vault: Use AppRole for applications
|
||
|
|
vault write auth/approle/role/provisioning \
|
||
|
|
token_ttl=1h \
|
||
|
|
secret_id_ttl=30m
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
### 4. Audit Logging
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# KMS: Enable CloudTrail
|
||
|
|
aws cloudtrail put-event-selectors \
|
||
|
|
--trail-name provisioning-trail \
|
||
|
|
--event-selectors ReadWriteType=All
|
||
|
|
|
||
|
|
# Vault: Check audit logs
|
||
|
|
vault audit list
|
||
|
|
|
||
|
|
# SOPS: Version control (encrypted)
|
||
|
|
git log -p provisioning/secrets.enc.yaml
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### SOPS Issues
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Test Age decryption
|
||
|
|
sops -d provisioning/secrets.enc.yaml
|
||
|
|
|
||
|
|
# Verify Age key
|
||
|
|
age-keygen -l ~/.age/provisioning
|
||
|
|
|
||
|
|
# Regenerate if needed
|
||
|
|
rm ~/.age/provisioning
|
||
|
|
age-keygen -o ~/.age/provisioning
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
### KMS Issues
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Test AWS credentials
|
||
|
|
aws sts get-caller-identity
|
||
|
|
|
||
|
|
# Check KMS key permissions
|
||
|
|
aws kms describe-key --key-id alias/provisioning
|
||
|
|
|
||
|
|
# List secrets
|
||
|
|
aws secretsmanager list-secrets --filters Name=name,Values=provisioning
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
### Vault Issues
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Check Vault status
|
||
|
|
vault status
|
||
|
|
|
||
|
|
# Test authentication
|
||
|
|
vault token lookup
|
||
|
|
|
||
|
|
# List secrets
|
||
|
|
vault kv list secret/ssh-keys/
|
||
|
|
|
||
|
|
# Check audit logs
|
||
|
|
vault audit list
|
||
|
|
vault read sys/audit
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
## FAQ
|
||
|
|
|
||
|
|
**Q: Can I use multiple secret sources simultaneously?**
|
||
|
|
A: Yes, configure multiple sources and set `PROVISIONING_SECRET_SOURCE` to specify primary. If primary fails, manual fallback to secondary is supported.
|
||
|
|
|
||
|
|
**Q: What happens if secret retrieval fails?**
|
||
|
|
A: System logs the error and fails fast. No automatic fallback to local filesystem (for security).
|
||
|
|
|
||
|
|
**Q: Can I cache SSH keys?**
|
||
|
|
A: Currently not, keys are retrieved fresh for each operation. Use local caching at OS level (ssh-agent) if needed.
|
||
|
|
|
||
|
|
**Q: How do I rotate keys?**
|
||
|
|
A: Update the secret in your configured source (SOPS/KMS/Vault) and retrieve fresh on next operation.
|
||
|
|
|
||
|
|
**Q: Is local-dev mode secure?**
|
||
|
|
A: No - it's development only. Production requires SOPS/KMS/Vault.
|
||
|
|
|
||
|
|
## Architecture
|
||
|
|
|
||
|
|
```plaintext
|
||
|
|
SSH Operation
|
||
|
|
↓
|
||
|
|
SecretsManager (Nushell/Rust)
|
||
|
|
↓
|
||
|
|
[Detect Source]
|
||
|
|
↓
|
||
|
|
┌─────────────────────────────────────┐
|
||
|
|
│ SOPS KMS Vault LocalDev
|
||
|
|
│ (Encrypted (AWS KMS (Self- (Filesystem
|
||
|
|
│ Secrets) Service) Hosted) Dev Only)
|
||
|
|
│
|
||
|
|
└─────────────────────────────────────┘
|
||
|
|
↓
|
||
|
|
Return SSH Key Path/Content
|
||
|
|
↓
|
||
|
|
SSH Operation Completes
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
## Integration with SSH Utilities
|
||
|
|
|
||
|
|
SSH operations automatically use secrets manager:
|
||
|
|
|
||
|
|
```nushell
|
||
|
|
# Automatic secret retrieval
|
||
|
|
ssh-cmd-smart $settings $server false "command" $ip
|
||
|
|
# Internally:
|
||
|
|
# 1. Determine secret source
|
||
|
|
# 2. Retrieve SSH key for server.installer_user@ip
|
||
|
|
# 3. Execute SSH with retrieved key
|
||
|
|
# 4. Cleanup sensitive data
|
||
|
|
|
||
|
|
# Batch operations also integrate
|
||
|
|
ssh-batch-execute $servers $settings "command"
|
||
|
|
# Per-host: Retrieves key → executes → cleans up
|
||
|
|
```plaintext
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**For Support**: See `docs/user/TROUBLESHOOTING_GUIDE.md`
|
||
|
|
**For Integration**: See `provisioning/core/nulib/lib_provisioning/platform/secrets.nu`
|