- Add CaService (@Injectable) that POSTs CSRs to step-ca /1.0/sign over HTTPS with a pinned CA root cert; builds HS256 OTT with custom claims mosaic_grant_id and mosaic_subject_user_id plus step.sha CSR fingerprint - Add CaServiceError with cause + remediation for fail-loud contract - Add IssueCertRequestDto and IssuedCertDto with class-validator decorators - Add FederationModule exporting CaService; wire into AppModule - Replace federation.tpl TODO placeholder with real step-ca Go template emitting OID 1.3.6.1.4.1.99999.1 (grantId) and .2 (subjectUserId) as DER UTF8String extensions (tag 0x0C, length 0x24, base64-encoded value) - Update infra/step-ca/init.sh to patch mosaic-fed provisioner config with templateFile path via jq on first boot (idempotent) - Append OID assignment registry and CA env var table to docs/federation/SETUP.md - 11 unit tests pass: happy path, certChain fallbacks, HTTP 401/4xx, malformed CSR (no HTTP call), non-JSON response, connection error, JWT claim assertions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
57 lines
1.9 KiB
Smarty
57 lines
1.9 KiB
Smarty
{
|
|
"subject": {{ toJson .Subject }},
|
|
"sans": {{ toJson .SANs }},
|
|
|
|
{{- /*
|
|
Mosaic Federation X.509 Certificate Template
|
|
============================================
|
|
Provisioner: mosaic-fed (JWK)
|
|
Implemented: FED-M2-04
|
|
|
|
This template emits two custom OID extensions carrying Mosaic federation
|
|
identifiers. The OTT token (built by CaService.buildOtt) MUST include the
|
|
claims `mosaic_grant_id` and `mosaic_subject_user_id` as top-level JWT
|
|
claims. step-ca exposes them under `.Token.<claim>` in this template.
|
|
|
|
OID Registry (Mosaic Internal Arc — 1.3.6.1.4.1.99999):
|
|
1.3.6.1.4.1.99999.1 mosaic_grant_id (UUID, 36 ASCII chars)
|
|
1.3.6.1.4.1.99999.2 mosaic_subject_user_id (UUID, 36 ASCII chars)
|
|
|
|
DER encoding for each extension value (ASN.1 UTF8String):
|
|
Tag = 0x0C (UTF8String)
|
|
Length = 0x24 (decimal 36 — the fixed length of a UUID string)
|
|
Value = 36 ASCII bytes of the UUID
|
|
|
|
The `printf` below builds the raw TLV bytes then base64-encodes them.
|
|
step-ca expects the `value` field to be base64-encoded raw DER bytes.
|
|
|
|
Fail-loud contract:
|
|
If either claim is missing from the token the printf will produce a
|
|
zero-length UUID field, making the extension malformed. step-ca will
|
|
reject the certificate rather than issuing one without the required OIDs.
|
|
Silent OID stripping is NEVER tolerated.
|
|
|
|
Step-CA template reference:
|
|
https://smallstep.com/docs/step-ca/templates
|
|
*/ -}}
|
|
|
|
"extensions": [
|
|
{
|
|
"id": "1.3.6.1.4.1.99999.1",
|
|
"critical": false,
|
|
"value": "{{ printf "\x0c\x24%s" .Token.mosaic_grant_id | b64enc }}"
|
|
},
|
|
{
|
|
"id": "1.3.6.1.4.1.99999.2",
|
|
"critical": false,
|
|
"value": "{{ printf "\x0c\x24%s" .Token.mosaic_subject_user_id | b64enc }}"
|
|
}
|
|
],
|
|
|
|
"keyUsage": ["digitalSignature"],
|
|
"extKeyUsage": ["clientAuth"],
|
|
"basicConstraints": {
|
|
"isCA": false
|
|
}
|
|
}
|