NetStacksNetStacks

Credential Vault

TeamsEnterprise

Centralized, encrypted storage for all network credentials with AES-256-GCM encryption, Argon2id key derivation, and zero-standing-privileges access.

Overview

The Credential Vault is the centralized, encrypted storage system at the heart of NetStacks credential management. Every password, SSH key, certificate, API token, and SNMP community string used to access network devices is stored in the vault and encrypted at rest before it ever touches disk.

The vault exists because network teams managing hundreds or thousands of devices cannot afford to scatter credentials across spreadsheets, password managers not designed for machine-to-machine access, or individual engineers' laptops. A single, purpose-built vault ensures that credentials are encrypted, auditable, and accessible only to authorized users and automated processes.

  • AES-256-GCM encryption at rest for all stored secrets
  • Argon2id key derivation for the master encryption key
  • Zero-standing-privileges model — users never see raw credentials
  • Role-based access control through credential folders
  • Full audit logging for every credential access event
  • Support for SSH passwords, SSH keys, SSH certificates, API tokens, SNMP communities, and generic secrets

How It Works

Encryption at Rest

Every credential stored in the vault is encrypted using AES-256-GCM (Galois/Counter Mode), an authenticated encryption algorithm that provides both confidentiality and integrity. Each credential gets a unique 96-bit initialization vector (IV), so identical plaintext values produce different ciphertext. The encrypted bytes are stored in the encrypted_secret column alongside optionalencrypted_enable_secret for devices that require a separate privileged mode password.

Master Key Derivation

The vault master key is derived from the VAULT_MASTER_KEY environment variable using Argon2id, a memory-hard key derivation function resistant to GPU and ASIC brute-force attacks. Argon2id combines the data-dependent access pattern of Argon2d (resistant to GPU attacks) with the data-independent access pattern of Argon2i (resistant to side-channel attacks). The derived 256-bit key is held in memory only while the Controller process is running.

Zero-Standing-Privileges

What are zero-standing-privileges?

Zero-standing-privileges means that no user, regardless of their role, has persistent access to view raw credential values. When connecting to a device, the Controller retrieves the encrypted credential, decrypts it in memory, uses it to establish the SSH or SNMP session on behalf of the user, and then discards the plaintext. Users interact with credentials by reference (UUID) rather than by value.

Password reveal is gated behind the can_view_password permission on credential folder access grants. Even when a user has this permission, every reveal action creates an audit log entry recording who viewed what and when.

Role-Based Access Control

Access to credentials is managed through credential folders. Each folder can be shared with one or more roles, and each role grant specifies whether members can only use the credential (for connections) or also reveal the raw value. Folder permissions cascade to sub-folders, so granting access to a parent folder automatically extends to its children.

Audit Logging

Every credential operation — creation, update, deletion, use during connection, and password reveal — generates an audit log entry. Audit logs record the user, timestamp, action, credential ID, and source IP address. Logs are immutable and cannot be deleted by any user, including administrators.

Step-by-Step Guide

Step 1: Initial Vault Setup and Master Key Configuration

The vault is initialized automatically when the Controller starts with a validVAULT_MASTER_KEY environment variable. Set this value in your deployment configuration:

vault-setup.shbash
# Generate a strong master key (32+ characters recommended)
openssl rand -base64 32

# Add to your .env file (never commit this to version control)
VAULT_MASTER_KEY=aG9wZSB5b3UgZGlkbnQgdGhpbmsgdGhpcyB3YXMgcmVhbA==
Protect your master key

If the master key is lost, all credentials in the vault become permanently unrecoverable. Store a backup of this key in a separate, secure location such as a hardware security module (HSM) or your organization's enterprise secrets manager.

Step 2: Create Your First Credential (SSH Password)

  1. Navigate to Credentials in the Admin UI sidebar
  2. Click Add Credential
  3. Select type: SSH Password
  4. Enter a descriptive name (e.g., "Core Router Admin — DC1")
  5. Enter the username and password
  6. Optionally enter an enable/privileged mode password
  7. Select a folder to organize the credential
  8. Click Save — the password is encrypted immediately

Step 3: Assign a Credential to a Device

When adding or editing a device, select the credential from the dropdown. The device stores only the credential's UUID reference, never the raw password.

  1. Navigate to Devices → Add Device or edit an existing device
  2. In the Credentials section, select the credential by name
  3. Save the device — connections will now use this credential automatically

Step 4: Rotate Credentials

  1. Navigate to Credentials and find the credential to rotate
  2. Click Edit
  3. Update the password or key material
  4. Click Save — the old encrypted value is overwritten
  5. All devices referencing this credential will use the new value on their next connection

Step 5: View Audit Logs for Credential Access

  1. Navigate to Administration → Audit Logs
  2. Filter by Resource Type: Credential
  3. Review entries showing who accessed, viewed, or modified each credential
  4. Export logs as needed for compliance reporting

Code Examples

Create an SSH Password Credential

create-credential.shbash
curl -X POST https://controller.example.net/api/credentials \
  -H "Authorization: Bearer ${API_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Core Router Admin - DC1",
    "description": "Admin credentials for core-rtr-01 through core-rtr-04",
    "credential_type": "ssh_password",
    "username": "admin",
    "secret": "SuperSecretPassword123!",
    "enable_secret": "EnableMode456!",
    "folder_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "metadata": {
      "environment": "production",
      "site": "dc1"
    }
  }'
Note

The secret and enable_secret fields are encrypted by the Controller before storage. They are never returned in API responses. The response includes a credential_type and metadata but the encrypted fields are omitted.

List Credentials in a Folder

list-credentials.shbash
curl https://controller.example.net/api/credentials?folder_id=a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer ${API_TOKEN}"

# Response (secrets are never included):
# {
#   "credentials": [
#     {
#       "id": "f7e8d9c0-b1a2-3456-7890-abcdef123456",
#       "name": "Core Router Admin - DC1",
#       "credential_type": "ssh_password",
#       "username": "admin",
#       "folder_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
#       "expires_at": null,
#       "created_at": "2025-01-15T10:30:00Z"
#     }
#   ]
# }

Reference a Credential When Adding a Device

add-device-with-credential.shbash
curl -X POST https://controller.example.net/api/devices \
  -H "Authorization: Bearer ${API_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "hostname": "core-rtr-01.dc1.example.net",
    "ip_address": "10.0.1.1",
    "device_type": "cisco_ios_xe",
    "credential_id": "f7e8d9c0-b1a2-3456-7890-abcdef123456",
    "port": 22
  }'

The device stores the credential's UUID. When connecting, the Controller decrypts the credential in memory and uses it for the SSH session without ever exposing the raw value to the user or the Terminal.

Questions & Answers

Q: What encryption does the credential vault use?
A: The vault uses AES-256-GCM (Galois/Counter Mode) for all credential encryption. Each credential receives a unique 96-bit initialization vector, ensuring that identical plaintext values produce different ciphertext. The 256-bit encryption key is derived from the master key using Argon2id.
Q: How is the master key protected?
A: The master key is provided via the VAULT_MASTER_KEY environment variable and processed through Argon2id key derivation to produce the actual encryption key. The derived key exists only in the Controller process memory and is never written to disk. In production, use your platform's secrets manager (AWS Secrets Manager, HashiCorp Vault, Azure Key Vault) to inject this value.
Q: What are zero-standing-privileges?
A: Zero-standing-privileges means no user has persistent access to view raw credential values. When a connection is needed, the Controller decrypts the credential in memory, uses it to establish the session on behalf of the user, and discards the plaintext immediately after. Users reference credentials by UUID, not by their actual values.
Q: Who can access credentials in the vault?
A: Access is controlled through credential folders. Each folder can be shared with roles, and each role grant specifies whether members can use credentials (for device connections) or also reveal raw values. Folder permissions cascade to sub-folders. Only users whose roles have been granted access to a credential's folder can use that credential.
Q: How do I rotate credentials?
A: Edit the credential in the Admin UI or via the API and update the password or key material. The old encrypted value is overwritten with the new one. All devices referencing this credential will automatically use the new value on their next connection — no device-side changes are needed.
Q: What happens if the master key is lost?
A: All credentials in the vault become permanently unrecoverable. The AES-256-GCM encryption cannot be reversed without the master key. Always maintain a secure backup of the VAULT_MASTER_KEY value in a separate system such as a hardware security module or enterprise secrets manager.
Q: Are credentials backed up?
A: Credentials are stored in PostgreSQL and are included in standard database backups. However, the backup data contains only the encrypted ciphertext. To restore credentials from a backup, you must also have the originalVAULT_MASTER_KEY. Without the master key, backed-up credentials are useless ciphertext.

Troubleshooting

Vault sealed or locked state

If the Controller starts without a valid VAULT_MASTER_KEY environment variable, the vault enters a sealed state. All credential operations will fail with an error indicating the vault is not initialized. Set the environment variable and restart the Controller.

check-vault-key.shbash
# Verify the environment variable is set
docker exec netstacks-api-1 printenv VAULT_MASTER_KEY | wc -c
# Expected: a number greater than 0

# If missing, update your docker-compose.yml or .env file and restart
docker compose restart api

Master key mismatch after restore

If you restore a database backup but use a different master key than the one used when the credentials were created, all decryption attempts will fail. The Controller will log AES-GCM authentication tag verification errors. Ensure you restore both the database and the correct master key together.

Permission denied accessing credentials

If a user receives a permission denied error when trying to use a credential:

  • Verify the credential is in a folder the user's role has access to
  • Check that the role grant exists in Credential Folders → Access
  • If trying to reveal a password, confirm the role grant has can_view_password enabled
  • Check the audit logs for the specific denial event

Credential not found when connecting to a device

If a device connection fails with a credential-not-found error:

  • Verify the credential still exists (it may have been deleted)
  • Check if the credential has expired (expires_at field)
  • Confirm the device's credential_id matches a valid credential UUID
  • For personal vault credentials, ensure the connecting user owns the credential

Learn more about specific credential types and related features:

  • SSH Passwords & Keys — Store SSH passwords and manage key pairs (RSA, ECDSA, Ed25519)
  • SSH Certificates — Configure the built-in SSH CA for short-lived certificate-based access
  • Credential Folders — Organize credentials with hierarchical folders and role-based sharing
  • Personal Vaults — Per-user private credential storage for individual SSH keys and passwords
  • Adding Devices — Associate credentials with devices for automated SSH connections
  • Audit Logs — Review all credential access events for compliance and security