Organisationsrichtlinie
Die Organisationsrichtlinie legt fest, was ein Projekt nicht lockern darf: vertrauenswürdige Werkzeugverzeichnisse, gesperrte Werte, Pflichtregeln, Mindestschweren und die Bedingungen für Builds in der CI. Sie gilt für jeden Lauf auf dem Rechner.
Speicherort und Rechte
Die Richtlinie wird nur von diesem festen Pfad gelesen:
/Library/Application Support/CodeGuard/policy.yml
Es gibt keinen Parameter und keine Umgebungsvariable, um den Pfad zu ändern. --ci lädt sie genauso wie ein lokaler Lauf. Sie gilt für config validate, doctor, trust … und alle check-*-Kommandos.
- Datei fehlt: Es gelten die eingebauten Vorgaben.
config validatezeigtpolicy: built-in (sha256:…). - Datei vorhanden: Sie muss eine reguläre Datei sein (kein Symlink),
rootgehören, darf weder gruppen- noch weltbeschreibbar sein und keinen ACL-Eintrag haben, der Schreiben, Löschen oder Rechteändern erlaubt. Dasselbe gilt für jedes Verzeichnis von/bis/Library/Application Support/CodeGuard.
Jeder Verstoß, eine nicht lesbare Datei, ungültiges YAML, eine falsche policy_version, ein unbekanntes Feld oder ein unsicherer Eintrag in trusted_roots beendet jedes Kommando mit Exit 2, bevor eine Prüfung startet. Es gibt keinen Rückfall auf die Vorgaben.
Installation:
sudo mkdir -p "/Library/Application Support/CodeGuard"
sudo install -o root -g wheel -m 0644 policy.yml "/Library/Application Support/CodeGuard/policy.yml"
codeguard config validate
codeguard doctor
doctor --format json zeigt die Quelle als "policySource": {"hash": "sha256:…", "kind": "file", "path": "…"} bzw. "kind": "built-in".
Jede Änderung der Richtlinie ändert den policy_hash. Alle bestehenden Trust-Tickets passen danach nicht mehr. Entwickler müssen codeguard trust grant einmal neu ausführen.
Aufbau
policy_version: 1
configuration_versions: [1]
enforcement:
tools:
trusted_roots: [...]
allow_project_tool_paths: false
locked_values: {...}
mandatory_rules: [...]
severity_floors: {...}
non_waivable_rules: [...]
mandatory_protected_files: [...]
metrics: {...}
limits: {...}
execution_environment:
declaration_path: ...
require_for_untrusted_builds: true
Nicht angegebene Felder erhalten ihre Standardwerte. Eine Richtlinie, die nur enforcement.tools.trusted_roots setzt, ist gültig.
Alle Schlüssel
| Schlüssel | Standard | Wirkung |
|---|---|---|
policy_version | 1 | Pflicht, nur 1 |
configuration_versions | [1] | erlaubte Konfigurationsversionen |
enforcement.tools.trusted_roots | /usr/bin, /usr/local/bin, /opt/homebrew/bin, /Applications/Xcode.app/Contents/Developer/usr/bin | Verzeichnisse, aus denen Werkzeuge gestartet werden dürfen. Ersetzt die Standardliste vollständig. |
enforcement.tools.allow_project_tool_paths | false | true erlaubt dem Projekt, tools.* zu setzen (Pfad muss trotzdem unter trusted_roots liegen) |
enforcement.locked_values | {} | gesperrte Werte, siehe unten |
enforcement.mandatory_rules | [] | Regeln, die immer an sind und vom Projekt nicht abgeschaltet werden können |
enforcement.severity_floors | {} | Mindestschwere je Regel-ID |
enforcement.non_waivable_rules | [] | Regeln, für die Waiver nicht wirken |
enforcement.mandatory_protected_files | [] | Globs, die immer zu protected_files hinzukommen |
enforcement.metrics | leer | Metrik-Baseline (gleiche Form wie rules.metrics), die das Projekt nur verschärfen darf |
enforcement.limits.max_waiver_days | 90 | Höchstdauer eines Waivers (bei critical gilt höchstens 7) |
enforcement.execution_environment.declaration_path | /Library/Application Support/CodeGuard/execution-environment.json | Pfad der CI-Attestierung |
enforcement.execution_environment.require_for_untrusted_builds | true | muss true bleiben, sonst sind Builds unter --ci unmöglich |
enforcement.limits.max_iterations, max_fix_files, max_fix_changed_lines, max_approval_ttl | 2, 5, 100, 5m | begrenzen Autofix- und Freigabewerte, die in 0.3.5 keine Wirkung haben |
enforcement.network.project_may_enable, enforcement.ci.project_may_enable_autofix | false | in 0.3.5 ohne Wirkung auf den Lauf |
Vertrauenswürdige Verzeichnisse
enforcement:
tools:
trusted_roots:
- /usr/bin
- /usr/local/bin
- /Applications/Xcode.app/Contents/Developer/usr/bin
- /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
- Jeder Eintrag muss ein sicherer absoluter Pfad sein (kein
//, kein.., kein$, kein Backslash, kein Backtick). - Jedes Verzeichnis muss
rootgehören und darf für niemanden sonst beschreibbar sein. CodeGuard prüft das nicht selbst. - Keine Homebrew-Pfade (
/opt/homebrew/bin,/opt/homebrew/Cellar/…). Lege SwiftLint als root-eigene Kopie nach/usr/local/bin(siehe Erste Schritte). - Ein Werkzeug darf nicht über zwei Einträge erreichbar sein (z. B. Symlink in einem, Ziel im anderen). Das gilt als mehrdeutig,
doctorzeigtunavailable. - Ohne den
XcodeDefault.xctoolchain-Eintrag findet CodeGuardswift-formatundswifteiner Standard-Xcode-Installation nicht.
Gesperrte Werte
locked_values setzt einen Konfigurationswert fest. Der Schlüssel ist der Pfad mit Punkten, der Wert der feste Wert. Ein Projektwert, der widerspricht, ist Exit 2 (configuration value conflicts with a locked organization value).
Damit erreichst du alles, was die Projektebene nicht darf:
enforcement:
locked_values:
# SwiftLint organisationsweit abschalten
checks.swiftlint.enabled: false
checks.swiftlint.required: false
# Tests nicht verpflichtend machen (z. B. für Plattformen ohne Simulator-Runtime)
checks.tests.required: false
# Simulator-Tests organisationsweit abschalten
checks.tests.simulator: false
# Inhaltsprüfung: Unvollständige Dateien nur als Warnung
checks.security.required: false
# Netzwerkziel-Regel aktivieren
security.network.allowed_destinations:
- "https://api.example.org"
- "https://*.cdn.example.org:8443"
# Zeitlimits
execution.timeouts.preflight: 30s
execution.timeouts.compile: 40m
execution.timeouts.simulator_boot: 5m
# Plattformen festlegen
project.platforms: [macos, ios]
Regeln für Sperrpfade:
- Nur kanonische Punktpfade (z. B.
checks.tests.required), kein/. - Unter
rules.metrics.*sind Sperren auf einzelne Schwellen und Schalter möglich, z. B.rules.metrics.cyclomatic_complexity.warning: 10. - Eine ganze Plattformregel als Objekt (
rules.ats-arbitrary-loads) lässt sich nicht sperren, nur einzelne Felder (rules.ats-arbitrary-loads.severity). - Mit einer gesperrten
security.network.allowed_destinationszeigtdoctordie Fähigkeitunauthorized-network-destination: active.
Gesperrte Werte, die Prüfungen abschalten, gelten für jedes Projekt auf dem Rechner. Prüfe, ob eine Projektlösung reicht, etwa scopes: [] für compile/tests.
Pflichtregeln, Mindestschweren, nicht waivebare Regeln
enforcement:
mandatory_rules:
- hardcoded-secret
- sensitive-data-in-log
- codeguard-metric-line-length
severity_floors:
hardcoded-secret: critical
forbidden-force-try: critical
codeguard-metric-cyclomatic-complexity: critical
non_waivable_rules:
- hardcoded-secret
- codeguard-metric-line-length
mandatory_rules: Das Projekt kann diese Regeln nicht abschalten (Exit 2). Für Metrikregeln stehen hier diecodeguard-metric-*-IDs. Hat eine Pflicht-Metrikregel nach dem Zusammenführen keine Schwelle, ist die Konfiguration ungültig (Exit 2), denn es gibt keine Standardschwellen.severity_floors: Hebt die Schwere zur Laufzeit an, und zwar für jeden Fund mit dieser Regel-ID. Das Projekt darf keine niedrigere Schwere setzen (Exit 2). Laufdiagnosen (codeguard-platform-*,codeguard-simulator-*,codeguard-content-*,codeguard-custom-rule-*,codeguard-tool-configuration-*,codeguard-project-config-*) sind ausgenommen.non_waivable_rules: Waiver für diese Regeln wirken nicht.
Bei Inhaltsregeln in check-diff entscheidet nach dem Anheben weiter die scope_relation: Ein Fund in unverändertem Code (pre_existing) blockiert nur bei critical. Ein Floor error macht Altcode also nicht blockierend.
Metrik-Baseline
enforcement:
metrics:
severity: error
line_length: { warning: 120, ignores_urls: true }
nesting: { function_level: { warning: 3 } }
locked_values:
rules.metrics.cyclomatic_complexity.warning: 10
mandatory_rules:
- codeguard-metric-line-length
Damit gilt für Projekte:
rules.metrics.line_length.warningdarf 120 oder kleiner sein, nicht größer.line_length.errorist frei, weil die Baseline ihn nicht setzt.ignores_urlsdarf auffalsegesetzt werden, nicht zurück auftrue.severitydarf nur angehoben werden (error→critical).cyclomatic_complexity.warningmuss genau10sein.- Ein Projekt, das ein
line_length-Objekt schreibt, braucht darin eine eigene Schwelle, etwaline_length: { warning: 120, ignores_urls: false }.
Setzt das Projekt nur eine Schwelle eines Paares und die Baseline die andere, sodass warning > error entstünde (Baseline warning: 120, Projekt error: 100), wird warning auf den error-Wert gesenkt.
Metriken schwer umgehbar machen
Schwellen allein erzwingen keinen Metrik-Lauf. Ein Projekt könnte die Scopes von swiftlint einschränken, Dateien ausschließen oder Funde waiven. Wer Metriken durchsetzen will, sperrt zusätzlich:
enforcement:
locked_values:
checks.swiftlint.enabled: true
checks.swiftlint.required: true
checks.swiftlint.scopes: [file, diff, project]
non_waivable_rules:
- codeguard-metric-line-length
- codeguard-metric-cyclomatic-complexity
Soll auch paths.exclude nicht erweitert werden, sperre die ganze Liste. Ein Projekt kann dann kein eigenes Exclude mehr hinzufügen.
CI-Attestierung
Unter --ci gelten lokale Trust-Tickets nicht. Builds und Tests starten nur, wenn alle Bedingungen erfüllt sind:
-
Eine Organisationsrichtlinie ist installiert und unterscheidet sich von den eingebauten Vorgaben. (Eine Richtlinie, die byteweise den Vorgaben entspricht, gilt als nicht vorhanden.)
-
enforcement.execution_environment.require_for_untrusted_buildsisttrue(Standard). Mitfalsesind Builds unter--ciunmöglich. -
Jedes Verzeichnis über der Attestierungsdatei ist ein echtes Verzeichnis (kein Symlink), gehört
root(oder dem Organisations-Eigentümer) und ist nicht gruppen- oder weltbeschreibbar. -
Die Datei unter
declaration_pathist eine reguläre Datei (kein Symlink), gehörtrootund hat keine Gruppen-/Welt-Schreibrechte und keine Sonderbits. -
Der Inhalt ist genau dieses Dokument, Zeile für Zeile, UTF-8, höchstens 4 KiB, ein abschließender Zeilenumbruch ist erlaubt:
version: 1runner_class: ephemeralephemeral: truefilesystem_isolated: truenetwork_isolated: true
Der Standardpfad endet auf .json, der Inhalt ist trotzdem das YAML-Dokument oben. Wer das vermeiden will, setzt declaration_path auf einen .yml-Pfad.
Mit dieser Datei erklärt der Betreiber, dass der Runner ephemer, dateisystem- und netzwerkisoliert ist. CodeGuard prüft das nicht nach, sondern verlässt sich darauf, um Projektcode ohne menschliche Freigabe auszuführen. Lege die Datei nur auf Runnern ab, für die das tatsächlich zutrifft.
Keine Umgebungsvariable kann die Attestierung ersetzen oder abschalten. Im Bericht steht danach run.build_authorization: "operator_attested". Die Einrichtung im Runner-Image beschreiben CI mit GitHub Actions und CI mit GitLab.
Vollständiges Beispiel
policy_version: 1
configuration_versions: [1]
enforcement:
tools:
trusted_roots:
- /usr/bin
- /usr/local/bin
- /Applications/Xcode.app/Contents/Developer/usr/bin
- /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
mandatory_rules:
- hardcoded-secret
- sensitive-data-in-log
severity_floors:
hardcoded-secret: critical
sensitive-data-in-log: critical
non_waivable_rules:
- hardcoded-secret
mandatory_protected_files:
- .codeguard.yml
- .gitlab-ci.yml
- .github/workflows/**
- "**/*.entitlements"
metrics:
line_length: { warning: 120, error: 200 }
limits:
max_waiver_days: 30
execution_environment:
declaration_path: /Library/Application Support/CodeGuard/execution-environment.yml
require_for_untrusted_builds: true
Die Richtlinienbeispiele auf dieser Seite folgen der Struktur aus dem CodeGuard-Repository (docs/help/policy.example.yml und Test-Fixtures). Da die Richtlinie nur vom festen Systempfad geladen wird, wurden sie für diese Hilfe nicht einzeln installiert und durchlaufen. Prüfe eine neue Richtlinie nach der Installation immer mit codeguard config validate.