Skip to main content

Security Hardening

Production security checklist and hardening guide for STOA Platform.

Security Layers​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Network (TLS, NetworkPolicy, firewall) β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Identity (Keycloak, OIDC, mTLS) β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Application (RBAC, quotas, SSRF block) β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Container (PSS, seccomp, read-only FS) β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Data (encryption at rest, audit trail) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

TLS Configuration​

Ingress TLS​

All external endpoints must use TLS 1.2+:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: stoa-gateway
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-protocols: "TLSv1.2 TLSv1.3"
spec:
tls:
- secretName: gateway-tls
hosts:
- mcp.<YOUR_DOMAIN>

Internal TLS​

For service-to-service encryption within the cluster, enable mTLS via the gateway. See mTLS Configuration.

Network Policies​

Tenant Isolation​

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: tenant-isolation
namespace: stoa-system
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: stoa-system
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: TCP
port: 53
- protocol: UDP
port: 53
- to:
- podSelector: {}

Gateway Egress Restriction​

Limit gateway outbound connections to known backends:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: gateway-egress
namespace: stoa-system
spec:
podSelector:
matchLabels:
app: stoa-gateway
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: control-plane-api
ports:
- port: 8000
- to:
- namespaceSelector: {}
ports:
- port: 443 # HTTPS backends
- port: 53 # DNS
protocol: UDP

Container Security​

Pod Security Standards​

Apply the restricted Pod Security Standard:

apiVersion: v1
kind: Namespace
metadata:
name: stoa-system
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted

Security Context (All Containers)​

securityContext:
privileged: false
runAsNonRoot: true
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true # Not for nginx containers
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault

SSRF Protection​

The STOA Gateway includes a built-in SSRF blocklist that rejects backend URLs pointing to:

  • Loopback addresses (127.0.0.0/8, ::1)
  • Private networks (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
  • Link-local (169.254.0.0/16 β€” AWS metadata)
  • IPv6 unique-local (fd00::/8)

This is defense-in-depth: backend URLs come from admin-configured data, but a compromised Control Plane could inject internal targets.

Security Headers​

The gateway automatically adds these headers to every response:

HeaderValuePurpose
X-Content-Type-OptionsnosniffPrevent MIME sniffing
X-Frame-OptionsDENYPrevent clickjacking
X-XSS-Protection0Disable legacy XSS filter
Referrer-Policystrict-origin-when-cross-originControl referrer leakage
Permissions-Policycamera=(), microphone=(), geolocation=()Restrict browser APIs

Secrets Management​

Infisical (self-hosted) β†’ K8s Secrets β†’ Pod env vars
  • Never hardcode secrets in code, Helm values, or ConfigMaps
  • Use secretRef in pod specs to reference K8s Secrets
  • Rotate secrets via Infisical; pods pick up changes on restart

See Secrets Management for detailed configuration.

Secret Rotation Checklist​

SecretRotation FrequencyMethod
Database password90 daysInfisical + pod restart
Keycloak client secrets90 daysKeycloak Admin + config update
Gateway admin token90 daysK8s Secret + pod restart
TLS certificatesAuto (cert-manager)cert-manager handles renewal
API keysOn demandConsumer-initiated via API

Compliance Alignment​

DORA (Digital Operational Resilience Act)​

DORA RequirementSTOA Capability
ICT risk managementRBAC, audit trail, monitoring
Incident reportingAlertmanager + audit logs
Operational resilience testingGateway Arena benchmarks
Third-party riskMulti-gateway adapter pattern
Information sharingOpenSearch audit trail

NIS2 (Network and Information Security)​

NIS2 RequirementSTOA Capability
Risk analysisSecurity headers, SSRF blocklist
Incident handlingPrometheus alerts, audit trail
Supply chain securitySBOM generation (CI), signed commits
EncryptionTLS 1.2+, mTLS support
Access controlKeycloak RBAC, 4 roles

STOA Platform provides technical capabilities that support regulatory compliance efforts. This does not constitute legal advice or a guarantee of compliance. Organizations should consult qualified legal counsel for compliance requirements.

Production Hardening Checklist​

  • TLS on all ingress endpoints
  • NetworkPolicy applied to stoa-system namespace
  • Pod Security Standard set to restricted
  • Keycloak brute force protection enabled
  • Token lifespans shortened (5min access, 15min idle)
  • SSRF blocklist active (default)
  • Security headers active (default)
  • Secrets in Infisical/Vault (not in env or ConfigMap)
  • RBAC roles assigned (no default admin access)
  • Audit trail enabled (OpenSearch)
  • Alerting configured (Alertmanager)
  • Container images scanned (Trivy in CI)
  • Signed commits enforced