mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-20 11:32:19 +00:00
3b5164032a
A RustFS cluster device needs a durable identity before it can exchange a one-time registration token for a certificate. This adds the device-side half of that exchange, which rustfs/connect already verifies. `connect::identity` builds the canonical registration transcript frozen by protocol/agent/v1/registration-proof.md, signs it as low-S ES256, and emits the PKCS#10 certificate request Connect consumes for its SubjectPublicKeyInfo. `connect::identity_store` seals the P-256 key at mode 0600 and publishes it through a no-clobber link, so a retry or a concurrent start returns the original identity rather than minting a second one, and a corrupt or widened key is refused rather than silently replaced. The protocol fixture set is copied here byte-identically because fixture-sets.json names this repository as the consumer copy; the tests verify it against its own manifests and cross-verify Connect-produced ECDSA proofs against transcripts rebuilt locally. Nothing starts a task or touches the S3 data path: an unenrolled deployment generates no key and holds no identity.
83 lines
2.7 KiB
JSON
83 lines
2.7 KiB
JSON
{
|
|
"protocolVersion": "v1",
|
|
"fixtureSet": "auth",
|
|
"fixture": "certificate-profile",
|
|
"description": "Frozen shape of the client certificate an online device presents and of the RFC 9440 header that conveys it.",
|
|
"certificate": {
|
|
"subject": {
|
|
"rdnCount": 1,
|
|
"commonName": "{clusterDeviceUid}",
|
|
"forbiddenAttributes": ["O", "OU", "C", "ST", "L", "emailAddress"]
|
|
},
|
|
"subjectAlternativeName": {
|
|
"entryCount": 1,
|
|
"type": "uniformResourceIdentifier",
|
|
"value": "urn:rustfs:connect:device:{clusterDeviceUid}",
|
|
"forbiddenTypes": ["dNSName", "iPAddress", "rfc822Name", "directoryName"],
|
|
"wildcardsAccepted": false
|
|
},
|
|
"clusterDeviceUid": {
|
|
"source": "cluster_devices.uid",
|
|
"format": "lowercase canonical UUIDv7",
|
|
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
},
|
|
"keyAlgorithm": "EC",
|
|
"keyCurve": "P-256",
|
|
"signatureAlgorithm": "ES256",
|
|
"certificateSigningRequest": {
|
|
"format": "PKCS#10",
|
|
"signatureAlgorithm": "ES256",
|
|
"proofOfPossession": "self-signed with the device private key"
|
|
},
|
|
"lifetimeSeconds": 86400,
|
|
"maxRotationOverlapSeconds": 86400,
|
|
"recommendedRotationLeadSeconds": 28800,
|
|
"maxPresentableCredentialsPerDevice": 2,
|
|
"serial": {
|
|
"encoding": "lowercase-hex",
|
|
"length": 32,
|
|
"pattern": "^[0-9a-f]{32}$",
|
|
"entropyBits": 128
|
|
},
|
|
"certificateFingerprint": {
|
|
"algorithm": "SHA-256",
|
|
"over": "DER certificate",
|
|
"encoding": "lowercase-hex",
|
|
"pattern": "^[0-9a-f]{64}$"
|
|
},
|
|
"publicKeyFingerprint": {
|
|
"algorithm": "SHA-256",
|
|
"over": "DER SubjectPublicKeyInfo",
|
|
"encoding": "lowercase-hex",
|
|
"pattern": "^[0-9a-f]{64}$"
|
|
},
|
|
"keyId": {
|
|
"pattern": "^[a-z0-9][a-z0-9._-]{7,127}$"
|
|
},
|
|
"carriesOrganizationIdentifier": false,
|
|
"carriesClusterIdentifier": false,
|
|
"tenantBinding": {
|
|
"source": "device_credentials matched by certificate serial and certificate fingerprint",
|
|
"resolver": "ClusterDeviceIdentityPort::resolveOnlineCertificate"
|
|
}
|
|
},
|
|
"header": {
|
|
"name": "Client-Cert",
|
|
"specification": "RFC 9440",
|
|
"encoding": "sf-binary",
|
|
"valueTemplate": ":{base64(DER certificate)}:",
|
|
"example": ":MIIBkDCCATagAwIBAgIQZXhhbXBsZQ==:",
|
|
"chainHeader": {
|
|
"name": "Client-Cert-Chain",
|
|
"accepted": false,
|
|
"reason": "Chain validation belongs to the trusted ingress, which verifies against the Connect device CA before forwarding."
|
|
},
|
|
"setByTrustedIngressOnly": true,
|
|
"inboundHeaderStripped": true,
|
|
"appendAccepted": false,
|
|
"acceptedOnSurfaces": ["/agent"],
|
|
"ignoredOnSurfaces": ["/api"],
|
|
"backendPubliclyReachable": false
|
|
}
|
|
}
|