2025-07-12 15:13:40 +00:00
2025-06-28 22:56:05 +01:00
2025-06-28 22:56:05 +01:00
2025-06-28 22:56:05 +01:00
2025-06-28 22:55:17 +01:00
2025-06-28 22:56:05 +01:00
2025-06-28 22:56:05 +01:00
2025-07-12 15:12:57 +00:00
2025-06-28 22:56:05 +01:00
2025-06-28 22:56:05 +01:00
2025-07-12 15:13:40 +00:00
2025-06-28 22:56:05 +01:00

Key/Info Manager

A robust and secure Key/Info Management system designed for applications requiring controlled access to sensitive data. It features a WebSocket API for client applications and an HTTP admin panel for comprehensive management tasks. All stored secrets are encrypted at rest using AES-256-GCM.

Overview

The Key/Info Manager provides a centralized solution for storing, managing, and securely distributing secrets or configuration data to authorized client applications. It emphasizes security through data encryption, role-based access (via admin approval and group association), and secure communication protocols (when deployed with HTTPS/WSS).

Key Features

  • Secure Storage: Secrets are encrypted using AES-256-GCM. The master encryption key is derived from a user-provided password at server startup.
  • Admin UI Panel: A comprehensive web-based interface for:
    • Managing secret groups (create, rename, delete).
    • Managing secrets within groups (create, view, update, delete).
    • Managing client applications:
      • Viewing pending client registrations.
      • Approving or rejecting client registration requests.
      • Associating approved clients with specific secret groups to grant access.
      • Revoking client access.
    • Configuring WebSocket client auto-approval (for debugging/development).
  • WebSocket API: A secure and efficient API for client applications to:
    • Register themselves with the server.
    • Request secrets they are authorized to access (based on group association).
    • List all secret keys they are authorized to access.
  • Password Protection: Admin UI login and initial server setup (for encryption key) are protected by a master password.
  • CSRF Protection: Admin UI operations are protected against Cross-Site Request Forgery.
  • Rate Limiting: Both HTTP admin endpoints and WebSocket communications are rate-limited to mitigate abuse and brute-force attempts.
  • Configuration Management: Core settings like JWT secret and port configurations are manageable.
  • Data Persistence: Stores data (encrypted secrets, client info, group info) in local files.

Tech Stack

  • Backend: Node.js, Express.js
  • WebSocket Server: ws library
  • Templating: EJS for Admin UI
  • Core Libraries:
    • jsonwebtoken for JWT generation (Admin sessions)
    • csurf for CSRF protection
    • helmet for security headers
    • express-rate-limit for rate limiting
    • express-session for session management
    • dotenv for environment variable management
  • Cryptography: Node.js crypto module (AES-256-GCM for data encryption)
  • Development: TypeScript, Jest (for testing), Nodemon

Prerequisites

  • Node.js (v16.x or later recommended)
  • npm (Node Package Manager, typically included with Node.js)

Getting Started & Installation

  1. Clone the Repository (if applicable):

    git clone <repository_url>
    cd key_manager # Or your project directory name
    
  2. Install Dependencies: Navigate to the project root directory and run:

    npm install
    
  3. Configure Environment Variables: Create a .env file in the project root directory. This file is used to store sensitive information and configurations. It is crucial for security that this file is NOT committed to version control. Add it to your .gitignore if it's not already there.

    Essential Security Variables (add these to your .env file):

    # Master Password for data encryption and initial admin login
    # Choose a strong, unique password. This will be used to derive the data encryption key.
    # If not set, you will be prompted for it in the console on first run.
    MASTER_PASSWORD=your_very_strong_master_password_here
    
    # JWT Secret for signing authentication tokens for the Admin UI
    # Should be a long, random, and unique string.
    JWT_SECRET=your_super_random_jwt_secret_string_here_at_least_32_chars
    
    # Session Secret for Express sessions (used by CSRF protection)
    # Should also be a long, random, and unique string.
    SESSION_SECRET=another_super_random_session_secret_string_here
    

    Optional Configuration Variables (defaults are generally suitable for local development):

    # HTTP Port for the Admin UI (default: 3000, can also be set in data/runtime-config.json)
    HTTP_PORT=3000
    
    # WebSocket Port for client applications (default: 3001, can also be set in data/runtime-config.json)
    WS_PORT=3001
    
    # Data files path (defaults to 'data' directory in project root)
    # DATA_DIR=./data # Example, usually not needed to change
    
    # Config file path (defaults to 'data/runtime-config.json')
    # CONFIG_FILE_PATH=./data/runtime-config.json # Example
    

    Refer to src/lib/configManager.ts for how jwtSecret, httpPort, and wsPort can also be managed via data/runtime-config.json (which is auto-generated on first run if it doesn't exist). For production, setting secrets like JWT_SECRET and SESSION_SECRET via environment variables is generally recommended.

  4. Build TypeScript Code: Compile the TypeScript source files to JavaScript:

    npm run build
    

    This will create a dist directory with the compiled code.

Running the Application

  1. Start the Server: After building the code, run:

    npm start
    

    This command executes the compiled dist/main.js file.

  2. Development Mode (Optional): For development, you can use npm run dev. This script typically watches for TypeScript file changes, recompiles, and restarts the server automatically using nodemon.

    npm run dev
    
  3. First Run & Master Password:

    • If the MASTER_PASSWORD environment variable was not set in your .env file, the server will prompt you to enter and confirm a master password in the console during its first startup.
    • This password is critical: it's used to derive the encryption key for your secrets.json.enc data file. Choose a strong password and store it securely. Losing this password means losing access to all encrypted data.
    • A salt for deriving the master key will be generated and stored in data/masterkey.salt. This salt file should be backed up along with your encrypted data.
    • The encrypted data itself is stored in data/secrets.json.enc.
    • The application runtime configuration (like JWT secret if not overridden by env var, ports, etc.) is stored in data/runtime-config.json.

    Important: The data directory (containing secrets.json.enc, masterkey.salt, and runtime-config.json) should be backed up regularly and secured appropriately. It is gitignored by default.

Usage

Admin UI

The Admin UI provides a web interface for managing secrets, secret groups, and client applications.

  1. Access: Open your web browser and navigate to http://localhost:<HTTP_PORT>/admin (e.g., http://localhost:3000/admin if using the default port).

  2. Login: You will be prompted to log in. Use the MASTER_PASSWORD that you either set as an environment variable or entered in the console during the server's first startup.

  3. Key Management Areas:

    • Manage Secrets (Main Page / Secrets Tab):

      • Create Secret Groups: Define logical groups to organize your secrets.
      • Manage Existing Groups: View, rename, or delete secret groups. Deleting a group also deletes all secrets within it.
      • Add New Secrets: Create new secrets (key-value pairs) and assign them to an existing group. Values can be simple strings or complex JSON objects/arrays.
      • View/Manage Secrets within a Group: Drill down into a group to see its secrets, edit their values, or delete them.
      • Edit/Delete Individual Secrets: Modify the value of existing secrets or delete them from the system (this also removes them from their group).
    • Manage Clients (Clients Tab):

      • Pending Client Registrations: View client applications that have registered via the WebSocket API and are awaiting administrative approval.
        • Approve: Approves the client's registration. The client can then proceed to use the WebSocket API with its approved status.
        • Reject: Rejects the client's registration request.
      • Approved Clients: View already approved client applications.
        • Manage Groups (for Client): For each approved client, you can associate them with one or more secret groups. This grants the client access to all secrets within the associated groups.
        • Revoke Access: Deletes the client from the system, effectively revoking all their access.
      • WebSocket Settings (Debug):
        • Toggle the "Automatically Approve New WebSocket Registrations" setting. This is primarily for development or debugging and should generally be disabled in production environments.

WebSocket API

Client applications connect to the Key/Info Manager via WebSocket to register and request authorized secrets.

  • Connection URL: ws://localhost:<WS_PORT> (e.g., ws://localhost:3001)
  • Message Format: All messages (client-to-server and server-to-client) are JSON objects. A typical structure includes:
    • type: A string indicating the message type (e.g., REGISTER_CLIENT, ERROR).
    • payload: An object containing the data relevant to the message type.
    • code (Server-to-Client): A numerical response code (see WsResponseCodes below).
    • requestId (Optional, Client-to-Server & echoed in Server-to-Client): A client-generated ID to correlate requests and responses.

Common Server Response Codes (WsResponseCodes):

  • 2000 OK: General success.
  • 2001 REGISTRATION_SUBMITTED: Client registration successfully submitted, awaiting approval.
  • 4000 BAD_REQUEST: The request was malformed or missing required parameters.
  • 4001 UNAUTHORIZED: Client is not authorized for the requested action (e.g., not approved, wrong credentials, insufficient permissions).
  • 4004 NOT_FOUND: Requested resource (e.g., a specific secret) was not found.
  • 4005 CLIENT_NOT_REGISTERED: Client attempted an action before completing REGISTER_CLIENT.
  • 4006 CLIENT_REGISTRATION_EXPIRED: A pending client registration has expired.
  • 4029 RATE_LIMIT_EXCEEDED: Client has sent too many requests in a given timeframe.
  • 5000 INTERNAL_SERVER_ERROR: An unexpected error occurred on the server.

Key Message Flows:

  1. Server Welcome Message (Server to Client): Upon successful WebSocket connection, the server sends:

    {
      "type": "WELCOME",
      "code": 2000,
      "payload": { "detail": "Welcome! Please register your client using REGISTER_CLIENT message." }
    }
    
  2. Client Registration (Client to Server):

    • Purpose: New client applications must register to be recognized by the server.
    • Request:
      {
        "type": "REGISTER_CLIENT",
        "payload": {
          "clientName": "My Awesome Application",
          // "requestedSecretKeys": ["key1", "key2"] // Legacy field, group association is now preferred
        },
        "requestId": "client-req-001"
      }
      
    • Server Response (Success - Awaiting Approval):
      {
        "type": "REGISTRATION_ACK",
        "code": 2001, // REGISTRATION_SUBMITTED
        "payload": {
          "clientId": "server_generated_client_id", // For admin tracking
          "detail": "Registration for 'My Awesome Application' submitted. Awaiting admin approval. Your Client ID is server_generated_client_id."
        },
        "requestId": "client-req-001"
      }
      
      The client must then be approved in the Admin UI.
  3. Status Update Notification (Server to Client):

    • Purpose: After admin action (approval/rejection), the server notifies the specific client if connected.
    • Example (Approved):
      {
        "type": "STATUS_UPDATE",
        "code": 2000, // Or a more specific code if defined
        "payload": {
          "newStatus": "approved",
          "detail": "Client registration automatically approved (debug mode)." // Or admin approved
        }
      }
      
    • Example (Rejected):
      {
        "type": "STATUS_UPDATE",
        "code": 4001, // UNAUTHORIZED (or a specific "REJECTED" code)
        "payload": {
          "newStatus": "rejected",
          "detail": "Client registration was rejected by an administrator."
        }
      }
      
  4. Request Secret (Client to Server - Approved Clients Only):

    • Purpose: To request the value of a secret the client is authorized (via group association) to access.
    • Request:
      {
        "type": "REQUEST_SECRET",
        "payload": { "secretKey": "database_connection_string" },
        "requestId": "client-req-002"
      }
      
    • Server Response (Success):
      {
        "type": "SECRET_DATA",
        "code": 2000, // OK
        "payload": {
          "secretKey": "database_connection_string",
          "value": "the_actual_secret_value_here"
        },
        "requestId": "client-req-002"
      }
      
    • Server Response (Unauthorized):
      {
        "type": "ERROR",
        "code": 4001, // UNAUTHORIZED
        "payload": {
          "detail": "You are not authorized to access the secret key \"database_connection_string\"."
        },
        "requestId": "client-req-002"
      }
      
    • Server Response (Not Found):
      {
        "type": "ERROR",
        "code": 4004, // NOT_FOUND
        "payload": {
          "detail": "Secret key \"some_other_key\" not found on server, though client is authorized. Please contact admin."
        },
        "requestId": "client-req-003"
      }
      
  5. List Authorized Secrets (Client to Server - Approved Clients Only):

    • Purpose: To get a list of all secret keys the client is currently authorized to access.
    • Request:
      {
        "type": "LIST_AUTHORIZED_SECRETS",
        "requestId": "client-req-004"
      }
      
    • Server Response (Success):
      {
        "type": "AUTHORIZED_SECRETS_LIST",
        "code": 2000, // OK
        "payload": {
          "authorizedSecretKeys": ["key1", "key2", "database_connection_string"]
        },
        "requestId": "client-req-004"
      }
      

General Error Response (Server to Client): If a request fails for other reasons (e.g., malformed JSON, internal server error), a generic error is sent:

{
  "type": "ERROR",
  "code": "<appropriate_error_code>", // e.g., 4000, 5000
  "payload": { "detail": "A descriptive error message." },
  "requestId": "<client_provided_requestId_if_any>"
}

Security Considerations

Security is a primary focus of the Key/Info Manager. Please be aware of the following:

  • Master Password: The security of all encrypted data relies heavily on the strength and secrecy of your MASTER_PASSWORD. Choose a strong, unique password and protect it diligently. This password is used to derive the data encryption key.
  • JWT Secret (JWT_SECRET): This secret is used to sign JSON Web Tokens for Admin UI sessions. It must be kept confidential. If compromised, attackers could forge admin session tokens. Ensure it's a long, random string.
  • Session Secret (SESSION_SECRET): Used by Express session middleware, which is crucial for CSRF protection. This also needs to be a long, random, and unique string kept confidential.
  • Data Encryption: Secrets are encrypted at rest using AES-256-GCM. The salt used for key derivation is stored in data/masterkey.salt, and the encrypted data is in data/secrets.json.enc. Protect these files appropriately.
  • HTTPS/WSS: For any production deployment, it is critical to run both the HTTP Admin UI and the WebSocket server over HTTPS and WSS respectively. This protects data in transit, including the master password during admin login, session cookies, and any secrets transmitted over WebSockets. This application setup does not include HTTPS/WSS by default; you will need to configure this using a reverse proxy (like Nginx or Caddy) or other methods.
  • CSRF Protection: The Admin UI uses csurf to protect against Cross-Site Request Forgery attacks on state-changing POST requests.
  • Security Headers: helmet is used to set various HTTP security headers, providing an additional layer of defense against common web vulnerabilities.
  • Rate Limiting: Both the HTTP admin interface and the WebSocket server implement rate limiting to protect against brute-force attacks and denial-of-service attempts. These limits are configurable via environment variables (see "Getting Started & Installation").
  • Input Validation: While the application includes input validation, continuously reviewing and hardening validation logic is good practice, especially for all data received from clients or the Admin UI.
  • Principle of Least Privilege: Clients should only be associated with secret groups containing the specific secrets they absolutely need. Avoid overly broad permissions.
  • Environment Variables: Never commit your .env file (or any file containing actual secrets) to version control. Use environment variables for deploying sensitive configurations in production.

Testing

Basic unit tests for some core components (like DataManager) might be available.

  • Run tests:
    npm test
    
  • Watch mode for tests:
    npm run test:watch
    

For end-to-end testing, manual testing of the Admin UI is recommended. The client-example.html file (if provided in the repository) can be used for basic WebSocket client interaction testing.

Project Structure Overview

key_manager/
├── data/                  # Encrypted data, salt, runtime config (gitignored)
├── dist/                  # Compiled JavaScript output from TypeScript
├── node_modules/          # Project dependencies (gitignored)
├── public/                # Static assets (e.g., CSS)
│   └── css/
│       └── admin_styles.css
├── src/                   # TypeScript source files
│   ├── http/              # HTTP server (Express) and Admin UI logic
│   ├── lib/               # Core libraries (dataManager, configManager, encryption)
│   ├── websocket/         # WebSocket server logic
│   └── main.ts            # Main application entry point
├── views/                 # EJS templates for Admin UI
├── .env                   # Local environment variables (gitignored)
├── .gitignore
├── client-example.html    # Example WebSocket client for testing (if present)
├── jest.config.js
├── package-lock.json
├── package.json
└── tsconfig.json

Contributing

Contributions are welcome! Please feel free to open an issue or submit a pull request. (Further details can be added here, e.g., coding standards, branch strategy, if the project grows.)

License

This project is licensed under the Strice License. See the LICENSE file (if one exists) for more details.

Description
No description provided
Readme 168 KiB
Languages
TypeScript 73.7%
EJS 12.5%
HTML 9.3%
CSS 4.2%
JavaScript 0.3%