Skip to content

Pass 06: Twelve-Factor-Reife (TF) ​

EigenschaftWert
Pass-Nummer06
Schlüsseltf
Pass-Name in der Ausgabetwelve_factor
Signal-PräfixTF (Findings des IaC-Scanners: TF-IAC)
TypDeterministisch (Regel-Engine), optionaler externer IaC-Scanner, kein LLM
StandardAktiv
Assessment-Typenapplication; llm (innerhalb jedes Legs). Bei service übersprungen (kein Terraform- oder Twelve-Factor-Quellcode). Läuft nicht bei landing-zone-catalog.
LizenzstufeNicht 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 in infra/ oder terraform/) sowie Checkov oder KICS im PATH, 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/.

FaktorPrüfungStatuswerte
III ConfigStack-spezifische Evidenz für ausgelagerte Konfiguration und fest kodierte Werte in der Konfiguration (siehe unten)pass, partial, fail, unknown
II DependenciesDie Compose-Datei verweist auf das öffentliche Docker Hub (docker.io, hub.docker.com) oder auf die Images postgres, redis, node, nginx, ubuntu ohne Registrypass (Compose ohne öffentliche Verweise), partial (öffentliche Registry), unknown (kein Compose)
VIII ConcurrencyKubernetes-Manifeste vorhandenpass (Kubernetes), fail (nur Compose), unknown
XI LogsNode.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 DisposabilityEine 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/healthpartial (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 in application*.yml / .properties, spring.config.import, Spring Cloud Config oder Vault, @Value("${...}") und @ConfigurationProperties im Java- oder Kotlin-Code; Profil-Dateien gelten als unterstützende Evidenz.
  • Helm und Kubernetes: Chart-Templates, die .Values lesen, ConfigMap- und Secret-Manifeste, envFrom, configMapKeyRef und secretKeyRef; umgebungsspezifische values-<env>.yaml gelten als unterstützende Evidenz.
  • Node.js: .env.example (auch .env.sample, .env.template), Zugriffe auf process.env (nicht nur NODE_ENV), dotenv.
  • Python: os.environ, os.getenv, pydantic BaseSettings. .NET: AddEnvironmentVariables(), umgebungsspezifische appsettings.<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 ​

SignalWird erzeugt, wennSchweregradBedeutung
TF-01Immerhigh (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-02Immermedium (öffentliche Registry), positive (Compose ohne öffentliche Images), low (kein Compose)Faktor II: Images müssen in eine souveräne Container-Registry gespiegelt werden
TF-03Immerhigh (Compose ohne Kubernetes), sonst informationalFaktor VIII: keine Mehrinstanz-Bereitstellung, eine Lücke bei der operativen Resilienz nach DORA
TF-04Immerpositive (strukturiertes Logging), medium (keines gefunden), informational (Sprache nicht geprüft)Faktor XI: strukturierte JSON-Logs für die SIEM-Anbindung erforderlich
TF-05ImmerlowFaktor IX: Health-Endpunkt gefunden oder nicht; Shutdown-Hooks nicht bestätigt
TF-IAC-01 und folgendeJe fehlgeschlagener IaC-Prüfunghigh (Scanner-Schweregrad critical oder high), sonst mediumRegel-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 ​

NameZweck in diesem PassLizenzGebündelt oder externVerhalten bei Fehlen
CheckovStatischer IaC-Sicherheitsscan von .tf-Dateien (erste Wahl)Externes Werkzeug; Lizenz im Repository nicht erfasstOptionale externe Installation im PATHKICS wird versucht
KICSStatischer IaC-Sicherheitsscan (Rückfall)Externes Werkzeug; Lizenz im Repository nicht erfasstOptionale externe Installation im PATHKeine TF-IAC-Signale; die Faktorprüfungen laufen normal
js-yamlLesen von 01-inv.yaml aus dem aktuellen LaufMITGebündeltEntfällt
@swao/module-iac-scan (SWAO-intern)Aufruf von Checkov bzw. KICS und Normalisierung der ErgebnisseInternes SWAO-PaketGebündeltEntfä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.yaml mit Kopf (id: 6, name: twelve_factor), Signalen und assessment.
  • Einträge pass.iac.scanner.start und pass.iac.scanner.complete im Portfolio-Ereignisprotokoll, wenn ein Scan läuft.

Konfiguration und Einschränkungen ​

Konfiguration

  • --passes tf führt den Pass allein aus (nehmen Sie inv hinzu, damit die Logging-Prüfung die Sprache kennt).
  • Installieren Sie Checkov oder KICS im PATH, um TF-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 auf process.env, der dotenv-Loader und .env.example als Evidenz, und literale Hosts in diesen JSON-Dateien werden nicht gemeldet.