Key Discovery
SSH Key Discovery
Section titled “SSH Key Discovery”Understand how SSH-KLM discovers, inventories, and classifies SSH keys across your infrastructure.
Overview
Section titled “Overview”SSH Key Discovery is the foundation of SSH-KLM, providing complete visibility into all SSH keys in your environment. Discovery can run in agent-based or agentless modes.
Discovery Methods
Section titled “Discovery Methods”Agent-Based Discovery
Section titled “Agent-Based Discovery”The SSH-KLM agent runs on target hosts and provides deep visibility.
Advantages:
- Real-time key change detection
- Access to all user directories
- Minimal network overhead
- Works in air-gapped environments
Scanned Locations:
/home/*/.ssh//root/.ssh//etc/ssh/~/.ssh/authorized_keys~/.ssh/id_*/etc/ssh/ssh_host_*Agentless Discovery
Section titled “Agentless Discovery”SSH-KLM connects via SSH to scan remote hosts.
Advantages:
- No agent installation required
- Quick deployment
- Good for read-only environments
Limitations:
- Requires SSH credentials
- Limited to accessible directories
- Higher network overhead
Discovery Process
Section titled “Discovery Process”flowchart TD A[Start Discovery] --> B{Discovery Mode} B -->|Agent| C[Agent Scans Local FS] B -->|Agentless| D[SSH Connection] C --> E[Enumerate SSH Directories] D --> E E --> F[Parse Key Files] F --> G[Extract Metadata] G --> H[Calculate Risk Score] H --> I[Store in Database] I --> J[Generate Report]Key Metadata
Section titled “Key Metadata”For each discovered key, SSH-KLM extracts:
| Field | Description |
|---|---|
| Fingerprint | SHA256 fingerprint |
| Algorithm | RSA, ED25519, ECDSA, DSA |
| Key Size | Bit length (e.g., 4096) |
| Created Date | File creation timestamp |
| Last Used | Last authentication time |
| Owner | User/service account |
| Location | File path |
| Authorized Hosts | Where public key is authorized |
Risk Scoring
Section titled “Risk Scoring”SSH-KLM calculates a risk score (0-100) for each key:
| Factor | Weight | High Risk Indicators |
|---|---|---|
| Key Age | 25% | > 365 days old |
| Algorithm | 20% | DSA, RSA < 2048 bits |
| No Passphrase | 15% | Unprotected private key |
| Shared Key | 15% | Same key on multiple hosts |
| Root Key | 10% | Key grants root access |
| Orphaned | 10% | Owner account deleted |
| No Rotation | 5% | Never rotated |
Risk Score Calculation
Section titled “Risk Score Calculation”// Example risk score calculationconst riskScore = await client.ssh.calculateRisk({ keyId: 'KEY-12345'});
console.log(riskScore);// {// score: 75,// factors: [// { name: 'keyAge', score: 25, reason: 'Key is 450 days old' },// { name: 'algorithm', score: 20, reason: 'RSA 2048 (weak)' },// { name: 'noPassphrase', score: 15, reason: 'Private key unprotected' },// { name: 'rootAccess', score: 10, reason: 'Grants root access' },// { name: 'noRotation', score: 5, reason: 'Never rotated' }// ]// }Key Classification
Section titled “Key Classification”SSH-KLM classifies discovered keys:
| Status | Description | Action |
|---|---|---|
| Managed | Key enrolled in SSH-KLM | Automated rotation |
| Unmanaged | Discovered but not enrolled | Review and enroll |
| Orphaned | Owner account deleted | Remove or reassign |
| Rogue | Unauthorized key | Investigate and remove |
| Service | Used by applications | Special rotation policy |
Discovery Scheduling
Section titled “Discovery Scheduling”Configure discovery frequency:
// Create discovery scheduleawait client.ssh.createDiscoverySchedule({ name: 'Daily Full Scan', schedule: '0 2 * * *', // 2 AM daily scanType: 'full', hosts: ['group:production']});
// Incremental scans for changesawait client.ssh.createDiscoverySchedule({ name: 'Hourly Incremental', schedule: '0 * * * *', // Every hour scanType: 'incremental', hosts: ['group:production']});Examples
Section titled “Examples”Manual Discovery Scan
Section titled “Manual Discovery Scan”import { QcClient } from '@qcecuring/ssh-sdk';
const client = new QcClient({ apiKey: process.env.QC_API_KEY });
// Start discovery for specific hostsconst scan = await client.ssh.startDiscovery({ hosts: ['server01.example.com', 'server02.example.com'], scanType: 'full', includeSystemKeys: true});
// Wait for completionconst result = await client.ssh.waitForScan(scan.id, { timeout: 300000 // 5 minutes});
console.log(`Discovered ${result.keysFound} keys`);console.log(`High risk: ${result.highRiskKeys}`);Filter Discovered Keys
Section titled “Filter Discovered Keys”// Get high-risk keysconst riskyKeys = await client.ssh.listKeys({ riskScoreMin: 70, status: 'unmanaged', algorithm: ['dsa', 'rsa-1024']});
// Get orphaned keysconst orphanedKeys = await client.ssh.listKeys({ status: 'orphaned'});Troubleshooting
Section titled “Troubleshooting”Discovery Returns No Keys
Section titled “Discovery Returns No Keys”Issue: Scan completes but no keys found
Solutions:
- Verify agent has read permissions on SSH directories
- Check scan includes correct paths
- Review discovery logs for errors
Keys Missing from Scan
Section titled “Keys Missing from Scan”Issue: Known keys not discovered
Solutions:
- Verify key file permissions (must be readable)
- Check for non-standard SSH directory locations
- Add custom scan paths if needed