feat(security): trusted-services surface + auth mgmt client (M2 §3)
Maestro is the UI/CA, not the enforcement: the auth service owns its
authorized-keys trust store. This is Maestro's side of the flow.
- lib/authmgmt: mTLS management client (Maestro's own identity cert from
the instance CA) for /internal/{attestation,authorizations,revoke,
pending}; RevokeServiceBestEffort for uninstall.
- handlers/peers: GET /api/peers, /api/peers/attestation, POST
approve/revoke.
- uninstall: revoke the service's authorization in the auth trust store
alongside the CRL identity revocation.
- frontend: TrustedServices panel (pending first-contact authorizations +
approved keys with authorize/ignore/revoke actions).
- spec.yaml: document the new endpoints and schemas.
- housekeeping: untrack pki test log artifacts, gofmt fixes in pki.
This commit is contained in:
@@ -29,6 +29,62 @@ components:
|
||||
message:
|
||||
type: string
|
||||
|
||||
PendingAuthorization:
|
||||
type: object
|
||||
description: A first-contact authorization request awaiting the instance owner (M2 §3).
|
||||
properties:
|
||||
service:
|
||||
type: string
|
||||
example: "keepnote"
|
||||
fingerprint:
|
||||
type: string
|
||||
example: "sha256:aa:bb:cc:dd"
|
||||
first_seen:
|
||||
type: string
|
||||
last_seen:
|
||||
type: string
|
||||
|
||||
AuthorizedKey:
|
||||
type: object
|
||||
description: An approved peer row of the auth service's trust store.
|
||||
properties:
|
||||
service:
|
||||
type: string
|
||||
fingerprint:
|
||||
type: string
|
||||
approved_by:
|
||||
type: string
|
||||
approved_at:
|
||||
type: string
|
||||
revoked_at:
|
||||
type: string
|
||||
nullable: true
|
||||
|
||||
PeerAction:
|
||||
type: object
|
||||
required: [service, fingerprint]
|
||||
properties:
|
||||
service:
|
||||
type: string
|
||||
description: The service name (cert CN / org.dcntrlized.service).
|
||||
fingerprint:
|
||||
type: string
|
||||
description: The SHA256 public-key fingerprint (sha256:…) shown to the owner.
|
||||
|
||||
Attestation:
|
||||
type: object
|
||||
description: The auth service's public signing key statement (D3).
|
||||
properties:
|
||||
public_key:
|
||||
type: string
|
||||
fingerprint:
|
||||
type: string
|
||||
example: "sha256:…"
|
||||
kid:
|
||||
type: string
|
||||
issued_at:
|
||||
type: string
|
||||
|
||||
RegistryContainer:
|
||||
type: object
|
||||
required: [name, image]
|
||||
@@ -399,3 +455,94 @@ paths:
|
||||
responses:
|
||||
'101':
|
||||
description: Switching Protocols - WebSocket upgrade
|
||||
|
||||
/api/peers:
|
||||
get:
|
||||
summary: List pending authorizations and the approved peer trust store
|
||||
tags: ["security"]
|
||||
description: >
|
||||
Security theme M2 §3. Returns the shared auth service's first-contact
|
||||
authorization requests (services whose certificate is valid but has
|
||||
not been approved by the instance owner yet) and the approved keys.
|
||||
Maestro is only the UI; the auth service owns the enforcement.
|
||||
responses:
|
||||
'200':
|
||||
description: Combined pending + approved trust state
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
pending:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/PendingAuthorization'
|
||||
authorized:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/AuthorizedKey'
|
||||
'500':
|
||||
description: Internal server error (auth management client unavailable)
|
||||
'502':
|
||||
description: Failed to reach the shared auth service
|
||||
|
||||
/api/peers/attestation:
|
||||
get:
|
||||
summary: Read the auth service's public signing key statement
|
||||
tags: ["security"]
|
||||
description: >
|
||||
The auth service's RSA public key, its kid, and the sha256 fingerprint
|
||||
peers should pin after first contact (TOFU, D3).
|
||||
responses:
|
||||
'200':
|
||||
description: Auth public key attestation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Attestation'
|
||||
'502':
|
||||
description: Failed to reach the shared auth service
|
||||
|
||||
/api/peers/approve:
|
||||
post:
|
||||
summary: Approve a peer's fingerprint in the auth service trust store
|
||||
tags: ["security"]
|
||||
description: >
|
||||
Forwards the instance owner's approval for a service's identity
|
||||
fingerprint. After this call the service's requests to /auth/* proceed
|
||||
normally (enforced by the auth service itself).
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PeerAction'
|
||||
responses:
|
||||
'200':
|
||||
description: Peer approved
|
||||
'400':
|
||||
description: Missing service or fingerprint
|
||||
'502':
|
||||
description: Failed to reach the shared auth service
|
||||
|
||||
/api/peers/revoke:
|
||||
post:
|
||||
summary: Revoke a peer's fingerprint (returns it to the no-op path)
|
||||
tags: ["security"]
|
||||
description: >
|
||||
Forwards the instance owner's revocation. Calls from that fingerprint
|
||||
become uniform 403 no-ops again immediately (the SSH authorized_keys
|
||||
"delete the line" action).
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PeerAction'
|
||||
responses:
|
||||
'200':
|
||||
description: Peer revoked
|
||||
'400':
|
||||
description: Missing service or fingerprint
|
||||
'502':
|
||||
description: Failed to reach the shared auth service
|
||||
|
||||
Reference in New Issue
Block a user