Skip to content

[roadmap] Add agent PKI CSR governance#45

Merged
ewilhelm1979-netizen merged 1 commit into
mainfrom
feature/agent-pki-csr-governance
Jul 9, 2026
Merged

[roadmap] Add agent PKI CSR governance#45
ewilhelm1979-netizen merged 1 commit into
mainfrom
feature/agent-pki-csr-governance

Conversation

@ewilhelm1979-netizen

Copy link
Copy Markdown
Owner

Problemstellung und Ziel

ISCY soll die Zero-Trust-Agent-Governance um eine CA-/PKI-/CSR-Schicht erweitern, ohne produktive CA-Secrets, private Schluessel, echte Zertifikatsausstellung oder automatische mTLS-Aktivierung einzufuehren. Ziel ist ein tenantgebundenes Governance- und Statusmodell fuer CA-Provider, CSR-Review, Zertifikatsstatus, mTLS-Bindung, Rotation und Widerruf.

Geaenderte Funktionen

  • Additives Agent-PKI-Store-Modell fuer SQLite und PostgreSQL.
  • CA-/PKI-Provider-Metadaten mit Status, Trust Domain, Policy, Laufzeiten, Revocation-Modus, Key-Storage-Policy, Secret-Referenzstatus und Limitierungen.
  • CSR-/Certificate-Request-Lifecycle mit sicheren Metadaten, Fingerprints/Hashes, Review-Status, Approval, Rejection und Cancel.
  • Zertifikatsstatusmodell fuer Agenten mit mTLS-Bindungsstatus, Rotation, Widerruf, Laufzeit und Evidence-IDs.
  • Agent-PKI-Auditereignisse fuer Provider-, CSR- und Zertifikatsstatus-Aktionen.
  • Integration in Zero-Trust-Webansicht, gefuehrtes Agent-Onboarding und Management-/Regulatory-Review-Snapshots.

Betroffene Dateien

  • rust/iscy-backend/src/agent_pki_store.rs
  • rust/iscy-backend/src/db_admin.rs
  • rust/iscy-backend/src/lib.rs
  • rust/iscy-backend/src/main.rs
  • rust/iscy-backend/src/report_store.rs
  • rust/iscy-backend/tests/http_tests.rs
  • CHANGELOG.md
  • docs/ZERO_TRUST_AGENT.md
  • docs/ISCY_Handbuch.md
  • docs/ISCY_Handbuch.pdf
  • docs/ISCY_STRATEGIC_ROADMAP.md
  • docs/GUI_SCREENSHOTS.md

Datenbankmigrationen

  • Neue additive Migration 0037_rust_agent_pki_csr_governance.
  • Neue Tabellen: agent_pki_provider, agent_certificate_request, agent_certificate_status, agent_pki_event.
  • Neue Indizes fuer Tenant-/Status-/Provider-/Agent-/Audit-Abfragen.
  • SQLite-Restartbarkeit und Bestandserhalt sind per Test abgedeckt.
  • PostgreSQL wurde lokal mit temporaerer Wegwerf-Instanz und Restore-Drill geprueft.

Neue oder geaenderte API-Endpunkte

  • GET / POST /api/v1/agents/pki/providers
  • GET / PATCH /api/v1/agents/pki/providers/{provider_id}
  • GET / POST /api/v1/agents/pki/csrs
  • GET /api/v1/agents/pki/csrs/{csr_id}
  • POST /api/v1/agents/pki/csrs/{csr_id}/approve
  • POST /api/v1/agents/pki/csrs/{csr_id}/reject
  • POST /api/v1/agents/pki/csrs/{csr_id}/cancel
  • GET /api/v1/agents/pki/certificates
  • GET /api/v1/agents/pki/certificates/{certificate_id}
  • PATCH /api/v1/agents/pki/certificates/{certificate_id}/status
  • POST /api/v1/agents/pki/certificates/{certificate_id}/rotation-required
  • POST /api/v1/agents/pki/certificates/{certificate_id}/revocation-request
  • GET /api/v1/agents/{agent_id}/pki
  • GET /api/v1/agents/onboarding/pki

GUI-Aenderungen

  • /zero-trust/ zeigt Agent-PKI, CSR und mTLS-Governance mit Provider-, CSR-, Zertifikats-, Rotation- und Widerrufstatus.
  • Schreibende Rollen erhalten Formulare und Aktionen fuer Provider, CSR-Review und Zertifikatsstatus.
  • Read-only-Rollen sehen sichere Metadaten ohne Schreibaktionen.
  • Der gefuehrte Agent-Onboarding-Assistent zeigt den PKI-/mTLS-Vorbereitungsstatus.

Tenant- und Berechtigungsgrenzen

  • Alle Lese- und Schreibpfade nutzen den bestehenden ISCY Tenant/User-Kontext.
  • DB-Abfragen enthalten Tenant-Praedikate.
  • Schreibaktionen bleiben schreibenden Rollen vorbehalten; Auditor/Read-only sieht nur sichere Metadaten.
  • Fremde Agenten, Provider, CSR und Zertifikatsstatus werden nicht verknuepft oder angezeigt.
  • Manipulierte Agent-/Provider-/CSR-/Certificate-IDs werden tenantgebunden validiert.

Security-Entscheidungen

  • Keine privaten Schluessel, keine produktiven CA-Secrets, keine Cloud-Credentials.
  • Keine echte CA-Anbindung, keine externe Zertifikatsausstellung, keine CA-Netzwerkaufrufe.
  • Keine automatische mTLS-Aktivierung, produktive Rotation oder produktiver Widerruf.
  • CSR-PEM wird nicht roh als Freitext gespeichert; Fingerprints/Hashes und redigierte Metadaten werden bevorzugt.
  • Private-key-, Secret-, Token- und lokale Pfadfragmente in PKI-Metadaten werden abgelehnt.
  • API-/UI-Fehler geben keine SQL-/Store-Details, Secrets oder lokalen Pfade aus.
  • Keine Dependency-, Toolchain-, Flake-, Docker-, nginx-, Postgres- oder CI-Upgrades.

Ausgefuehrte Tests

  • cargo fmt --manifest-path rust/iscy-backend/Cargo.toml -- --check
  • cargo clippy --locked --manifest-path rust/iscy-backend/Cargo.toml --all-targets -- -D warnings
  • cargo test --locked --manifest-path rust/iscy-backend/Cargo.toml
  • cargo audit --file rust/iscy-backend/Cargo.lock --ignore RUSTSEC-2023-0071
  • cargo deny --manifest-path rust/iscy-backend/Cargo.toml check advisories licenses sources
  • make rust-smoke
  • make rust-restore-smoke
  • nix flake check
  • make docs-pdf
  • Docker Compose config fuer dev, stage, prod, prod+llm und monitoring mit temporaerer Dummy-Env.
  • PostgreSQL-Live-Restore-Drill mit temporaerer lokaler PostgreSQL-16-Instanz, Quell- und Restore-DB; Migration 0037 und vier neue PKI-Tabellen im Restore verifiziert.
  • git diff --check

Hinweis: Der lokale hardened Docker-Build konnte nicht ausgefuehrt werden, weil auf diesem Rechner kein Docker-Daemon/Sockel unter /var/run/docker.sock verfuegbar ist. Die GitHub-CI wird dafuer abgewartet.

Bekannte Einschraenkungen

  • Das Modell ist bewusst Metadata-only.
  • Es gibt noch keine produktive CA-/PKI-Provider-Anbindung.
  • Es gibt keine automatische Zertifikatsausstellung, Rotation, Revocation oder mTLS-Durchsetzung.
  • Produktive lokale CSR-/Key-Erzeugung auf Agenten bleibt ein separater Security-Meilenstein.

Bewusst nicht umgesetzt

  • Keine Dependency-Updates.
  • Keine offenen Bot-/Dependabot-PRs angefasst.
  • Keine Plattform-Upgrades, kein Rust-Docker-, Postgres-, nginx- oder nixpkgs-Upgrade.
  • Keine neue Evidence-, Risk-, Control-, Notification- oder Release-Engine.
  • Keine Rechtsberatung, Zertifizierung, automatische Behoerdenmeldung oder produktive CA-/mTLS-Automation.

@ewilhelm1979-netizen ewilhelm1979-netizen marked this pull request as ready for review July 9, 2026 20:39
@ewilhelm1979-netizen ewilhelm1979-netizen merged commit 1e2221f into main Jul 9, 2026
7 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2f63cf1d96

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1591 to +1593
agent_id = excluded.agent_id,
ca_provider_id = excluded.ca_provider_id,
serial_number_hash = excluded.serial_number_hash,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve existing certificate metadata on PATCH

The status route is registered as PATCH and every field in AgentCertificateStatusUpdateRequest is optional, but a client that sends only a status change like {"certificate_status":"active"} reaches this conflict update with excluded.agent_id = NULL, excluded.ca_provider_id = '', empty fingerprints/evidence IDs, etc. That turns a status-only update into a destructive rewrite of the certificate’s existing agent/provider binding and evidence metadata; merge omitted fields from the current row or only update fields present in the payload.

Useful? React with 👍 / 👎.

Comment on lines +1230 to +1232
payload.ca_provider_id = Some(ca_provider_id.to_string());
create_provider_sqlite(pool, tenant_id, actor_id, payload)
.await

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve provider fields during PATCH updates

PATCH /api/v1/agents/pki/providers/{id} accepts a sparse AgentPkiProviderWriteRequest, but this forwards the sparse payload into create_provider, whose normalizer fills omitted fields with defaults. A status-only provider patch therefore resets the provider name, trust domain, policies, lifetimes, and limitations to default text, losing existing CA governance metadata; merge the payload with the current provider first or make this a full replace operation.

Useful? React with 👍 / 👎.

mtls_binding_status,
rotation_status,
revocation_status,
evidence_ids_json: json_i64_array(payload.evidence_ids, 50)?,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate evidence IDs against the tenant before persisting

When a certificate status includes evidence_ids, the payload only filters to positive integers and serializes them; no tenant-scoped lookup of evidence_evidenceitem is performed before the value is stored and returned. A tenant contributor can therefore attach arbitrary or another tenant’s private Evidence IDs to their certificate status, corrupting governance/review data and violating the evidence tenant-boundary invariant; validate each ID with tenant_id before accepting it.

Useful? React with 👍 / 👎.

"cancelled" => "csr_status = 'cancelled', rejected_by = rejected_by, rejection_reason = CASE WHEN ?2 = '' THEN rejection_reason ELSE ?2 END, approved_by = approved_by + (?1 - ?1)",
_ => "csr_status = 'failed', rejected_by = rejected_by, rejection_reason = CASE WHEN ?2 = '' THEN rejection_reason ELSE ?2 END, approved_by = approved_by + (?1 - ?1)",
};
format!("UPDATE agent_certificate_request SET {assignment}, updated_at = CURRENT_TIMESTAMP WHERE tenant_id = ?3 AND csr_id = ?4 RETURNING {CSR_COLUMNS}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restrict CSR decisions to pending requests

These transition updates match only tenant_id and csr_id, so any existing CSR can be approved, rejected, or cancelled regardless of its current status. For example, an already approved CSR can later be rejected or cancelled through the new endpoints, rewriting the approval/rejection fields and audit state; add a current-status predicate such as pending_review or enforce an explicit transition matrix in both query builders.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant