fix(device-plane): constrain B2 discovery to loopback
This commit is contained in:
parent
2b1795509b
commit
a3308c9b3d
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"schemaVersion": "nodedc.device-plane.b2-discovery-ingress.v1",
|
||||
"mode": "verified-b2-discovery-only",
|
||||
"mode": "verified-b2-loopback-discovery-only",
|
||||
"predecessorPatchId": "device-plane-foundation-network-publication-20260725-003",
|
||||
"predecessorArtifactSha256": "6fdd5a12c310786db1753882fc1378184fe378d2cc533633a8c73c951521b7bf",
|
||||
"sourceAction": "publish-verified-b2-discovery-ingress-source",
|
||||
"sourceAction": "publish-verified-b2-loopback-discovery-source",
|
||||
"runtimeAction": "build-and-recreate-stateless-services",
|
||||
"selectedServices": [
|
||||
"device-control-core",
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
"publishedPorts": [
|
||||
"127.0.0.1:18120:18120",
|
||||
"127.0.0.1:18121:18121",
|
||||
"0.0.0.0:9921:9921/tcp"
|
||||
"127.0.0.1:9921:9921/tcp"
|
||||
],
|
||||
"protocolProfile": "arusnavi.b2.internal.v1",
|
||||
"framingSpecification": "arusnavi.internal.protocol-sheet.gid-12.v1",
|
||||
|
|
|
|||
|
|
@ -100,8 +100,8 @@ services:
|
|||
DEVICE_GATEWAY_HEALTH_HOST: 0.0.0.0
|
||||
DEVICE_GATEWAY_HEALTH_PORT: "18121"
|
||||
DEVICE_GATEWAY_LISTEN_ENABLED: "true"
|
||||
DEVICE_GATEWAY_PUBLIC_INGRESS_ENABLED: "true"
|
||||
DEVICE_GATEWAY_TCP_HOST: 0.0.0.0
|
||||
DEVICE_GATEWAY_PUBLIC_INGRESS_ENABLED: "false"
|
||||
DEVICE_GATEWAY_TCP_HOST: 127.0.0.1
|
||||
DEVICE_GATEWAY_TCP_PORT: "9921"
|
||||
DEVICE_GATEWAY_CORE_URL: http://device-control-core:18120
|
||||
DEVICE_GATEWAY_CORE_TOKEN_FILE: /run/nodedc-secrets/gateway-core-token
|
||||
|
|
@ -120,7 +120,7 @@ services:
|
|||
create_host_path: false
|
||||
ports:
|
||||
- "127.0.0.1:18121:18121"
|
||||
- "0.0.0.0:9921:9921"
|
||||
- "127.0.0.1:9921:9921"
|
||||
networks:
|
||||
- device-plane-private
|
||||
- device-plane-control
|
||||
|
|
|
|||
|
|
@ -193,10 +193,12 @@ raw TCP remain forbidden until separate reviewed acceptance slices.
|
|||
through the standalone root administrative gate.
|
||||
3. Plan/apply the exact discovery-ingress artifact and independently prove:
|
||||
Core/Gateway/PostgreSQL health, PostgreSQL generation preservation,
|
||||
`0.0.0.0:9921` publication, verified framing, quarantine-only Core ingest and
|
||||
disabled command transport.
|
||||
4. Only after runtime acceptance, allow TCP 9921 in DSM firewall and configure
|
||||
WAN-to-NAS TCP forwarding. Keep the HTTP(S) Reverse Proxy out of this path.
|
||||
5. Add the NDC route to one approved B2 free server slot while preserving
|
||||
Gelios, then prove HEADER/discovery/PACKAGE acknowledgement. Claim and
|
||||
tenant assignment remain a later explicit platform-admin operation.
|
||||
`127.0.0.1:9921` loopback-only publication, verified framing,
|
||||
quarantine-only Core ingest and disabled command transport.
|
||||
4. Do not publish raw device TCP from the multi-service Synology. Design and
|
||||
independently review an isolated edge/DMZ/VPS ingress with no lateral NAS
|
||||
access, explicit firewall/NAT evidence, acceptance and rollback.
|
||||
5. Only after that separate edge gate, add the NDC route to one approved B2
|
||||
free server slot while preserving Gelios, then prove
|
||||
HEADER/discovery/PACKAGE acknowledgement. Claim and tenant assignment
|
||||
remain a later explicit platform-admin operation.
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ const artifactDir = resolve(
|
|||
|| resolve(scriptDir, "../deploy-artifacts"),
|
||||
);
|
||||
const [
|
||||
patchId = "device-plane-b2-discovery-ingress-20260726-001",
|
||||
patchId = "device-plane-b2-discovery-loopback-20260726-002",
|
||||
...extra
|
||||
] = process.argv.slice(2);
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ try {
|
|||
artifact: target,
|
||||
sha256: digest,
|
||||
component: "device-plane",
|
||||
transition: "verified-b2-discovery-only",
|
||||
transition: "verified-b2-loopback-discovery-only",
|
||||
entries: files,
|
||||
services: ["device-control-core", "device-gateway"],
|
||||
preservedRuntime: [
|
||||
|
|
@ -109,8 +109,8 @@ try {
|
|||
],
|
||||
ingress: {
|
||||
transport: "tcp",
|
||||
published: "0.0.0.0:9921:9921",
|
||||
mode: "discovery-only",
|
||||
published: "127.0.0.1:9921:9921",
|
||||
mode: "loopback-discovery-only",
|
||||
framing: "verified-read-only",
|
||||
lifecycle: "quarantine",
|
||||
commandTransport: "disabled",
|
||||
|
|
@ -137,12 +137,12 @@ async function assertBoundary() {
|
|||
for (const fragment of [
|
||||
'DEVICE_DISCOVERY_INGEST_ENABLED: "true"',
|
||||
'DEVICE_GATEWAY_LISTEN_ENABLED: "true"',
|
||||
'DEVICE_GATEWAY_PUBLIC_INGRESS_ENABLED: "true"',
|
||||
'DEVICE_GATEWAY_PUBLIC_INGRESS_ENABLED: "false"',
|
||||
"DEVICE_GATEWAY_CORE_URL: http://device-control-core:18120",
|
||||
"DEVICE_GATEWAY_CORE_TOKEN_FILE: /run/nodedc-secrets/gateway-core-token",
|
||||
'"127.0.0.1:18120:18120"',
|
||||
'"127.0.0.1:18121:18121"',
|
||||
'"0.0.0.0:9921:9921"',
|
||||
'"127.0.0.1:9921:9921"',
|
||||
"name: nodedc-device-plane-private",
|
||||
"internal: true",
|
||||
"name: nodedc-device-plane-control",
|
||||
|
|
@ -180,12 +180,12 @@ async function assertBoundary() {
|
|||
));
|
||||
const expected = {
|
||||
schemaVersion: "nodedc.device-plane.b2-discovery-ingress.v1",
|
||||
mode: "verified-b2-discovery-only",
|
||||
mode: "verified-b2-loopback-discovery-only",
|
||||
predecessorPatchId:
|
||||
"device-plane-foundation-network-publication-20260725-003",
|
||||
predecessorArtifactSha256:
|
||||
"6fdd5a12c310786db1753882fc1378184fe378d2cc533633a8c73c951521b7bf",
|
||||
sourceAction: "publish-verified-b2-discovery-ingress-source",
|
||||
sourceAction: "publish-verified-b2-loopback-discovery-source",
|
||||
runtimeAction: "build-and-recreate-stateless-services",
|
||||
selectedServices: ["device-control-core", "device-gateway"],
|
||||
preservedServices: ["device-postgres"],
|
||||
|
|
@ -194,7 +194,7 @@ async function assertBoundary() {
|
|||
publishedPorts: [
|
||||
"127.0.0.1:18120:18120",
|
||||
"127.0.0.1:18121:18121",
|
||||
"0.0.0.0:9921:9921/tcp",
|
||||
"127.0.0.1:9921:9921/tcp",
|
||||
],
|
||||
protocolProfile: "arusnavi.b2.internal.v1",
|
||||
framingSpecification:
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ DEVICE_PLANE_B2_DISCOVERY_INGRESS_PREDECESSOR_ARTIFACT_SHA256 = (
|
|||
"6fdd5a12c310786db1753882fc1378184fe378d2cc533633a8c73c951521b7bf"
|
||||
)
|
||||
DEVICE_PLANE_B2_DISCOVERY_INGRESS_COMPOSE_SHA256 = (
|
||||
"50bc7842481ea73b89891a65bf243c2ecb7bbb4c093e95e3c20ddbfaa8ad6726"
|
||||
"eb1018cc0ffeaa0c019944d8810e2daa01eeca4c06289efff175785fb16457e7"
|
||||
)
|
||||
DEVICE_PLANE_FOUNDATION_FAILED_PATCH_ID = (
|
||||
"device-plane-foundation-20260725-001"
|
||||
|
|
@ -8362,14 +8362,14 @@ def validate_device_plane_foundation_network_publication_payload(payload_dir):
|
|||
def expected_device_plane_b2_discovery_ingress_descriptor():
|
||||
return {
|
||||
"schemaVersion": "nodedc.device-plane.b2-discovery-ingress.v1",
|
||||
"mode": "verified-b2-discovery-only",
|
||||
"mode": "verified-b2-loopback-discovery-only",
|
||||
"predecessorPatchId": (
|
||||
DEVICE_PLANE_B2_DISCOVERY_INGRESS_PREDECESSOR_PATCH_ID
|
||||
),
|
||||
"predecessorArtifactSha256": (
|
||||
DEVICE_PLANE_B2_DISCOVERY_INGRESS_PREDECESSOR_ARTIFACT_SHA256
|
||||
),
|
||||
"sourceAction": "publish-verified-b2-discovery-ingress-source",
|
||||
"sourceAction": "publish-verified-b2-loopback-discovery-source",
|
||||
"runtimeAction": "build-and-recreate-stateless-services",
|
||||
"selectedServices": [
|
||||
"device-control-core",
|
||||
|
|
@ -8381,7 +8381,7 @@ def expected_device_plane_b2_discovery_ingress_descriptor():
|
|||
"publishedPorts": [
|
||||
"127.0.0.1:18120:18120",
|
||||
"127.0.0.1:18121:18121",
|
||||
"0.0.0.0:9921:9921/tcp",
|
||||
"127.0.0.1:9921:9921/tcp",
|
||||
],
|
||||
"protocolProfile": "arusnavi.b2.internal.v1",
|
||||
"framingSpecification": (
|
||||
|
|
@ -9381,7 +9381,7 @@ def validate_device_plane_b2_discovery_ingress_runtime(runtime_before):
|
|||
"HostPort": "18121",
|
||||
}],
|
||||
"9921/tcp": [{
|
||||
"HostIp": "0.0.0.0",
|
||||
"HostIp": "127.0.0.1",
|
||||
"HostPort": "9921",
|
||||
}],
|
||||
},
|
||||
|
|
@ -9492,8 +9492,8 @@ def validate_device_plane_b2_discovery_ingress_runtime(runtime_before):
|
|||
)
|
||||
gateway_required = {
|
||||
"DEVICE_GATEWAY_LISTEN_ENABLED": "true",
|
||||
"DEVICE_GATEWAY_PUBLIC_INGRESS_ENABLED": "true",
|
||||
"DEVICE_GATEWAY_TCP_HOST": "0.0.0.0",
|
||||
"DEVICE_GATEWAY_PUBLIC_INGRESS_ENABLED": "false",
|
||||
"DEVICE_GATEWAY_TCP_HOST": "127.0.0.1",
|
||||
"DEVICE_GATEWAY_TCP_PORT": "9921",
|
||||
"DEVICE_GATEWAY_CORE_URL": "http://device-control-core:18120",
|
||||
"DEVICE_GATEWAY_CORE_TOKEN_FILE":
|
||||
|
|
@ -15182,7 +15182,7 @@ def plan_artifact(artifact):
|
|||
)
|
||||
print("device_postgres_volume=preserved:nodedc-device-plane-postgres-data")
|
||||
if device_plane_b2_ingress_preflight is not None:
|
||||
print("device_gateway_public_ingress=discovery-only:tcp:9921")
|
||||
print("device_gateway_public_ingress=disabled:loopback-test:tcp:9921")
|
||||
print("device_control_core_discovery_ingest=enabled:authenticated")
|
||||
else:
|
||||
print("device_gateway_public_ingress=disabled")
|
||||
|
|
@ -15284,7 +15284,7 @@ def plan_artifact(artifact):
|
|||
print(
|
||||
"device_plane_actual_ports="
|
||||
"required:127.0.0.1:18120,127.0.0.1:18121,"
|
||||
"0.0.0.0:9921/tcp"
|
||||
"127.0.0.1:9921/tcp"
|
||||
)
|
||||
print(
|
||||
"device_gateway_framing="
|
||||
|
|
@ -16622,7 +16622,7 @@ def component_healthchecks(component, entries=None, services=None):
|
|||
"service": "nodedc-device-gateway",
|
||||
"framing": "verified-read-only",
|
||||
"tcpListener": "discovery-only",
|
||||
"publicIngress": "discovery-only",
|
||||
"publicIngress": "disabled",
|
||||
"commandTransport": "disabled",
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class DevicePlaneB2DiscoveryIngressArtifactTest(unittest.TestCase):
|
|||
)
|
||||
self.assertEqual(
|
||||
first["transition"],
|
||||
"verified-b2-discovery-only",
|
||||
"verified-b2-loopback-discovery-only",
|
||||
)
|
||||
self.assertEqual(
|
||||
first["services"],
|
||||
|
|
@ -119,10 +119,11 @@ class DevicePlaneB2DiscoveryIngressArtifactTest(unittest.TestCase):
|
|||
stateless,
|
||||
)
|
||||
self.assertIn(
|
||||
'DEVICE_GATEWAY_PUBLIC_INGRESS_ENABLED: "true"',
|
||||
'DEVICE_GATEWAY_PUBLIC_INGRESS_ENABLED: "false"',
|
||||
stateless,
|
||||
)
|
||||
self.assertIn('"0.0.0.0:9921:9921"', stateless)
|
||||
self.assertIn('"127.0.0.1:9921:9921"', stateless)
|
||||
self.assertNotIn('"0.0.0.0:9921:9921"', stateless)
|
||||
self.assertNotIn("DEVICE_GATEWAY_COMMAND", compose)
|
||||
self.assertNotIn("POSTGRES_PASSWORD:", compose)
|
||||
|
||||
|
|
@ -145,7 +146,7 @@ class DevicePlaneB2DiscoveryIngressArtifactTest(unittest.TestCase):
|
|||
)
|
||||
self.assertEqual(
|
||||
checks[1]["expected_json"]["publicIngress"],
|
||||
"discovery-only",
|
||||
"disabled",
|
||||
)
|
||||
self.assertEqual(
|
||||
checks[1]["expected_json"]["commandTransport"],
|
||||
|
|
@ -207,14 +208,14 @@ class DevicePlaneB2DiscoveryIngressArtifactTest(unittest.TestCase):
|
|||
"HostPort": "18121",
|
||||
}],
|
||||
"9921/tcp": [{
|
||||
"HostIp": "0.0.0.0",
|
||||
"HostIp": "127.0.0.1",
|
||||
"HostPort": "9921",
|
||||
}],
|
||||
},
|
||||
environment={
|
||||
"DEVICE_GATEWAY_LISTEN_ENABLED": "true",
|
||||
"DEVICE_GATEWAY_PUBLIC_INGRESS_ENABLED": "true",
|
||||
"DEVICE_GATEWAY_TCP_HOST": "0.0.0.0",
|
||||
"DEVICE_GATEWAY_PUBLIC_INGRESS_ENABLED": "false",
|
||||
"DEVICE_GATEWAY_TCP_HOST": "127.0.0.1",
|
||||
"DEVICE_GATEWAY_TCP_PORT": "9921",
|
||||
"DEVICE_GATEWAY_CORE_URL":
|
||||
"http://device-control-core:18120",
|
||||
|
|
|
|||
Loading…
Reference in New Issue