dsec - Domain Secrets Manager
Domain Model
| Domain | Structure | Purpose |
|---|---|---|
d000 |
Nested ( |
Personal Infrastructure |
d001+ |
Nested or Flat ( |
Client/Organization work |
Categories (Nested Tiers)
| Category | Contents |
|---|---|
|
API keys, OAuth, webhooks, SaaS tokens |
|
Servers, VMs, containers, hypervisor |
|
ISE, firewalls, switches, routers, DNS |
|
SIEM, vulnerability scanners, threat intel |
|
Azure AD, Okta, LDAP, SSO, MFA |
|
PostgreSQL, Redis, MongoDB |
|
AWS, Azure, GCP, Cloudflare |
|
NAS, S3, backup credentials |
|
Crates.io, PyPI, NPM, Docker Hub |
|
GitHub Actions, GitLab CI, Jenkins |
|
Test device IDs, endpoint MACs, group IDs |
Commands
Core Commands
| Command | Description |
|---|---|
|
List all domains and their environments |
|
Initialize new domain (e.g., |
|
Add/update env file for domain tier |
|
Decrypt to directory or stdout |
|
Securely remove decrypted .env (shred -n 10) |
|
Display decrypted env to stdout (for review) |
|
Output export statements for eval |
|
Output unset statements to clear loaded secrets |
|
Edit encrypted env file |
|
View/edit domain registry |
Utility Commands (v2.0.0+)
| Command | Description |
|---|---|
|
Show overall secrets status (env loaded, domains, last access) |
|
Verify all encrypted files can be decrypted |
|
Display domain/environment tree structure |
|
Count secrets across domains |
|
Backup entire secrets directory to destination |
|
Show dsec version and codename |
|
Generate shell completions (bash/zsh/fish) |
Shell Wrappers (Recommended)
For maximum security, use shell wrappers instead of raw eval "$(dsec source …)".
First-Time Setup
# Add to your shell config
dsec shell-init >> ~/.zshrc # or ~/.bashrc
source ~/.zshrc
Domain Access Control
|
This feature enforces strict boundaries around client/third-party credentials to prevent unauthorized access or accidental disclosure. |
The Simple Rule
| Domain | What It Is | What You Can Access |
|---|---|---|
d000 |
Your personal infrastructure |
EVERYTHING (dev, staging, prod, network, app, etc.) |
d001, d002, … |
Client/work domains |
All standard tiers (lab, dev, staging, prod) |
Why This Exists
Protected credentials are subject to NDAs, contracts, and federal law. The domain access control system:
-
Separates personal and client credential namespaces
-
Logs all access attempts for audit purposes
-
Can be restricted to specific tiers when needed (e.g.,
DSEC_ALLOWED_TIERS="lab")
Attempting to access a tier not in the allowed list triggers a legal warning and is logged.
Restricting Access
To lock down client domains to specific tiers (e.g., lab-only for a shared machine):
# Restrict client domains to lab tier only
export DSEC_ALLOWED_TIERS="lab"
# Or disable domain locking entirely
export DSEC_DOMAIN_LOCK=false
Quick Reference
# These ALWAYS work (d000 = your stuff)
dsec show d000 dev/network # ✓
dsec show d000 prod/app # ✓
dsec edit d000 staging/identity # ✓
# These work for client domains (all standard tiers)
dsec show d001 dev/network # ✓
dsec show d001 staging # ✓
dsec show d001 prod # ✓
dsec show d001 lab # ✓
# If DSEC_ALLOWED_TIERS has been restricted to "lab":
dsec show d001 dev # ✗ BLOCKED
dsec show d001 prod # ✗ BLOCKED
DSEC_DOMAIN_LOCK=false dsec show d001 prod # ✓ (override)
Security Modes
dsec operates in two security modes:
| Mode | Behavior | When to Use |
|---|---|---|
strict (default) |
Requires wrapper functions, blocks raw |
Always (production) |
permissive |
Allows |
Legacy scripts, debugging |
Passphrase Protection
Add an extra authentication layer before any decrypt operation:
# Enable passphrase (prompts you to set one)
dsec set-passphrase
# Disable passphrase
dsec remove-passphrase
Directory Structure
~/.secrets/environments/domains/
├── .registry.age # Encrypted domain→name mapping
├── DOMAIN_INVENTORY.yaml.age # Schema documentation
├── d000/ # Personal Infrastructure
│ ├── dev/
│ │ ├── app.env.age # API keys, OAuth, SaaS
│ │ ├── network.env.age # ISE, firewalls, switches
│ │ ├── identity.env.age # Azure AD, Okta, LDAP
│ │ ├── storage.env.age # NAS, backup
│ │ ├── identifiers.env.age # Test IDs
│ │ └── ... # infra, security, db, cloud, registry, cicd
│ ├── staging/
│ │ └── (same structure)
│ └── prod/
│ └── (same structure)
├── d001/ # Client 1
│ ├── dev/
│ │ └── network.env.age
│ ├── staging/
│ │ └── network.env.age
│ └── prod/
│ └── network.env.age
└── d002/ # Client 2
└── ...
Examples
Add Secrets from Template
# Copy template to RAM
cp ~/.secrets/templates/network.env.example /dev/shm/temp.env
# Edit with your values
vim /dev/shm/temp.env
# Add to domain (encrypts automatically)
dsec add d001 prod/network /dev/shm/temp.env
# Say 'y' to shred source file
Load Secrets to Shell
# Using wrappers (RECOMMENDED)
dsource d000 dev/network
dsource d001 prod
# Legacy syntax (requires permissive mode)
eval "$(dsec source d000 dev/network)"
Security Features
| Feature | Implementation |
|---|---|
Temp files |
|
Cleanup |
|
Backups |
Automatic |
Change detection |
SHA256 hash comparison |
Audit logging |
|
Eval protection |
Blocks direct TTY output without eval |
Passphrase |
Optional authentication before decrypt |
Env File Format
Files use rest.nvim compatible format with @ prefix:
@VARIABLE_NAME = value
@ANOTHER_VAR = another value
dsec automatically strips the @ when sourcing to shell.
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
|
Unquoted glob chars in secrets |
Use double quotes: |
|
Strict mode active |
Use |
Passphrase prompt |
Passphrase protection enabled |
Enter passphrase or set |
Variables empty after load |
Wrong shell detected |
Override with |
Secrets visible |
Used |
Use |
Templates
Templates are located in ~/.secrets/templates/ and provide starting points for new secrets.
Network Template
The network.env.example template includes placeholders for:
| Section | Services |
|---|---|
Cisco ISE |
ERS API, OpenAPI, MnT, pxGrid, DataConnect, mTLS |
Switches |
Cisco IOS-XE (3560-CX, 3850, 9300, 9500) |
WLC |
Cisco 9800 RESTCONF API and SSH |
Firewalls |
pfSense, Palo Alto, Cisco FMC/FTD |
IPAM/Network Mgmt |
Infoblox WAPI, Cisco DNA Center, Cisco Prime Infrastructure |
netapi CLI aliases |
DNAC_HOST, PRIME_HOST, FMC_USER, INFOBLOX_HOST |
Using Templates
# Copy template to RAM
cp ~/.secrets/templates/network.env.example /dev/shm/temp.env
# Edit with your values
vim /dev/shm/temp.env
# Add to domain (auto-encrypts and shreds)
dsec add d001 dev/network /dev/shm/temp.env
netapi CLI Integration
Network secrets include aliases that map to what netapi CLI expects:
# These are set automatically when you load network secrets
DNAC_HOST={{DNAC_IP}}
PRIME_HOST={{PRIME_IP}}
FMC_USER={{FMC_API_USER}}
INFOBLOX_HOST={{INFOBLOX_GM_IP}}
After loading secrets, netapi commands work directly:
dsource d000 dev/network
netapi dnac get-devices
netapi prime get-alarms
netapi fmc get-policies
netapi infoblox get-networks