Skip to main content
Glama

MCP SSH Orchestrator

by samerfarida
06.2-credentials.yml.md14.8 kB
# 6.2 credentials.yml **Purpose:** Configure SSH authentication methods, manage secrets, and define credential resolution for mcp-ssh-orchestrator. ## Overview The `credentials.yml` file defines **SSH authentication methods** and **secret management** for connecting to target hosts. It supports both key-based and password-based authentication with secure secret resolution. ## File Structure ```yaml # credentials.yml entries: - name: "prod_admin" username: "ubuntu" key_path: "id_ed25519" key_passphrase_secret: "prod_key_passphrase" password_secret: "" - name: "legacy_password" username: "admin" key_path: "" password_secret: "legacy_password" ``` ## Configuration Fields ### Required Fields | Field | Type | Description | Example | |-------|------|-------------|---------| | `name` | string | Unique credential identifier | `"prod_admin"` | | `username` | string | SSH username | `"ubuntu"` | ### Optional Fields | Field | Type | Default | Description | Example | |-------|------|---------|-------------|---------| | `key_path` | string | `""` | SSH private key file path | `"id_ed25519"` | | `key_passphrase_secret` | string | `""` | Passphrase secret name | `"prod_key_passphrase"` | | `password_secret` | string | `""` | Password secret name | `"admin_password"` | ## Authentication Methods ### Key-Based Authentication (Recommended) **SSH Key Authentication:** ```yaml entries: - name: "prod_admin" username: "ubuntu" key_path: "id_ed25519" key_passphrase_secret: "prod_key_passphrase" password_secret: "" # Empty = no password auth ``` **Key without Passphrase:** ```yaml entries: - name: "dev_admin" username: "developer" key_path: "dev_key" key_passphrase_secret: "" # Empty = no passphrase password_secret: "" ``` ### Password-Based Authentication **Password Authentication:** ```yaml entries: - name: "legacy_admin" username: "admin" key_path: "" # Empty = no key auth password_secret: "legacy_password" ``` **Mixed Authentication (Key + Password):** ```yaml entries: - name: "mixed_auth" username: "ubuntu" key_path: "id_ed25519" key_passphrase_secret: "key_passphrase" password_secret: "user_password" ``` ## Secret Resolution ### Secret Resolution Order Secrets are resolved in this order: 1. **Environment variable**: `MCP_SSH_SECRET_<NAME>` (uppercase) 2. **Docker secret file**: `/app/secrets/<name>` 3. **Empty string**: If not found ### Path Traversal Protection **Security Feature:** Secret resolution includes path traversal protection to prevent unauthorized file access. ### Input Length Limits All string parameters in credentials configuration have length limits: - **Secret Names**: Maximum 100 characters - Validated when resolving secrets via `password_secret`, `key_passphrase_secret` - Names exceeding limit are rejected with security event logging - **SSH Key Paths**: Maximum 500 characters - Validated when resolving key paths - Paths exceeding limit are rejected with security event logging **Security**: Length limits prevent resource exhaustion attacks via oversized inputs. #### Secret Name Validation - **Allowed characters**: Alphanumeric (a-z, A-Z, 0-9), dash (-), underscore (_) - **Rejected**: Special characters, path separators, traversal patterns - **Examples**: ```yaml # ✅ Valid password_secret: "prod_password" password_secret: "key-passphrase" # ❌ Invalid (rejected) password_secret: "../etc/passwd" # Path traversal password_secret: "/absolute/path" # Absolute path password_secret: "secret.name" # Special characters ``` #### Path Resolution Security 1. **Relative paths only**: Secrets must use relative paths (no absolute paths) 2. **Directory confinement**: All resolved paths must stay within `/app/secrets` 3. **Normalization**: Paths are normalized to handle encoded traversal attempts 4. **File type validation**: Only regular files are accepted (directories and symlinks rejected) 5. **Security logging**: Path traversal and file validation failures are logged as security events **File Type Requirements:** - ✅ Regular files within secrets directory - ❌ Directories (must be files, not directories) - ❌ Symbolic links (rejected for security) **Effect**: Prevents accessing files outside the secrets directory via path traversal attacks and blocks access to directories or symlinks that could pose security risks. ### Environment Variables **Setting secrets via environment:** ```bash # Set secret via environment variable export MCP_SSH_SECRET_PROD_KEY_PASSPHRASE="my-passphrase" export MCP_SSH_SECRET_ADMIN_PASSWORD="admin-password" # Use in Docker docker run -i --rm \ -e MCP_SSH_SECRET_PROD_KEY_PASSPHRASE="my-passphrase" \ -e MCP_SSH_SECRET_ADMIN_PASSWORD="admin-password" \ ghcr.io/samerfarida/mcp-ssh-orchestrator:0.1.0 ``` **Claude Desktop configuration:** ```json { "mcpServers": { "ssh-orchestrator": { "command": "docker", "args": [ "run", "-i", "--rm", "-e", "MCP_SSH_SECRET_PROD_PASSWORD=your-password", "-v", "/Users/YOUR_USERNAME/mcp-ssh/config:/app/config:ro", "-v", "/Users/YOUR_USERNAME/mcp-ssh/keys:/app/keys:ro", "ghcr.io/samerfarida/mcp-ssh-orchestrator:0.1.0" ] } } } ``` ### Docker Secrets **Creating Docker secrets:** ```bash # Create secret echo "my-passphrase" | docker secret create ssh_key_passphrase - # Use in Docker Compose services: mcp-ssh: image: ghcr.io/samerfarida/mcp-ssh-orchestrator:0.1.0 secrets: - ssh_key_passphrase volumes: - ./config:/app/config:ro - ./keys:/app/keys:ro secrets: ssh_key_passphrase: external: true ``` **File-based secrets:** ```bash # Create secrets directory mkdir -p ~/mcp-ssh/secrets chmod 0700 ~/mcp-ssh/secrets # Add secret files echo "passphrase" > ~/mcp-ssh/secrets/key_passphrase echo "password" > ~/mcp-ssh/secrets/admin_password # Set permissions chmod 0400 ~/mcp-ssh/secrets/* ``` ## SSH Key Management ### Key Generation **Ed25519 Keys (Recommended):** ```bash # Generate Ed25519 key pair ssh-keygen -t ed25519 -f ~/.ssh/mcp_orchestrator -C "mcp-ssh-orchestrator" # Copy to keys directory cp ~/.ssh/mcp_orchestrator ~/mcp-ssh/keys/id_ed25519 cp ~/.ssh/mcp_orchestrator.pub ~/mcp-ssh/keys/id_ed25519.pub # Set permissions chmod 0400 ~/mcp-ssh/keys/id_ed25519 chmod 0444 ~/mcp-ssh/keys/id_ed25519.pub ``` **RSA Keys (Legacy):** ```bash # Generate RSA 4096-bit key pair ssh-keygen -t rsa -b 4096 -f ~/.ssh/mcp_orchestrator_rsa -C "mcp-ssh-orchestrator" # Copy to keys directory cp ~/.ssh/mcp_orchestrator_rsa ~/mcp-ssh/keys/id_rsa cp ~/.ssh/mcp_orchestrator_rsa.pub ~/mcp-ssh/keys/id_rsa.pub # Set permissions chmod 0400 ~/mcp-ssh/keys/id_rsa chmod 0444 ~/mcp-ssh/keys/id_rsa.pub ``` ### Key Deployment **Deploy public key to target hosts:** ```bash # Copy public key to target host ssh-copy-id -i ~/mcp-ssh/keys/id_ed25519.pub ubuntu@10.0.0.11 # Or manually add to authorized_keys cat ~/mcp-ssh/keys/id_ed25519.pub | ssh ubuntu@10.0.0.11 "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys" ``` ### Key Rotation **Rotate SSH keys:** ```bash # Generate new key pair ssh-keygen -t ed25519 -f ~/.ssh/mcp_orchestrator_new -C "mcp-ssh-orchestrator-new" # Deploy new public key to all hosts for host in $(ssh_list_hosts); do ssh-copy-id -i ~/.ssh/mcp_orchestrator_new.pub ubuntu@$host done # Update configuration cp ~/.ssh/mcp_orchestrator_new ~/mcp-ssh/keys/id_ed25519 chmod 0400 ~/mcp-ssh/keys/id_ed25519 # Remove old key from hosts for host in $(ssh_list_hosts); do ssh ubuntu@$host "sed -i '/mcp-ssh-orchestrator/d' ~/.ssh/authorized_keys" done ``` ## Environment-Specific Configurations ### Development Environment ```yaml # credentials.yml - Development entries: - name: "dev_admin" username: "developer" key_path: "dev_key" key_passphrase_secret: "" # No passphrase for dev password_secret: "" - name: "dev_root" username: "root" key_path: "dev_root_key" key_passphrase_secret: "" password_secret: "" ``` ### Staging Environment ```yaml # credentials.yml - Staging entries: - name: "staging_admin" username: "ubuntu" key_path: "staging_key" key_passphrase_secret: "staging_key_passphrase" password_secret: "" - name: "staging_service" username: "service" key_path: "staging_service_key" key_passphrase_secret: "staging_service_passphrase" password_secret: "" ``` ### Production Environment ```yaml # credentials.yml - Production entries: - name: "prod_admin" username: "ubuntu" key_path: "prod_key" key_passphrase_secret: "prod_key_passphrase" password_secret: "" - name: "prod_service" username: "service" key_path: "prod_service_key" key_passphrase_secret: "prod_service_passphrase" password_secret: "" - name: "prod_monitoring" username: "monitoring" key_path: "prod_monitoring_key" key_passphrase_secret: "prod_monitoring_passphrase" password_secret: "" ``` ## Multi-User Configurations ### Different Users per Host Type ```yaml entries: # Web server credentials - name: "web_admin" username: "ubuntu" key_path: "web_key" key_passphrase_secret: "web_key_passphrase" password_secret: "" # Database server credentials - name: "db_admin" username: "postgres" key_path: "db_key" key_passphrase_secret: "db_key_passphrase" password_secret: "" # Monitoring server credentials - name: "monitor_admin" username: "monitoring" key_path: "monitor_key" key_passphrase_secret: "monitor_key_passphrase" password_secret: "" ``` ### Service Account Credentials ```yaml entries: # Application service account - name: "app_service" username: "app" key_path: "app_service_key" key_passphrase_secret: "app_service_passphrase" password_secret: "" # Backup service account - name: "backup_service" username: "backup" key_path: "backup_service_key" key_passphrase_secret: "backup_service_passphrase" password_secret: "" # Monitoring service account - name: "monitoring_service" username: "monitoring" key_path: "monitoring_service_key" key_passphrase_secret: "monitoring_service_passphrase" password_secret: "" ``` ## Path Traversal Protection for Keys **Security Feature:** SSH key path resolution includes path traversal protection. ### Key Path Validation - **Relative paths**: Resolved relative to `keys_dir`, validated to stay within directory - **Absolute paths**: Must be within `keys_dir` (rejected if outside) - **Traversal patterns**: Paths containing `..` or `..\\` are rejected - **File type validation**: Only regular files accepted (directories and symlinks rejected) - **Security logging**: Path traversal and file validation failures are logged **Examples**: ```yaml # ✅ Valid key paths key_path: "id_ed25519" # Relative, within keys_dir key_path: "/app/keys/id_ed25519" # Absolute, within keys_dir # ❌ Invalid (rejected) key_path: "../outside_key" # Path traversal key_path: "/etc/passwd" # Outside keys_dir key_path: "../../root/.ssh/id_rsa" # Traversal attempt key_path: "subdirectory" # Points to directory, not file key_path: "symlink_key" # Points to symlink, not regular file ``` **File Type Requirements:** - ✅ Regular files within keys_dir (or non-existent files - validated when used) - ❌ Directories - ❌ Symbolic links (rejected for security) **Effect**: Prevents accessing SSH keys from unauthorized locations and blocks access to directories or symlinks that could pose security risks. ## Security Best Practices ### Key Security 1. **Use Ed25519 keys** for new deployments 2. **Set private key permissions** to 0400 3. **Use passphrases** for private keys 4. **Rotate keys quarterly** 5. **Use separate keys** for different environments ### Secret Security 1. **Never hardcode secrets** in YAML files 2. **Use Docker secrets** for production 3. **Use environment variables** for development 4. **Rotate secrets regularly** 5. **Use strong, unique secrets** ### Access Control 1. **Use least-privilege usernames** 2. **Separate service accounts** from admin accounts 3. **Use different credentials** per environment 4. **Monitor credential usage** 5. **Revoke unused credentials** ## Validation and Testing ### Configuration Validation ```bash # Validate credentials.yml syntax python -c "import yaml; yaml.safe_load(open('config/credentials.yml'))" # Validate credential references python -c " from mcp_ssh.config import Config config = Config('config/') print('Credential validation:', config.validate_credentials()) " ``` ### Authentication Testing ```bash # Test SSH key authentication ssh -i keys/id_ed25519 ubuntu@10.0.0.11 "echo 'Key auth successful'" # Test password authentication ssh ubuntu@10.0.0.11 "echo 'Password auth successful'" # Test via mcp-ssh-orchestrator ssh_ping # Health check ssh_describe_host --alias "web1" # Get host details ``` ### Secret Resolution Testing ```bash # Test secret resolution python -c " from mcp_ssh.config import Config config = Config('config/') cred = config.get_credentials('prod_admin') print('Key path:', cred.key_path) print('Username:', cred.username) " ``` ## Troubleshooting ### Common Issues 1. **Invalid YAML syntax** ```bash # Check syntax python -c "import yaml; yaml.safe_load(open('config/credentials.yml'))" ``` 2. **Missing secret files** ```bash # Check secret files ls -la ~/mcp-ssh/secrets/ ``` 3. **Wrong key permissions** ```bash # Fix key permissions chmod 0400 ~/mcp-ssh/keys/* ``` 4. **SSH connection failures** ```bash # Test SSH connection ssh -v -i keys/id_ed25519 ubuntu@10.0.0.11 ``` ### Authentication Issues 1. **Key authentication failed** ```bash # Check key format ssh-keygen -l -f keys/id_ed25519 # Test key manually ssh -i keys/id_ed25519 ubuntu@10.0.0.11 ``` 2. **Password authentication failed** ```bash # Check password secret echo $MCP_SSH_SECRET_ADMIN_PASSWORD # Test password manually ssh ubuntu@10.0.0.11 ``` 3. **Passphrase authentication failed** ```bash # Check passphrase secret echo $MCP_SSH_SECRET_KEY_PASSPHRASE # Test passphrase manually ssh -i keys/id_ed25519 ubuntu@10.0.0.11 ``` ## Next Steps - **[policy.yml](06.3-policy.yml)** - Security policy configuration - **[Usage Cookbook](08-Usage-Cookbook)** - Practical credential examples - **[Deployment](09-Deployment)** - Production credential management - **[Troubleshooting](12-Troubleshooting)** - Common credential issues

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/samerfarida/mcp-ssh-orchestrator'

If you have feedback or need assistance with the MCP directory API, please join our Discord server