Pass 06: Twelve-Factor-Reife (TF)
| Eigenschaft | Wert |
|---|---|
| Pass-Nummer | 06 |
| Schlüssel | tf |
| Pass-Name in der Ausgabe | twelve_factor |
| Signal-Präfix | TF (Findings des IaC-Scanners: TF-IAC) |
| Typ | Deterministisch (Regel-Engine), optionaler externer IaC-Scanner, kein LLM |
| Standard | Aktiv |
| Assessment-Typen | application; llm (innerhalb jedes Legs). Bei service übersprungen (kein Terraform- oder Twelve-Factor-Quellcode). Läuft nicht bei landing-zone-catalog. |
| Lizenzstufe | Nicht eingeschränkt (ab Community) |
Wofür der Pass gedacht ist
Die Twelve-Factor-App-Methode beschreibt Eigenschaften, die den Betrieb einer Anwendung auf modernen Cloud-Plattformen erleichtern: Konfiguration in der Umgebung, explizite Abhängigkeiten, horizontale Skalierung, Logs als Ereignisströme, schneller Start und geordnetes Herunterfahren. Pass 06 beantwortet die Frage: „Wie cloud-tauglich ist diese Anwendung, und was stünde einem Replatforming im Weg?“
Er prüft fünf der zwölf Faktoren, die sich am Repository beurteilen lassen, und führt bei vorhandenen Terraform-Dateien und installiertem Scanner einen statischen IaC-Sicherheitsscan durch.
Was Sie bereitstellen müssen
- Den Quellcode der Anwendung.
- Optional: Terraform-Dateien (
*.tf) an beliebiger Stelle im Quellbaum (zum Beispiel ininfra/oderterraform/) sowie Checkov oder KICS imPATH, um IaC-Sicherheits-Findings zu erhalten.
Ein LLM ist nicht nötig. Der Pass liest die von Pass 01 (INV) im selben Lauf erkannte Sprache; führen Sie beide Passes daher gemeinsam aus.
Wie der Pass arbeitet
Der Pass sucht bis zu drei Verzeichnisebenen tief nach .env.example und nach Compose-Dateien (docker-compose*.yml, compose*.yml) und prüft das Wurzelverzeichnis auf k8s/ und helm/.
| Faktor | Prüfung | Statuswerte |
|---|---|---|
| III Config | Stack-spezifische Evidenz für ausgelagerte Konfiguration und fest kodierte Werte in der Konfiguration (siehe unten) | pass, partial, fail, unknown |
| II Dependencies | Die Compose-Datei verweist auf das öffentliche Docker Hub (docker.io, hub.docker.com) oder auf die Images postgres, redis, node, nginx, ubuntu ohne Registry | pass (Compose ohne öffentliche Verweise), partial (öffentliche Registry), unknown (kein Compose) |
| VIII Concurrency | Kubernetes-Manifeste vorhanden | pass (Kubernetes), fail (nur Compose), unknown |
| XI Logs | Node.js: pino, winston, bunyan, nestjs-pino oder pino-http in package.json. Rust: tracing, log, env_logger, tracing-subscriber oder slog in Cargo.toml. Andere Sprachen werden nicht geprüft. | pass, partial, unknown |
| IX Disposability | Eine Health-Handler-Datei (health.controller.ts, health.rs, healthcheck.rs, health_check.rs, bis zu vier Ebenen tief) oder ein Verzeichnis src/health bzw. apps/api/src/app/health | partial (Health-Endpunkt gefunden; geordnetes Herunterfahren statisch nicht bestätigbar) oder unknown |
Faktor III je Stack. Der Pass erkennt die Konfigurationskonvention des jeweiligen Stacks, statt nur nach .env.example zu suchen:
- Spring Boot:
${ENV}-Platzhalter inapplication*.yml/.properties,spring.config.import, Spring Cloud Config oder Vault,@Value("${...}")und@ConfigurationPropertiesim Java- oder Kotlin-Code; Profil-Dateien gelten als unterstützende Evidenz. - Helm und Kubernetes: Chart-Templates, die
.Valueslesen,ConfigMap- undSecret-Manifeste,envFrom,configMapKeyRefundsecretKeyRef; umgebungsspezifischevalues-<env>.yamlgelten als unterstützende Evidenz. - Node.js:
.env.example(auch.env.sample,.env.template), Zugriffe aufprocess.env(nicht nurNODE_ENV),dotenv. - Python:
os.environ,os.getenv, pydanticBaseSettings. .NET:AddEnvironmentVariables(), umgebungsspezifischeappsettings.<Environment>.json.
Fest kodierte Werte sprechen gegen Faktor III: ein öffentlicher oder privater Host bzw. eine IP-Adresse (gefunden vom gemeinsamen Endpunkt-Scanner) in der mitgelieferten Konfiguration (application*.yml, appsettings*.json) sowie ein literales Passwort, Secret, Token oder API-Schlüssel in der mitgelieferten Konfiguration, in Helm-Values oder ConfigMaps. Der Wert wird nie angezeigt, nur der Schlüssel und Datei:Zeile. Ein Host in einem Platzhalter (${DB_HOST}) gilt als ausgelagert. Ein Host in einer umgebungsspezifischen Helm-Values-Datei (values-<env>.yaml) ist Umgebungskonfiguration und wird nur zur Information aufgeführt; ein Host in der Standard-values.yaml des Charts oder in einer ConfigMap legt eine Umgebung im Artefakt fest und senkt TF-01 auf low (Faktor III teilweise erfüllt). Ein Cluster-Servicename (postgres, *.svc.cluster.local) wird von der Plattform aufgelöst und nur zur Information aufgeführt. Testressourcen (src/test/resources, application-test.yml) werden ignoriert.
IaC-Scan. Der Pass sucht Terraform-Wurzeln unterhalb des Quellverzeichnisses: die obersten Ordner bis sechs Ebenen tief, die .tf-Dateien enthalten (höchstens zehn Wurzeln; versteckte Ordner wie .terraform und .git sowie node_modules, vendor, dist, build und target werden übersprungen). Ein Ordner unterhalb einer bereits gefundenen Wurzel wird nicht erneut aufgeführt, weil die Scanner rekursiv arbeiten. Für jede Wurzel führt der Pass checkov --directory <root> -o json --compact --quiet aus. Ist Checkov nicht installiert oder liefert keine Ausgabe, versucht er kics scan --path <root> --report-formats json --output-path - --no-progress. Jedes Werkzeug erhält 60 Sekunden. Findings mit gleicher Regel-ID und Ressource werden nur einmal gemeldet. Fehlgeschlagene Prüfungen werden zu TF-IAC-NN-Signalen.
Wie gemessen wird
| Signal | Wird erzeugt, wenn | Schweregrad | Bedeutung |
|---|---|---|---|
TF-01 | Immer | high (fest kodierter Endpunkt oder Zugangsdatum, mit Datei:Zeile), positive (Evidenz für ausgelagerte Konfiguration im Stack), low (nur unterstützende Evidenz oder literale Host-Vorgaben in Platzhaltern), medium mit Konfidenz low (nicht bestimmbar: weder Evidenz dafür noch dagegen) | Faktor III: Konfiguration ausgelagert, fest kodiert oder nicht bestimmbar |
TF-02 | Immer | medium (öffentliche Registry), positive (Compose ohne öffentliche Images), low (kein Compose) | Faktor II: Images müssen in eine souveräne Container-Registry gespiegelt werden |
TF-03 | Immer | high (Compose ohne Kubernetes), sonst informational | Faktor VIII: keine Mehrinstanz-Bereitstellung, eine Lücke bei der operativen Resilienz nach DORA |
TF-04 | Immer | positive (strukturiertes Logging), medium (keines gefunden), informational (Sprache nicht geprüft) | Faktor XI: strukturierte JSON-Logs für die SIEM-Anbindung erforderlich |
TF-05 | Immer | low | Faktor IX: Health-Endpunkt gefunden oder nicht; Shutdown-Hooks nicht bestätigt |
TF-IAC-01 und folgende | Je fehlgeschlagener IaC-Prüfung | high (Scanner-Schweregrad critical oder high), sonst medium | Regel-ID, Meldung und Ressource aus Checkov oder KICS |
Bewertung. twelve_factor_pass_rate = Anzahl der Faktoren mit Status pass geteilt durch die Anzahl der Faktoren, deren Status nicht unknown ist, auf zwei Nachkommastellen gerundet (0, wenn nichts geprüft werden konnte). Da Faktor IX nur partial oder unknown sein kann, liegt die höchste erreichbare Quote bei Bewertung aller fünf Faktoren bei 0,8. IaC-Findings beeinflussen die Quote nicht.
Der assessment-Block enthält factor_scores (Faktor, Status, Notiz), twelve_factor_pass_rate, iac_roots (Anzahl der obersten Terraform-/OpenTofu-Ordner) und config_externalisation (Status von Faktor III, Konfidenz, erkannte Stacks, positive und unterstützende Evidenz, fest kodierte Werte und Platzhalter-Vorgaben mit Datei:Zeile, Deployment-Literale, Anzahl geprüfter Dateien). Ist Faktor III nicht bestimmbar, lautet der Status unknown; die Quote sinkt dadurch nicht.
Wie die Ergebnisse in spätere Passes einfließen. Der Cloud-Native-Score (#3431) wird aus factor_scores berechnet: gewichteter Mittelwert mit pass 1, partial 0,5, fail 0 und unknown 0,5 (unknown zählt halb, statt wie bei twelve_factor_pass_rate herauszufallen), ausgewiesen mit factors_checked und einer Konfidenz; siehe Pass 09 (SYNTH). iac_roots sowie die Helm- und Kubernetes-Stacks sind Evidenz für Infrastructure as Code und Container im Portabilitätswert. TF-*-Signale sind Evidenz für Pass 11 (COMP).
Drittanbieter-Module und Werkzeuge
| Name | Zweck in diesem Pass | Lizenz | Gebündelt oder extern | Verhalten bei Fehlen |
|---|---|---|---|---|
| Checkov | Statischer IaC-Sicherheitsscan von .tf-Dateien (erste Wahl) | Externes Werkzeug; Lizenz im Repository nicht erfasst | Optionale externe Installation im PATH | KICS wird versucht |
| KICS | Statischer IaC-Sicherheitsscan (Rückfall) | Externes Werkzeug; Lizenz im Repository nicht erfasst | Optionale externe Installation im PATH | Keine TF-IAC-Signale; die Faktorprüfungen laufen normal |
| js-yaml | Lesen von 01-inv.yaml aus dem aktuellen Lauf | MIT | Gebündelt | Entfällt |
@swao/module-iac-scan (SWAO-intern) | Aufruf von Checkov bzw. KICS und Normalisierung der Ergebnisse | Internes SWAO-Paket | Gebündelt | Entfällt |
swao health-check prüft derzeit nicht, ob Checkov oder KICS vorhanden sind; kontrollieren Sie dies selbst mit checkov --version oder kics version.
Ausgaben
wsp/runs/<ts>/passes/06-tf.yamlmit Kopf (id: 6,name: twelve_factor), Signalen undassessment.- Einträge
pass.iac.scanner.startundpass.iac.scanner.completeim Portfolio-Ereignisprotokoll, wenn ein Scan läuft.
Konfiguration und Einschränkungen
Konfiguration
--passes tfführt den Pass allein aus (nehmen Sieinvhinzu, damit die Logging-Prüfung die Sprache kennt).- Installieren Sie Checkov oder KICS im
PATH, umTF-IAC-Findings zu erhalten.
Einschränkungen und bekannte Lücken
- Bewertet werden nur fünf Faktoren (III, II, VIII, XI, IX). Die übrigen sieben Faktoren werden nicht geprüft.
- Der IaC-Scan erfasst höchstens zehn Terraform-Wurzeln bis sechs Ordnerebenen unterhalb des Quellverzeichnisses.
- Ist keiner der beiden Scanner installiert, weist keine Meldung darauf hin, dass der Scan übersprungen wurde.
- Die Prüfung auf öffentliche Registries erkennt nur Verweise auf Docker Hub und fünf gängige Image-Namen ohne Registry.
- Faktor XI wird nur für Node.js, Rust und Java (einschließlich Spring Boot) geprüft.
- TF-01 nutzt die Gitleaks-Findings von Pass 14 (Secret-Scan) nicht, weil Pass 14 nach diesem Pass läuft. Zugangsdaten in der Konfiguration werden nur am Schlüsselnamen (oder als eingebettetes Passwort in einem Connection-String) erkannt; ein Geheimnis unter einem ungewöhnlichen Schlüssel (
app.integration.value) senkt Faktor III daher nicht. - Jeder öffentliche oder private Host bzw. jede IP-Adresse in der mitgelieferten Konfiguration zählt als fest kodiert, auch bekannte öffentliche SaaS-Endpunkte wie ein OAuth- oder OpenID-Connect-Issuer (
spring.security.oauth2.resourceserver.jwt.issuer-uri). Eine Allowlist für solche Endpunkte gibt es noch nicht; prüfen Sie ein TF-01-Finding mit hohem Schweregrad, das nur einen öffentlichen Identitätsanbieter nennt, bevor Sie handeln. - Konfigurationsdateien des Node.js-Pakets
config(config/default.json,config/production.json,config/custom-environment-variables.json) werden nicht gelesen. Für Node.js-Dienste zählen nur Lesezugriffe aufprocess.env, der dotenv-Loader und.env.exampleals Evidenz, und literale Hosts in diesen JSON-Dateien werden nicht gemeldet.
