Files
qinglong/docs/operations/ql3-worker-credential-management-live-ceremony.md
T

146 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# QingLong 3.0 Worker Credential Management External OIDC Ceremony
This operation records one external-identity, two-User management ceremony. It creates and approves a
secret-free Worker credential plan, then inspects it without consuming the approval or executing credential
delivery.
It is a short-lived operator command, not a controller. Run it only against an already reviewed Worker
management endpoint. A successful local/K3s fixture is not a substitute for this external report.
## Private inputs
Prepare five canonical absolute paths:
- mode 0600 production client config using the exact Worker endpoint path, TLS server name, CA file, client
certificate file, matching private-key file and a 130 second timeout;
- mode 0600 requester assertion;
- mode 0600 reviewer assertion for a different User from the same external issuer;
- mode 0600 ceremony JSON;
- an unused output path in a canonical private directory.
Both assertions must use:
```text
aud=qinglong3-worker-credential-management
typ=ql3-worker-credential-management+jwt
ql3_purpose=worker-credential-management
```
The client certificate is a separate transport-possession factor. It must be issued by the manager's reviewed
client CA, be absent from the current CRL and must not be reused as an assertion-signing key or Worker execution
identity. A valid certificate never substitutes for either external User assertion.
The ceremony JSON has this exact top-level shape:
```json
{
"schemaVersion": 1,
"planRequest": {
"actionRef": "worker-credential:REVIEWED_WORKER:REVIEWED_GENERATION",
"authorityProjectId": "REVIEWED_AUTHORITY_PROJECT",
"action": "rotate",
"deliveryId": "REVIEWED_UUID",
"workerId": "REVIEWED_WORKER",
"credentialId": "REVIEWED_NEW_CREDENTIAL",
"previousCredentialId": "REVIEWED_PREVIOUS_CREDENTIAL",
"credentialNotBeforeAtMs": 0,
"credentialExpiresAtMs": 0,
"deploymentTargetDigest": "REVIEWED_64_LOWERCASE_HEX_DIGEST",
"deploymentGeneration": "REVIEWED_GENERATION"
},
"approvalRequestId": "REVIEWED_APPROVAL_ID",
"approvalAuditEventId": "REVIEWED_UUID",
"requesterDecisionId": "REVIEWED_SELF_DENY_PROBE_ID",
"requesterDecisionAuditEventId": "REVIEWED_UUID",
"reviewerDecisionId": "REVIEWED_REVIEWER_DECISION_ID",
"reviewerDecisionAuditEventId": "REVIEWED_UUID",
"decisionReasonCode": "reviewed",
"inspectionId": "REVIEWED_INSPECTION_ID"
}
```
Replace both timestamps with valid future millisecond values accepted by the Worker management plan contract.
Use new identifiers dedicated to evidence; do not reuse a production delivery that an executor may consume.
## Run and audit
```bash
export QL3_WORKER_CREDENTIAL_MANAGEMENT_LIVE_CEREMONY=1
pnpm evidence:worker-management-live-ceremony:ql3 -- \
--config=/absolute/private/client.json \
--requester-assertion=/absolute/private/requester.jwt \
--reviewer-assertion=/absolute/private/reviewer.jwt \
--ceremony=/absolute/private/ceremony.json \
--output=/absolute/private/worker-management-ceremony.json
unset QL3_WORKER_CREDENTIAL_MANAGEMENT_LIVE_CEREMONY
pnpm audit:worker-management-live-ceremony:ql3 -- \
--report=/absolute/private/worker-management-ceremony.json
```
The runner performs exactly five calls: requester plan, requester propose, requester self-decision rejection,
reviewer decision and reviewer inspect. It fails if self-decision is accepted, if the resulting approval is not
approved by the reviewer, or if inspect observes a dispatch/consumption.
The report contains no raw assertion, subject, JTI, request ID, Worker identifier, Project identifier, token,
Secret, DSN or private key. Retain it with the IdP/operator change record and the independent durable-audit
evidence.
## Collect independent durable-audit evidence
Create a short-lived PostgreSQL login role outside the QingLong migration stream. It must not inherit or be
granted any QingLong runtime role:
```sql
CREATE ROLE ql3_worker_management_evidence
LOGIN NOINHERIT NOSUPERUSER NOCREATEDB NOCREATEROLE
NOREPLICATION NOBYPASSRLS;
GRANT CONNECT ON DATABASE qinglong
TO ql3_worker_management_evidence;
GRANT USAGE ON SCHEMA ql3
TO ql3_worker_management_evidence;
GRANT SELECT ON
ql3.worker_credential_management_plans,
ql3.approval_requests,
ql3.security_audit_events
TO ql3_worker_management_evidence;
```
Set its password through the deployment's private credential mechanism, not a checked-in SQL file. Prepare a
mode 0600 libpq service file and an independently protected passfile. The service entry should use
`sslmode=verify-full`, the reviewed hostname and an absolute CA path; do not put a DSN on the command line.
Run the second collector only after the ceremony report has passed its offline audit:
```bash
export QL3_WORKER_CREDENTIAL_MANAGEMENT_DURABLE_AUDIT_EVIDENCE=1
pnpm evidence:worker-management-durable-audit:ql3 -- \
--ceremony-report=/absolute/private/worker-management-ceremony.json \
--ceremony=/absolute/private/ceremony.json \
--pg-service-file=/absolute/private/pg_service.conf \
--pg-service=ql3_worker_management_evidence \
--output=/absolute/private/worker-management-durable-audit.json
unset QL3_WORKER_CREDENTIAL_MANAGEMENT_DURABLE_AUDIT_EVIDENCE
pnpm audit:worker-management-durable-audit:ql3 -- \
--report=/absolute/private/worker-management-durable-audit.json
```
The collector rejects a role that can read any other `ql3` table, mutate any `ql3` table, or become a
privileged QingLong role. It observes exactly two durable audit rows: proposal and reviewer decision. The
requester's rejected self-decision must have no audit row because separation-of-duty fails before the database
update/audit insert transaction can commit. The v1 evidence contract requires PostgreSQL 18.4 or a later
security patch in the reviewed 18.x major.
After retaining the report, revoke the three SELECT grants, schema usage and database connect grant, then drop
the short-lived role according to the deployment's credential revocation procedure. Do not retain its passfile
with the low-sensitive evidence reports.
If the runner stops after creating durable facts, inspect them before using any new identifiers. Do not infer
rollback from a missing response and do not hand this evidence-only approval to the credential executor.