Keeper Of Secrets A Secure Key Management Solution Overhaul
Hey guys! Let's dive into a detailed discussion about overhauling our secrets management with a new solution called Keeper. This article will explore the current issues with key management, outline Keeper's goals and features, and delve into the technical aspects of its security architecture, CLI API, daemon implementation, and integration philosophy. We'll also cover a comprehensive implementation plan to ensure a smooth transition. Buckle up, this is gonna be a deep dive!
The Problem with Current Key Management Solutions
In many MCP (Machine Credential Provider) setups, existing key management solutions often fall short. The main issue? They're frequently not as secure as they should be. Some solutions involve practices like pasting keys directly into configuration files (e.g., mcps.json
), which is a big no-no from a security perspective. Others rely on key management systems that are clunky and intrusive, negatively impacting the user experience. We need a better way, and that's where Keeper comes in.
The ideal key management system for MCPs needs to tick several boxes. Firstly, it must keep your keys super safe. This means secrets should stay local to the system, be ephemeral (no lingering in-memory caches), use second-layer encryption, and be decryptable only on the machine the MCP is running on. Device-specific key derivation is also crucial to prevent secrets from being accessed on different machines. Secondly, it should operate seamlessly in the background, just like the MCP itself. Thirdly, it should only prompt you for keys when absolutely necessary. Authenticating once for access to all keys, using a non-intrusive method (like an environment variable), is a must. Finally, a sessionless design, where derived keys are stored like SSH keys for service restarts, adds an extra layer of convenience and security.
Keeper's Goals: Safe, Seamless, and Secure
Keeper aims to address these shortcomings with a focus on the following core principles:
- Security First: The primary goal is to ensure the utmost security for your secrets. This means protecting them from unauthorized access and minimizing the risk of exposure.
- User-Friendly Experience: Key management should be seamless and intuitive, avoiding unnecessary friction for the user. No one wants to jump through hoops just to access their secrets.
- Automated and Unobtrusive: Ideally, the system should work behind the scenes, requiring minimal manual intervention. Think set it and forget it!
- Flexibility and Integration: Keeper should easily integrate with various services and tools, providing a consistent and secure way to manage secrets across your entire workflow.
Keeper CLI API: Your Command-Line Companion
To interact with Keeper, we'll use a command-line interface (CLI). The keeper
CLI provides a set of commands for managing your secrets. Let's explore the available commands and their functionalities.
keeper -h
Secrets management for Kernelle, the AI toolshed.
usage: keeper <command>
Commands:
store Stores a secret
read Retrieves a secret
ls, list List available secrets
Options:
-h, --help Display this help section
--version Displays the version of this tool
The main commands are store
, read
, and list
, each serving a specific purpose in secrets management. The -h
flag displays help information, and --version
shows the tool's version.
Storing Secrets with keeper store
The keeper store
command is used to securely store your secrets. Let's break down its usage and options:
keeper store -h
Stores a secret
usage: keeper store [-g <group-name>] <secret-name> [<secret>]
Arguments:
<secret-name> The key/name to store the secret as. Good names use-bash-safe-naming patterns.
<secret> The actual secret to save. If not provided, will prompt securely.
Options
-g, --group <group-name> The group to store the secret under. Good group names use-bash-safe-naming patterns.
-h, --help Displays this help section
<secret-name>
: This argument specifies the name or key you want to associate with the secret. It's recommended to use bash-safe naming patterns for these names.<secret>
: This is the actual secret value you want to store. If you don't provide it directly in the command, Keeper will prompt you securely to enter it.-g, --group <group-name>
: This option lets you organize your secrets into groups. Grouping secrets makes them easier to manage and retrieve. Again, bash-safe naming patterns are recommended for group names.
For example, to store a GitHub token, you might use a command like this:
keeper store -g github token <your_github_token>
Or, if you prefer to be prompted for the secret:
keeper store -g github token
Reading Secrets with keeper read
To retrieve a stored secret, you'll use the keeper read
command:
keeper read -h
Retrieves a secret
usage: keeper read [-g <group-name>] <secret-name>
Arguments:
<secret-name> The key/name of the secret. Good names use-bash-safe-naming patterns.
Options:
-g, --group <group-name> The group the secret is stored under. Good group names use-bash-safe-naming patterns.
-h, --help Displays this help section
<secret-name>
: This argument specifies the name of the secret you want to retrieve.-g, --group <group-name>
: This option allows you to specify the group the secret belongs to. If you don't specify a group, Keeper will look for the secret in the default group.
For example, to read the GitHub token we stored earlier, you would use:
keeper read -g github token
Listing Secrets with keeper list
The keeper list
command is handy for getting an overview of your stored secrets:
keeper ls, keeper list
Lists available secrets in a POSIX friendly manner. eg:
GROUP SECRET NAME
general secret-1
general secret-2
general ...
general secret-n
group-name grouped-secret-1
group-name grouped-secret-2
group-name ...
Options:
-g, --group Filter the listing by group. If the group does not exist, no output will be provided.
-h, --help Displays this help section
This command lists secrets in a POSIX-friendly format, making it easy to parse the output in scripts. It displays secrets in a tabular format, showing the group and secret name. The -g, --group
option lets you filter the list by a specific group. If the group doesn't exist, no output will be shown.
For instance, to list all secrets in the github
group:
keeper list -g github
Security Architecture: A Fortress for Your Secrets
Keeper's security architecture is designed with multiple layers of protection to ensure the confidentiality and integrity of your secrets. Let's break down the key components:
Key Derivation: Building the Foundation
The master key, the cornerstone of Keeper's security, is derived from two crucial components:
- User's System Password: Your password acts as a primary factor in securing your secrets. You'll be prompted for it only once, and then the derived key is cached for future use. This ensures that your secrets are protected even if the device itself is compromised.
- Device-Specific Fingerprint: This fingerprint acts like a unique identifier for your machine, composed of hardware UUID and OS identifiers. This makes the key derivation process specific to each device, preventing secrets from being accessed on different machines. It's designed to be robust against minor upgrades, so you won't have to re-authenticate every time you update your system.
To combine these inputs, Keeper uses a strong Key Derivation Function (KDF) such as Argon2 or PBKDF2. These algorithms are designed to be computationally expensive, making it extremely difficult for attackers to crack the key even if they obtain a copy of the encrypted secrets. The device fingerprint serves as an implicit salt, further preventing rainbow table attacks across different devices.
The derived key is stored securely in ~/.kernelle/keeper.key
, similar to how SSH private keys are managed. This file has restricted permissions (600), meaning only the user can read and write to it. This key file is reused for service restarts, so you don't have to enter your password every time a service needs a secret. The user will only be prompted for their password if the derived key doesn't exist or is invalid, ensuring a smooth and secure experience.
Encryption: Shielding Your Secrets at Rest
Secrets themselves are encrypted using the industry-standard AES-256-GCM algorithm when stored on disk. This provides a robust level of protection against unauthorized access. The encrypted blobs are stored in ~/.kernelle/secrets.json
. Each secret has its own unique nonce (a random value), which is crucial for AES-GCM security. This prevents attacks that could exploit patterns in the encryption process. No separate salt is needed because the device fingerprint already provides uniqueness.
A critical aspect of Keeper's design is that there is no persistent in-memory credential cache. Secrets are ephemeral, meaning they are only decrypted when needed and then immediately discarded from memory. This significantly reduces the attack surface, as there's no long-lived decrypted data for an attacker to target.
Device Changes: Handling Migrations and Updates
Keeper is designed to handle device changes gracefully. If your system password changes, Keeper will re-derive the key and re-encrypt all your secrets. This ensures that your secrets remain protected even if your password is changed. A migration tool will also be available for device transfers or major hardware changes. This will allow you to securely move your secrets to a new machine without compromising their security. The device fingerprint is designed to be stable across minor system updates, so you won't have to re-authenticate every time you install a patch.
Memory Security: Keeping Secrets Safe in Memory
Keeper implements several measures to protect secrets while they are in memory. Secrets are zeroed from memory immediately after use, ensuring that no sensitive data lingers in memory longer than necessary. There is no long-lived storage of decrypted values. This minimizes the risk of an attacker being able to extract secrets from memory. Secure memory handling practices are employed throughout the codebase, reducing the likelihood of memory leaks or other vulnerabilities.
Keeper Daemon: A Secure Key Holder
To enhance security and reduce the need for frequent password prompts, Keeper utilizes a daemon process called keeper-daemon
. Let's explore its purpose, responsibilities, and architecture.
Purpose: Eliminating Password Prompts
The primary goal of the keeper-daemon
is to hold the derived master key in memory, eliminating the need for repeated password prompts. This significantly improves the user experience without compromising security. By keeping the key in memory, services can access secrets quickly and efficiently, without requiring user interaction.
Responsibilities: Focused and Secure
The keeper-daemon
has a very specific and limited set of responsibilities:
- Key Storage Only: The daemon's sole purpose is to hold the derived master key in secure memory. It does not handle any other aspects of secret management.
- Simple IPC: The daemon communicates with other processes via a Unix socket, responding to