|
| 1 | +# SSH Provider |
| 2 | + |
| 3 | +The SSH Provider extends the platform-health server to enable monitoring of SSH services. It performs protocol-level handshake(s) to capture host key fingerprints for security verification, without requiring authentication credentials. This enables MITM detection through host key fingerprint pinning and algorithm compliance checks using CEL (Common Expression Language) expressions. |
| 4 | + |
| 5 | +When `algorithms` is specified, the provider polls each algorithm separately, collecting all fingerprints into a map for comprehensive verification. |
| 6 | + |
| 7 | +## Usage |
| 8 | + |
| 9 | +Once the SSH Provider is configured, any query to the platform health server will trigger validation of the configured SSH service(s). The server will attempt to establish SSH connection(s) to each instance, capture the host key(s) during the handshake, and report each instance as "healthy" if the handshake is successful and all CEL checks pass, or "unhealthy" if the connection fails or any check fails. |
| 10 | + |
| 11 | +### Ad-hoc Check |
| 12 | + |
| 13 | +```bash |
| 14 | +# Basic SSH check (server chooses algorithm) |
| 15 | +ph check ssh --host example.com --port 22 |
| 16 | + |
| 17 | +# Check specific algorithm |
| 18 | +ph check ssh --host example.com --algorithms ssh-ed25519 |
| 19 | + |
| 20 | +# Check multiple algorithms |
| 21 | +ph check ssh --host example.com --algorithms ssh-ed25519 --algorithms ecdsa-sha2-nistp256 |
| 22 | + |
| 23 | +# Check with CEL expression |
| 24 | +ph check ssh --host example.com --check='"ssh-ed25519" in ssh.hostKey' |
| 25 | +``` |
| 26 | + |
| 27 | +### Context Inspection |
| 28 | + |
| 29 | +Use `ph context` to inspect the available CEL variables before writing expressions: |
| 30 | + |
| 31 | +```bash |
| 32 | +# Default (server chooses algorithm) |
| 33 | +ph context ssh --host example.com |
| 34 | + |
| 35 | +# Specific algorithm |
| 36 | +ph context ssh --host example.com --algorithms ssh-ed25519 |
| 37 | + |
| 38 | +# Multiple algorithms |
| 39 | +ph context ssh --host example.com --algorithms ssh-ed25519 --algorithms ecdsa-sha2-nistp256 |
| 40 | +``` |
| 41 | + |
| 42 | +## Configuration |
| 43 | + |
| 44 | +The SSH Provider is configured through the platform-health server's configuration file. Each instance is defined with its name as the YAML key under `components`. |
| 45 | + |
| 46 | +- `type` (required): Must be `ssh`. |
| 47 | +- `spec`: Provider-specific configuration: |
| 48 | + - `host` (required): The hostname or IP address of the SSH service to monitor. |
| 49 | + - `port` (default: `22`): The port number of the SSH service to monitor. |
| 50 | + - `algorithms` (optional): List of host key algorithms to poll. If not specified, server chooses (single handshake). If specified, one handshake per algorithm. |
| 51 | +- `checks`: A list of CEL expressions to validate the SSH connection. Each check has: |
| 52 | + - `check` (required): A CEL expression that must evaluate to `true` for the connection to be healthy. |
| 53 | + - `message` (optional): Custom error message when the check fails. |
| 54 | + |
| 55 | +### Valid Algorithm Names |
| 56 | + |
| 57 | +- `ssh-ed25519` |
| 58 | +- `ecdsa-sha2-nistp256` |
| 59 | +- `ecdsa-sha2-nistp384` |
| 60 | +- `ecdsa-sha2-nistp521` |
| 61 | +- `ssh-rsa` |
| 62 | +- `rsa-sha2-256` |
| 63 | +- `rsa-sha2-512` |
| 64 | + |
| 65 | +## CEL Check Context |
| 66 | + |
| 67 | +The SSH provider exposes an `ssh` variable containing host key details: |
| 68 | + |
| 69 | +- `ssh.hostKey`: Map of algorithm name to SHA256 fingerprint (map[string]string) |
| 70 | +- `ssh.host`: Target hostname used for connection (string) |
| 71 | +- `ssh.port`: Target port used for connection (int) |
| 72 | + |
| 73 | +### Example Context Output |
| 74 | + |
| 75 | +Default (server chooses algorithm): |
| 76 | +```json |
| 77 | +{ |
| 78 | + "ssh": { |
| 79 | + "hostKey": { |
| 80 | + "ecdsa-sha2-nistp256": "SHA256:p2QAMXNIC1TJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM" |
| 81 | + }, |
| 82 | + "host": "github.com", |
| 83 | + "port": 22 |
| 84 | + } |
| 85 | +} |
| 86 | +``` |
| 87 | + |
| 88 | +With multiple algorithms specified: |
| 89 | +```json |
| 90 | +{ |
| 91 | + "ssh": { |
| 92 | + "hostKey": { |
| 93 | + "ssh-ed25519": "SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU", |
| 94 | + "ecdsa-sha2-nistp256": "SHA256:p2QAMXNIC1TJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM" |
| 95 | + }, |
| 96 | + "host": "github.com", |
| 97 | + "port": 22 |
| 98 | + } |
| 99 | +} |
| 100 | +``` |
| 101 | + |
| 102 | +### Example CEL Expressions |
| 103 | + |
| 104 | +```cel |
| 105 | +// Check if server supports specific algorithm |
| 106 | +"ssh-ed25519" in ssh.hostKey |
| 107 | +
|
| 108 | +// Verify known host key fingerprint for specific algorithm (MITM detection) |
| 109 | +ssh.hostKey["ssh-ed25519"] == "SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU" |
| 110 | +
|
| 111 | +// Check at least one modern algorithm is available |
| 112 | +"ssh-ed25519" in ssh.hostKey || "ecdsa-sha2-nistp256" in ssh.hostKey |
| 113 | +
|
| 114 | +// Ensure RSA is not the only option (when polling multiple) |
| 115 | +!("ssh-rsa" in ssh.hostKey) || size(ssh.hostKey) > 1 |
| 116 | +``` |
| 117 | + |
| 118 | +## Examples |
| 119 | + |
| 120 | +### Basic SSH Check |
| 121 | + |
| 122 | +```yaml |
| 123 | +components: |
| 124 | + bastion: |
| 125 | + type: ssh |
| 126 | + spec: |
| 127 | + host: bastion.example.com |
| 128 | + port: 22 |
| 129 | +``` |
| 130 | +
|
| 131 | +In this example, the SSH Provider will establish an SSH connection to `bastion.example.com` on port 22 and report the service as "healthy" if the handshake completes successfully. The server chooses which host key algorithm to present. |
| 132 | + |
| 133 | +### Host Key Verification (Single Algorithm) |
| 134 | + |
| 135 | +```yaml |
| 136 | +components: |
| 137 | + production-ssh: |
| 138 | + type: ssh |
| 139 | + spec: |
| 140 | + host: prod.example.com |
| 141 | + port: 22 |
| 142 | + algorithms: |
| 143 | + - ssh-ed25519 |
| 144 | + checks: |
| 145 | + - check: 'ssh.hostKey["ssh-ed25519"] == "SHA256:uNiVztksCsDhcc0u9e8BujQXVUpKZIDTMczCvj3tD2s"' |
| 146 | + message: "Host key mismatch - possible MITM attack" |
| 147 | +``` |
| 148 | + |
| 149 | +This configuration verifies that the SSH server presents the expected ED25519 host key, providing protection against man-in-the-middle attacks. |
| 150 | + |
| 151 | +### Multi-Algorithm Verification |
| 152 | + |
| 153 | +```yaml |
| 154 | +components: |
| 155 | + secure-bastion: |
| 156 | + type: ssh |
| 157 | + spec: |
| 158 | + host: bastion.example.com |
| 159 | + algorithms: |
| 160 | + - ssh-ed25519 |
| 161 | + - ecdsa-sha2-nistp256 |
| 162 | + checks: |
| 163 | + - check: '"ssh-ed25519" in ssh.hostKey' |
| 164 | + message: "Server must support ED25519" |
| 165 | + - check: 'ssh.hostKey["ssh-ed25519"] == "SHA256:expected..."' |
| 166 | + message: "ED25519 key mismatch" |
| 167 | + - check: 'ssh.hostKey["ecdsa-sha2-nistp256"] == "SHA256:expected..."' |
| 168 | + message: "ECDSA key mismatch" |
| 169 | +``` |
| 170 | + |
| 171 | +This polls both ED25519 and ECDSA keys and verifies both fingerprints. |
| 172 | + |
| 173 | +### Algorithm Compliance Check |
| 174 | + |
| 175 | +```yaml |
| 176 | +components: |
| 177 | + modern-ssh: |
| 178 | + type: ssh |
| 179 | + spec: |
| 180 | + host: secure.example.com |
| 181 | + algorithms: |
| 182 | + - ssh-ed25519 |
| 183 | + checks: |
| 184 | + - check: '"ssh-ed25519" in ssh.hostKey' |
| 185 | + message: "ED25519 host key required" |
| 186 | +``` |
| 187 | + |
| 188 | +This ensures the SSH server supports the modern ED25519 algorithm. The check will fail if the server doesn't support ED25519. |
0 commit comments