Security
Defense-in-depth approach covering transport encryption, key management, secrets handling, authentication, and network isolation.
Table of contents
Transport Security
TLS for External Traffic
All client-facing endpoints are secured with TLS certificates:
- Automated provisioning via cert-manager with Let’s Encrypt ACME
- DNS validation through Cloudflare for domain ownership verification
- Automatic renewal — certificates are renewed before expiry with zero downtime
- Per-client certificates — each client namespace has its own TLS certificate, not shared across tenants
Mutual TLS (mTLS) for Internal Traffic
All pod-to-pod communication within the cluster is encrypted and authenticated through Istio service mesh:
- Every service gets a cryptographic identity (SPIFFE certificate)
- Traffic between pods is automatically encrypted — no application-level changes needed
- Identity-based authentication ensures only authorized services can communicate
graph LR
subgraph cluster["Kubernetes Cluster"]
A[Validator Pod] <-->|mTLS| B[Participant Pod]
B <-->|mTLS| C[PostgreSQL Pod]
A <-->|mTLS| C
end
Client[External Client] -->|TLS| LB[Load Balancer]
LB -->|TLS| A
Cryptographic Key Management
Canton nodes require cryptographic keys for signing transactions and establishing identity on the network. These keys are managed through Google Cloud KMS:
- Hardware-backed storage — keys are stored in FIPS 140-2 validated hardware security modules
- Keys never leave the KMS boundary — signing operations happen within KMS, private key material is never exposed
- Per-client key rings — each client has a dedicated KMS key ring with isolated access controls
- GCP Workload Identity — Kubernetes pods authenticate to KMS without static credentials, using GCP’s identity federation
Secrets Management
No secrets are ever stored in Git. All sensitive configuration is managed through a dedicated secrets pipeline:
graph LR
GSM[GCP Secret Manager] -->|sync| ESO[External Secrets<br/>Operator]
ESO -->|inject| K8S[Kubernetes Secrets]
K8S -->|mount| Pods[Application Pods]
- GCP Secret Manager — centralized secrets store with audit logging and access controls
- External Secrets Operator (ESO) — automatically syncs secrets from GCP into Kubernetes
- Per-client secret stores — each client namespace has its own
SecretStoreresource backed by a dedicated GCP service account - Automatic rotation — when a secret is updated in GCP Secret Manager, ESO propagates the change to the cluster
What’s Protected
| Secret | Storage |
|---|---|
| Database credentials | GCP Secret Manager → Kubernetes Secret |
| OIDC client secrets | GCP Secret Manager → Kubernetes Secret |
| Onboarding tokens | GCP Secret Manager → Kubernetes Secret |
| Canton node signing keys | GCP Cloud KMS (never extracted) |
| TLS private keys | cert-manager managed (in-cluster only) |
Authentication and Authorization
Identity Provider
Keycloak serves as the centralized OIDC identity provider:
- Per-client realm — each client gets an isolated authentication realm with its own users, roles, and credentials
- Separate OAuth clients — distinct credentials for each application component:
- Validator backend
- Wallet Web UI
- CNS (Canton Name Service) UI
- Data applications
- Standard protocols — OpenID Connect and OAuth 2.0 for all authentication flows
- Token management — configurable token lifetimes and refresh policies
Kubernetes RBAC
Access within the cluster is controlled through Kubernetes role-based access control:
- Per-namespace service accounts — each client’s workloads run under dedicated service accounts
- Scoped permissions — service accounts have only the permissions needed for their specific function
- GCP Workload Identity binding — Kubernetes service accounts are mapped to GCP service accounts for cloud resource access
Network Security
Namespace Isolation
Kubernetes namespaces provide the first layer of tenant isolation:
- Each client operates in a dedicated namespace
- Resources (pods, services, secrets, configmaps) are namespace-scoped and invisible to other tenants
- Network policies restrict cross-namespace communication
Istio Authorization Policies
Fine-grained network access control through Istio:
- IP whitelisting — sensitive endpoints (e.g., metrics) are restricted to specific IP addresses
- Service-to-service rules — authorization policies define which services can communicate
- Deny-by-default — traffic not explicitly allowed is blocked
Ingress Architecture
External and internal traffic is separated:
- External Ingress — public-facing load balancer for client API access
- Internal Ingress — separate controller for platform-internal communication
- Per-client routing — Istio VirtualServices route traffic to the correct namespace based on hostname
Security Summary
| Layer | Technology | What it Protects |
|---|---|---|
| Transport (external) | TLS / cert-manager / Let’s Encrypt | Client ↔ Platform communication |
| Transport (internal) | Istio mTLS | Pod ↔ Pod communication |
| Key Management | GCP Cloud KMS | Canton node signing keys |
| Secrets | GCP Secret Manager + ESO | Credentials and tokens |
| Authentication | Keycloak OIDC | User and service identity |
| Authorization | Kubernetes RBAC + Istio policies | Resource and network access |
| Isolation | Kubernetes namespaces | Tenant separation |
| Audit | Git history + GCP audit logs | Change tracking |