Files
bridge/k8s/mpc-security.yaml
zeekayandHanzo Dev e7d3548f74 fix(mpc): point the keygen path at :9800 — the only port mpcd opens
Every bridge swap creation has failed since the MPC StatefulSet was cut over,
with `dial tcp <mpc-api-svc>:8081: i/o timeout`, so no deposit address was ever
minted and /health showed 229,398 broadcast ticks with 0 attempts and 0
successes. Two independent misconfigurations, each fatal on its own:

1. mpc-api-svc mapped 8081 -> targetPort 8080, but the StatefulSet launches
   `mpcd start --listen :9651 --api :9800`. `netstat -ltn` inside mpc-node-0
   lists 7301/9800/9653/9651 — nothing has ever bound 8080. The StatefulSet
   declares no readinessProbe, so all three pods were published as ready
   endpoints on the dead port and the Service read as healthy.

2. mpc-node-ingress admitted only app=bridge-server on 8080/8081. The Go
   backend that serves bridge.lux.network is app=lux-bridge, and the real API
   port 9800 was on no allow-list at all, so the packets were dropped rather
   than rejected — hence a hang instead of a connection error.

Verified against the live cluster: mpc-api-svc:8081/keygen now answers instead
of hanging, and POST /api/swaps advances from 502 `i/o timeout` to 401
`unauthorized`. Auth is a separate, still-open blocker: mpcd's validateJWT
requires iss=mpc.lux.network and aud containing mpc-api, and derives its HS256
key from --jwt-secret / MPC_JWT_SECRET (neither is set on the StatefulSet),
while bridge-mpc-token/MPC_API_TOKEN carries only user_id/org_id/role/iat/exp.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 19:45:34 -07:00

101 lines
2.8 KiB
YAML

# MPC Network Security Policy
# Namespace: lux-bridge
#
# Threat model:
# - MPC nodes hold key shares; lateral movement from any other pod must be blocked
# - Only the bridge-server may call the MPC HTTP/dashboard APIs
# - MPC nodes must reach each other for ZAP p2p consensus on port 9651
# - Egress is unrestricted (nodes need S3, postgres, external peers)
#
# Ports:
# 9651 - ZAP p2p consensus (mpc-node ↔ mpc-node only)
# 9800 - mpcd HTTP API (bridge callers → mpc-node). This is the ONLY API port
# mpcd actually opens: the StatefulSet launches `mpcd start --api :9800`.
# 8080/8081 are kept only because mpc-api-svc still publishes 8081 as its
# service port; nothing has ever listened on 8080 inside the pod.
#
# Both bridge backends call keygen, so both must be admitted:
# app=bridge-server - the TypeScript server (bridge-api.lux.network)
# app=lux-bridge - the Go server (bridge.lux.network)
# Omitting lux-bridge silently BLACKHOLED every keygen (packets dropped, not
# rejected) so createSwap failed with `i/o timeout` and no deposit address could
# ever be minted — the reason /health showed 229k broadcast ticks and 0 attempts.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: mpc-node-ingress
namespace: lux-bridge
spec:
podSelector:
matchLabels:
app: mpc-node
policyTypes:
- Ingress
ingress:
# bridge backends → mpc-node: mpcd HTTP API
- from:
- podSelector:
matchLabels:
app: bridge-server
- podSelector:
matchLabels:
app: lux-bridge
ports:
- protocol: TCP
port: 9800
- protocol: TCP
port: 8080
- protocol: TCP
port: 8081
# mpc-node ↔ mpc-node: ZAP p2p consensus
- from:
- podSelector:
matchLabels:
app: mpc-node
ports:
- protocol: TCP
port: 9651
---
# Egress: unrestricted — nodes must reach S3, postgres, and external MPC peers
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: mpc-node-egress
namespace: lux-bridge
spec:
podSelector:
matchLabels:
app: mpc-node
policyTypes:
- Egress
egress:
- {}
---
# Ingress: api.mpc.lux.network → mpc-api-svc:8081
# API key auth is enforced by mpcd itself. TLS via cert-manager.
# DNS: add A record api.mpc.lux.network → ingress controller IP.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mpc-api-ingress
namespace: lux-bridge
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: ingress
tls:
- hosts:
- api.mpc.lux.network
secretName: mpc-api-lux-tls
rules:
- host: api.mpc.lux.network
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: mpc-api-svc
port:
number: 8081