feat: initial open marketplace with llm-security, config-audit, ultraplan-local
This commit is contained in:
commit
f93d6abdae
380 changed files with 65935 additions and 0 deletions
111
plugins/config-audit/scanners/posture.mjs
Normal file
111
plugins/config-audit/scanners/posture.mjs
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Config-Audit Posture Assessment CLI
|
||||
* Runs all scanners + scoring in a single Node.js process.
|
||||
* Usage: node posture.mjs <target-path> [--json] [--global] [--output-file path]
|
||||
* Zero external dependencies.
|
||||
*/
|
||||
|
||||
import { resolve } from 'node:path';
|
||||
import { writeFile } from 'node:fs/promises';
|
||||
import { runAllScanners } from './scan-orchestrator.mjs';
|
||||
import {
|
||||
calculateUtilization,
|
||||
determineMaturityLevel,
|
||||
determineSegment,
|
||||
scoreByArea,
|
||||
topActions,
|
||||
generateScorecard,
|
||||
generateHealthScorecard,
|
||||
} from './lib/scoring.mjs';
|
||||
|
||||
/**
|
||||
* Run posture assessment and return structured result.
|
||||
* @param {string} targetPath
|
||||
* @param {object} [opts]
|
||||
* @param {boolean} [opts.includeGlobal=false]
|
||||
* @param {boolean} [opts.fullMachine=false] - Scan all known locations across the machine
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
export async function runPosture(targetPath, opts = {}) {
|
||||
const envelope = await runAllScanners(targetPath, opts);
|
||||
|
||||
// Extract GAP scanner results
|
||||
const gapScanner = envelope.scanners.find(s => s.scanner === 'GAP');
|
||||
const gapFindings = gapScanner ? gapScanner.findings : [];
|
||||
|
||||
// Calculate scores
|
||||
const utilization = calculateUtilization(gapFindings);
|
||||
const maturity = determineMaturityLevel(gapFindings, { files: [] });
|
||||
const segment = determineSegment(utilization.score);
|
||||
const areaScores = scoreByArea(envelope.scanners);
|
||||
const actions = topActions(gapFindings);
|
||||
|
||||
return {
|
||||
utilization,
|
||||
maturity,
|
||||
segment,
|
||||
areas: areaScores.areas,
|
||||
overallGrade: areaScores.overallGrade,
|
||||
topActions: actions,
|
||||
opportunityCount: gapFindings.length,
|
||||
scannerEnvelope: envelope,
|
||||
};
|
||||
}
|
||||
|
||||
// --- CLI entry point ---
|
||||
async function main() {
|
||||
const args = process.argv.slice(2);
|
||||
let targetPath = '.';
|
||||
let outputFile = null;
|
||||
let jsonMode = false;
|
||||
let includeGlobal = false;
|
||||
let fullMachine = false;
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i] === '--output-file' && args[i + 1]) {
|
||||
outputFile = args[++i];
|
||||
} else if (args[i] === '--json') {
|
||||
jsonMode = true;
|
||||
} else if (args[i] === '--global') {
|
||||
includeGlobal = true;
|
||||
} else if (args[i] === '--full-machine') {
|
||||
fullMachine = true;
|
||||
} else if (args[i] === '--include-fixtures') {
|
||||
// handled below
|
||||
} else if (!args[i].startsWith('-')) {
|
||||
targetPath = args[i];
|
||||
}
|
||||
}
|
||||
|
||||
const filterFixtures = !args.includes('--include-fixtures');
|
||||
const result = await runPosture(targetPath, { includeGlobal, fullMachine, filterFixtures });
|
||||
|
||||
if (jsonMode) {
|
||||
const json = JSON.stringify(result, null, 2);
|
||||
process.stdout.write(json + '\n');
|
||||
} else {
|
||||
// Terminal scorecard (v3 health format)
|
||||
const scorecard = generateHealthScorecard(
|
||||
{ areas: result.areas, overallGrade: result.overallGrade },
|
||||
result.opportunityCount,
|
||||
);
|
||||
process.stderr.write('\n' + scorecard + '\n');
|
||||
}
|
||||
|
||||
if (outputFile) {
|
||||
const json = JSON.stringify(result, null, 2);
|
||||
await writeFile(outputFile, json, 'utf-8');
|
||||
process.stderr.write(`\nResults written to ${outputFile}\n`);
|
||||
}
|
||||
}
|
||||
|
||||
// Only run CLI if invoked directly
|
||||
const isDirectRun = process.argv[1] && resolve(process.argv[1]) === resolve(new URL(import.meta.url).pathname);
|
||||
if (isDirectRun) {
|
||||
main().catch(err => {
|
||||
process.stderr.write(`Fatal: ${err.message}\n`);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue