mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-21 20:06:37 +00:00
feat(connect): add device identity store and registration proof (#6267)
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
610eeaf44cb7a9a4ed2e4f076c2aec6050a5b81e873fa5c97845155b7ee727a2 additive-compatibility.json
|
||||
3c9453cdbb34557d08ac63a1e2d7024870c8794e7d0cdc48c3a7fdfd2fa8b15f field-registry.json
|
||||
3c7fe86634b7c85da87865498a6677968a78fad1be6d69ed5b3607c29d47430e negotiation-vectors.json
|
||||
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"protocolVersion": "v1",
|
||||
"fixtureSet": "version",
|
||||
"fixture": "additive-compatibility",
|
||||
"description": "Release skew in both directions. v1 grows by optional fields only, so an unknown field is discarded and an absent one takes its documented default.",
|
||||
"vectors": [
|
||||
{
|
||||
"name": "new agent sends a v1 field this Connect does not know",
|
||||
"direction": "new-agent-to-old-connect",
|
||||
"payload": {
|
||||
"protocolVersion": "v1",
|
||||
"agentVersion": "1.9.0",
|
||||
"capabilities": ["heartbeat"],
|
||||
"telemetryProfile": "extended"
|
||||
},
|
||||
"expected": {
|
||||
"decision": "ACCEPT",
|
||||
"retained": ["protocolVersion", "agentVersion", "capabilities"],
|
||||
"discarded": ["telemetryProfile"],
|
||||
"defaultsApplied": {},
|
||||
"echoedBack": [],
|
||||
"stored": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "new agent sends several unknown optional fields at once",
|
||||
"direction": "new-agent-to-old-connect",
|
||||
"payload": {
|
||||
"protocolVersion": "v1",
|
||||
"capabilities": ["heartbeat", "inventory", "bundle.upload"],
|
||||
"telemetryProfile": "extended",
|
||||
"regionHint": "eu-west",
|
||||
"experimentalFlags": {
|
||||
"fastHeartbeat": true
|
||||
}
|
||||
},
|
||||
"expected": {
|
||||
"decision": "ACCEPT",
|
||||
"retained": ["protocolVersion", "capabilities"],
|
||||
"discarded": ["telemetryProfile", "regionHint", "experimentalFlags"],
|
||||
"defaultsApplied": {
|
||||
"agentVersion": null
|
||||
},
|
||||
"echoedBack": [],
|
||||
"stored": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "old agent omits every optional field",
|
||||
"direction": "old-agent-to-new-connect",
|
||||
"payload": {
|
||||
"protocolVersion": "v1"
|
||||
},
|
||||
"expected": {
|
||||
"decision": "ACCEPT",
|
||||
"retained": ["protocolVersion"],
|
||||
"discarded": [],
|
||||
"defaultsApplied": {
|
||||
"agentVersion": null,
|
||||
"capabilities": []
|
||||
},
|
||||
"echoedBack": [],
|
||||
"stored": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "old agent reports no capabilities but names itself",
|
||||
"direction": "old-agent-to-new-connect",
|
||||
"payload": {
|
||||
"protocolVersion": "v1",
|
||||
"agentVersion": "1.0.0"
|
||||
},
|
||||
"expected": {
|
||||
"decision": "ACCEPT",
|
||||
"retained": ["protocolVersion", "agentVersion"],
|
||||
"discarded": [],
|
||||
"defaultsApplied": {
|
||||
"capabilities": []
|
||||
},
|
||||
"echoedBack": [],
|
||||
"stored": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "unknown fields do not rescue an unsupported major version",
|
||||
"direction": "new-agent-to-old-connect",
|
||||
"payload": {
|
||||
"protocolVersion": "v2",
|
||||
"agentVersion": "2.0.0",
|
||||
"compatibilityShim": "v1"
|
||||
},
|
||||
"expected": {
|
||||
"decision": "REJECT",
|
||||
"reason": "UNSUPPORTED_PROTOCOL",
|
||||
"httpStatus": 400,
|
||||
"retained": [],
|
||||
"discarded": [],
|
||||
"defaultsApplied": {},
|
||||
"echoedBack": [],
|
||||
"stored": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"protocolVersion": "v1",
|
||||
"fixtureSet": "version",
|
||||
"fixture": "field-registry",
|
||||
"description": "The frozen v1 negotiation envelope. Registration and heartbeat both carry it. Any top-level field not listed here is unknown and is discarded after acceptance.",
|
||||
"envelope": "AgentProtocolNegotiation",
|
||||
"supportedMajorVersions": [1],
|
||||
"protocolVersionPattern": "^v[1-9][0-9]{0,3}$",
|
||||
"unknownFieldPolicy": "accept-and-discard",
|
||||
"unknownCapabilityPolicy": "discard",
|
||||
"fields": [
|
||||
{
|
||||
"name": "protocolVersion",
|
||||
"requiredness": "required",
|
||||
"type": "string",
|
||||
"default": null,
|
||||
"note": "Major version only. The minor and patch level of an agent is not negotiated."
|
||||
},
|
||||
{
|
||||
"name": "agentVersion",
|
||||
"requiredness": "optional",
|
||||
"type": "string",
|
||||
"default": null,
|
||||
"note": "Informational. Connect never compares it for equality with its own version and never gates behavior on it."
|
||||
},
|
||||
{
|
||||
"name": "capabilities",
|
||||
"requiredness": "optional",
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"note": "Unordered token set. A capability an operation requires but the device did not report fails that operation with a structured result, not the connection."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"protocolVersion": "v1",
|
||||
"fixtureSet": "version",
|
||||
"fixture": "negotiation-vectors",
|
||||
"description": "Protocol version decisions. A rejected version fails closed: nothing in the payload is processed, stored, or echoed.",
|
||||
"vectors": [
|
||||
{
|
||||
"name": "supported major version",
|
||||
"request": {
|
||||
"protocolVersion": "v1",
|
||||
"agentVersion": "1.4.0",
|
||||
"capabilities": ["heartbeat", "inventory"]
|
||||
},
|
||||
"expected": {
|
||||
"decision": "ACCEPT",
|
||||
"negotiatedProtocolVersion": "v1",
|
||||
"reason": null,
|
||||
"httpStatus": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "supported major version reported by an agent that sends nothing else",
|
||||
"request": {
|
||||
"protocolVersion": "v1"
|
||||
},
|
||||
"expected": {
|
||||
"decision": "ACCEPT",
|
||||
"negotiatedProtocolVersion": "v1",
|
||||
"reason": null,
|
||||
"httpStatus": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "next major version from a future agent",
|
||||
"request": {
|
||||
"protocolVersion": "v2",
|
||||
"agentVersion": "2.0.0",
|
||||
"capabilities": ["heartbeat"]
|
||||
},
|
||||
"expected": {
|
||||
"decision": "REJECT",
|
||||
"negotiatedProtocolVersion": null,
|
||||
"reason": "UNSUPPORTED_PROTOCOL",
|
||||
"httpStatus": 400
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "far future major version",
|
||||
"request": {
|
||||
"protocolVersion": "v9999"
|
||||
},
|
||||
"expected": {
|
||||
"decision": "REJECT",
|
||||
"negotiatedProtocolVersion": null,
|
||||
"reason": "UNSUPPORTED_PROTOCOL",
|
||||
"httpStatus": 400
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "missing protocol version",
|
||||
"request": {
|
||||
"agentVersion": "1.4.0"
|
||||
},
|
||||
"expected": {
|
||||
"decision": "REJECT",
|
||||
"negotiatedProtocolVersion": null,
|
||||
"reason": "UNSUPPORTED_PROTOCOL",
|
||||
"httpStatus": 400
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "version without its prefix",
|
||||
"request": {
|
||||
"protocolVersion": "1"
|
||||
},
|
||||
"expected": {
|
||||
"decision": "REJECT",
|
||||
"negotiatedProtocolVersion": null,
|
||||
"reason": "UNSUPPORTED_PROTOCOL",
|
||||
"httpStatus": 400
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "uppercase prefix",
|
||||
"request": {
|
||||
"protocolVersion": "V1"
|
||||
},
|
||||
"expected": {
|
||||
"decision": "REJECT",
|
||||
"negotiatedProtocolVersion": null,
|
||||
"reason": "UNSUPPORTED_PROTOCOL",
|
||||
"httpStatus": 400
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "dotted version",
|
||||
"request": {
|
||||
"protocolVersion": "v1.2"
|
||||
},
|
||||
"expected": {
|
||||
"decision": "REJECT",
|
||||
"negotiatedProtocolVersion": null,
|
||||
"reason": "UNSUPPORTED_PROTOCOL",
|
||||
"httpStatus": 400
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "zero major version",
|
||||
"request": {
|
||||
"protocolVersion": "v0"
|
||||
},
|
||||
"expected": {
|
||||
"decision": "REJECT",
|
||||
"negotiatedProtocolVersion": null,
|
||||
"reason": "UNSUPPORTED_PROTOCOL",
|
||||
"httpStatus": 400
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "empty protocol version",
|
||||
"request": {
|
||||
"protocolVersion": ""
|
||||
},
|
||||
"expected": {
|
||||
"decision": "REJECT",
|
||||
"negotiatedProtocolVersion": null,
|
||||
"reason": "UNSUPPORTED_PROTOCOL",
|
||||
"httpStatus": 400
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user