feat: add Docker label audit across Fleet and Stack views (#1531)

This commit is contained in:
Anso
2026-07-03 18:26:09 -04:00
committed by GitHub
parent 10fb93dcb1
commit 4a350e7a0a
27 changed files with 3099 additions and 1 deletions
@@ -0,0 +1,18 @@
import type { Request } from 'express';
import type { LabelInventoryOptions } from '../services/LabelInventoryService';
import { requireAdmin } from '../middleware/tierGates';
/** Parse ?reveal=1; full values only when the caller is an admin. */
export function labelInventoryOptionsFromRequest(req: Request): LabelInventoryOptions {
const wantsReveal = req.query.reveal === '1' || req.query.reveal === 'true';
if (!wantsReveal) return { revealSecrets: false };
// requireAdmin is synchronous guard; routes call it before building inventory when reveal is requested.
return { revealSecrets: true };
}
/** Returns false and sends 403 when reveal was requested but caller is not admin. */
export function requireRevealAdmin(req: Request, res: import('express').Response): boolean {
const wantsReveal = req.query.reveal === '1' || req.query.reveal === 'true';
if (!wantsReveal) return true;
return requireAdmin(req, res);
}
@@ -0,0 +1,24 @@
import { isLikelySecretKey } from './secretClassification';
export const REDACTED_SENTINEL = '[redacted]';
/**
* Compound single-token segments specific to Docker/Compose labels that the generic
* env classifier does not split (e.g. Traefik `basicauth`/`digestauth` middleware keys,
* whose value carries inline `user:passwordhash` credentials).
*/
const SECRET_LABEL_SEGMENTS = new Set(['BASICAUTH', 'DIGESTAUTH']);
/** True when a Docker/Compose label key likely carries a sensitive value. */
export function isLikelySecretLabelKey(rawKey: string): boolean {
if (isLikelySecretKey(rawKey)) return true;
const segments = rawKey.trim().toUpperCase().split(/[^A-Z0-9]+/).filter(Boolean);
return segments.some(seg => SECRET_LABEL_SEGMENTS.has(seg));
}
export function redactLabelValue(key: string, value: string, revealSecrets: boolean): { value: string; redacted?: boolean } {
if (revealSecrets || !isLikelySecretLabelKey(key)) {
return { value };
}
return { value: REDACTED_SENTINEL, redacted: true };
}
@@ -16,6 +16,7 @@ const SECRET_SEGMENTS = new Set([
'SECRET', 'SECRETS',
'TOKEN', 'KEY', 'APIKEY',
'CREDENTIAL', 'CREDENTIALS', 'AUTH',
'BASIC',
]);
/** Connection strings whose value is sensitive but whose segments are innocuous. */