deploy(gx10): add DeviceManagement agent mTLS route

This commit is contained in:
Robot
2026-06-19 00:51:01 -05:00
parent 14d89ba49d
commit 0d71a789c2
7 changed files with 125 additions and 6 deletions

View File

@@ -1,7 +1,9 @@
# FlowerCore DeviceManagement on GX10
This adopted GX10 app hosts `FlowerCore.DeviceManagement.Web` at
`https://devices.iamworkin.lan`.
`https://devices.iamworkin.lan`. Agent-only REST/SignalR callbacks can use
`https://devices-agent.iamworkin.lan`, which is a separate Traefik router that
requires a TLS client certificate and forwards the presented PEM to the app.
## Apple MDM Runtime Contract
@@ -35,10 +37,18 @@ DeviceManagement auth is enabled on GX10. The deployment maps
`FlowerCore__Auth__ApiKey`; the unprefixed key keeps the MCP API key post-config
path aligned with REST auth. Agent heartbeat, inventory, command poll, app-catalog,
and command-result callbacks use the agent-specific authorization boundary: the
server validates a device client certificate when Kestrel receives one, and also
accepts only the scoped `DEVICE_MANAGEMENT_AGENT_API_KEY` via `Authorization:
Bearer` or `X-Agent-Api-Key` when TLS is terminated before the app. Operator write
endpoints must use `X-Api-Key`.
server validates a direct device client certificate when Kestrel receives one,
validates Traefik-forwarded client certificate PEM only on
`devices-agent.iamworkin.lan`, and also accepts only the scoped
`DEVICE_MANAGEMENT_AGENT_API_KEY` via `Authorization: Bearer` or
`X-Agent-Api-Key` as the fallback path. Operator write endpoints must use
`X-Api-Key`.
The agent-only Traefik route currently uses `RequireAnyClientCert`; the
application remains the authorization boundary by matching the forwarded client
certificate thumbprint to the enrolled device record. Once DeviceManagement
exports a persistent enrollment CA bundle, switch this TLSOption to
`RequireAndVerifyClientCert` with that CA secret.
## Readiness Check

View File

@@ -0,0 +1,18 @@
{
"apiVersion": "cert-manager.io/v1",
"kind": "Certificate",
"metadata": {
"name": "fc-devicemgmt-agent-tls",
"namespace": "fc-devicemgmt"
},
"spec": {
"dnsNames": [
"devices-agent.iamworkin.lan"
],
"issuerRef": {
"kind": "ClusterIssuer",
"name": "step-ca-acme"
},
"secretName": "fc-devicemgmt-agent-tls"
}
}

View File

@@ -155,6 +155,14 @@
}
}
},
{
"name": "FlowerCore__DeviceManagement__AgentMtls__ForwardedCertificateHosts__0",
"value": "devices-agent.iamworkin.lan"
},
{
"name": "FlowerCore__DeviceManagement__AgentMtls__ForwardedCertificateHeader",
"value": "X-Forwarded-Tls-Client-Cert"
},
{
"name": "FlowerCore__EventBus__Redis__Configuration",
"value": "redis.fc-redis.svc:6379"
@@ -313,7 +321,7 @@
"value": "true"
}
],
"image": "localhost/fc-devicemgmt-web:v20260619-agentkey-48b20bc",
"image": "localhost/fc-devicemgmt-web:v20260619-agentmtls-3b298d7",
"imagePullPolicy": "Never",
"livenessProbe": {
"failureThreshold": 3,

View File

@@ -0,0 +1,42 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "devicemgmt-agent-mtls",
"namespace": "fc-devicemgmt"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`devices-agent.iamworkin.lan`)",
"middlewares": [
{
"name": "devicemgmt-agent-strip-forwarded-cert",
"namespace": "fc-devicemgmt"
},
{
"name": "devicemgmt-agent-pass-client-cert",
"namespace": "fc-devicemgmt"
}
],
"services": [
{
"name": "fc-devicemgmt-web",
"port": 80
}
]
}
],
"tls": {
"options": {
"name": "devicemgmt-agent-mtls",
"namespace": "fc-devicemgmt"
},
"secretName": "fc-devicemgmt-agent-tls"
}
}
}

View File

@@ -0,0 +1,13 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "Middleware",
"metadata": {
"name": "devicemgmt-agent-pass-client-cert",
"namespace": "fc-devicemgmt"
},
"spec": {
"passTLSClientCert": {
"pem": true
}
}
}

View File

@@ -0,0 +1,15 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "Middleware",
"metadata": {
"name": "devicemgmt-agent-strip-forwarded-cert",
"namespace": "fc-devicemgmt"
},
"spec": {
"headers": {
"customRequestHeaders": {
"X-Forwarded-Tls-Client-Cert": ""
}
}
}
}

View File

@@ -0,0 +1,13 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "TLSOption",
"metadata": {
"name": "devicemgmt-agent-mtls",
"namespace": "fc-devicemgmt"
},
"spec": {
"clientAuth": {
"clientAuthType": "RequireAnyClientCert"
}
}
}