Online Boutique Microservices Demo
This example deploys a microservices e-commerce application (based on Google’s Online Boutique) secured end-to-end with Riptides. Every service receives a SPIFFE identity, and all inter-service communication is encrypted with transparent mTLS — no application code changes required.
Architecture
Section titled “Architecture”The application consists of five core services:
┌──────────┐ ┌─────────┤ frontend ├──────────┐ │ └────┬─────┘ │ │ │ │ v v v ┌─────────────┐ ┌───────────┐ ┌─────────────┐ │ product- │ │ cart │ │ checkout │ │ catalog │ │ service │ │ service │ └─────────────┘ └─────┬─────┘ └──┬──┬──┬────┘ │ │ │ │ v │ │ │ ┌───────────┐ │ │ │ │ redis │ │ │ │ └───────────┘ │ │ │ ┌──────────────────────────┘ │ └────────┐ v v v ┌─────────────┐ ┌──────────────┐ ┌─────────┐ │ product- │ │ payment │ │ email │ │ catalog │ │ service │ │ service │ └─────────────┘ └──────────────┘ └─────────┘Communication paths:
| Source | Destination | Protocol | Port |
|---|---|---|---|
| frontend | product-catalog | gRPC | 3550 |
| frontend | cart | gRPC | 7070 |
| frontend | checkout | gRPC | 5050 |
| checkout | product-catalog | gRPC | 3550 |
| checkout | cart | gRPC | 7070 |
| checkout | payment | gRPC | 50051 |
| checkout | gRPC | 5000 | |
| cart | redis | TCP | 6379 |
All connections are transparently encrypted with mTLS by the Riptides kernel module. The frontend uses PERMISSIVE TLS mode so it can accept plaintext traffic from external load balancers, while backend services enforce MUTUAL TLS for all inbound connections.
Resources
Section titled “Resources”WorkloadIdentities
Section titled “WorkloadIdentities”Each service gets a unique SPIFFE identity. The allowedSPIFFEIDs fields define which services can communicate, creating a cryptographic service graph.
frontend
Section titled “frontend”The frontend accepts traffic from external sources and calls multiple backend services.
apiVersion: core.riptides.io/v1alpha1kind: WorkloadIdentitymetadata: name: frontend namespace: riptides-systemspec: workloadID: online-boutique/app/frontend scope: daemonGroup: id: riptides/daemongroup/dev-eu-west-1/on-demand-workers selectors: - k8s:label:app: frontend k8s:pod:namespace: online-boutique process:name: frontend connection: tls: mode: PERMISSIVE allowedSPIFFEIDs: outbound: - spiffe://example.com/online-boutique/app/product-catalog - spiffe://example.com/online-boutique/app/cart - spiffe://example.com/online-boutique/app/checkoutKey points:
PERMISSIVETLS mode accepts both plaintext and mTLS connections, allowing ingress from load balancers that do not present a client certificate.outboundallowedSPIFFEIDs list the identities this workload is permitted to connect to.- The
selectorscombine Kubernetes metadata (label, namespace) with process-level attestation (process:name) for defense in depth.
product-catalog
Section titled “product-catalog”apiVersion: core.riptides.io/v1alpha1kind: WorkloadIdentitymetadata: name: product-catalog namespace: riptides-systemspec: workloadID: online-boutique/app/product-catalog scope: daemonGroup: id: riptides/daemongroup/dev-eu-west-1/on-demand-workers selectors: - k8s:label:app: productcatalogservice k8s:pod:namespace: online-boutique process:name: productcatalogservice connection: tls: mode: MUTUAL allowedSPIFFEIDs: inbound: - spiffe://example.com/online-boutique/app/frontend - spiffe://example.com/online-boutique/app/checkoutKey points:
MUTUALTLS mode requires all clients to present a valid SPIFFE identity. Unauthenticated connections are rejected at the kernel level.- Only
frontendandcheckoutare allowed to call this service.
apiVersion: core.riptides.io/v1alpha1kind: WorkloadIdentitymetadata: name: cart namespace: riptides-systemspec: workloadID: online-boutique/app/cart scope: daemonGroup: id: riptides/daemongroup/dev-eu-west-1/on-demand-workers selectors: - k8s:label:app: cartservice k8s:pod:namespace: online-boutique process:name: cartservice connection: tls: mode: MUTUAL allowedSPIFFEIDs: inbound: - spiffe://example.com/online-boutique/app/frontend - spiffe://example.com/online-boutique/app/checkout outbound: - spiffe://example.com/online-boutique/app/redischeckout
Section titled “checkout”The checkout service orchestrates the purchase flow, calling multiple downstream services.
apiVersion: core.riptides.io/v1alpha1kind: WorkloadIdentitymetadata: name: checkout namespace: riptides-systemspec: workloadID: online-boutique/app/checkout scope: daemonGroup: id: riptides/daemongroup/dev-eu-west-1/on-demand-workers selectors: - k8s:label:app: checkoutservice k8s:pod:namespace: online-boutique process:name: checkoutservice connection: tls: mode: MUTUAL allowedSPIFFEIDs: inbound: - spiffe://example.com/online-boutique/app/frontend outbound: - spiffe://example.com/online-boutique/app/product-catalog - spiffe://example.com/online-boutique/app/cart - spiffe://example.com/online-boutique/app/payment - spiffe://example.com/online-boutique/app/emailpayment
Section titled “payment”apiVersion: core.riptides.io/v1alpha1kind: WorkloadIdentitymetadata: name: payment namespace: riptides-systemspec: workloadID: online-boutique/app/payment scope: daemonGroup: id: riptides/daemongroup/dev-eu-west-1/on-demand-workers selectors: - k8s:label:app: paymentservice k8s:pod:namespace: online-boutique process:name: node connection: tls: mode: MUTUAL allowedSPIFFEIDs: inbound: - spiffe://example.com/online-boutique/app/checkoutapiVersion: core.riptides.io/v1alpha1kind: WorkloadIdentitymetadata: name: email namespace: riptides-systemspec: workloadID: online-boutique/app/email scope: daemonGroup: id: riptides/daemongroup/dev-eu-west-1/on-demand-workers selectors: - k8s:label:app: emailservice k8s:pod:namespace: online-boutique process:name: python connection: tls: mode: MUTUAL allowedSPIFFEIDs: inbound: - spiffe://example.com/online-boutique/app/checkoutapiVersion: core.riptides.io/v1alpha1kind: WorkloadIdentitymetadata: name: redis namespace: riptides-systemspec: workloadID: online-boutique/app/redis scope: daemonGroup: id: riptides/daemongroup/dev-eu-west-1/on-demand-workers selectors: - k8s:label:app: redis-cart k8s:pod:namespace: online-boutique process:name: redis-server connection: tls: mode: MUTUAL allowedSPIFFEIDs: inbound: - spiffe://example.com/online-boutique/app/cartServices
Section titled “Services”Service resources tell Riptides where each workload listens, and provide labels used by egress rules.
apiVersion: core.riptides.io/v1alpha1kind: Servicemetadata: name: online-boutique-frontend namespace: riptides-systemspec: addresses: - address: frontend.online-boutique.svc.cluster.local port: 80 labels: app: online-boutique service: frontend---apiVersion: core.riptides.io/v1alpha1kind: Servicemetadata: name: online-boutique-product-catalog namespace: riptides-systemspec: addresses: - address: productcatalogservice.online-boutique.svc.cluster.local port: 3550 labels: app: online-boutique service: productcatalogservice---apiVersion: core.riptides.io/v1alpha1kind: Servicemetadata: name: online-boutique-cart namespace: riptides-systemspec: addresses: - address: cartservice.online-boutique.svc.cluster.local port: 7070 labels: app: online-boutique service: cartservice---apiVersion: core.riptides.io/v1alpha1kind: Servicemetadata: name: online-boutique-checkout namespace: riptides-systemspec: addresses: - address: checkoutservice.online-boutique.svc.cluster.local port: 5050 labels: app: online-boutique service: checkoutservice---apiVersion: core.riptides.io/v1alpha1kind: Servicemetadata: name: online-boutique-payment namespace: riptides-systemspec: addresses: - address: paymentservice.online-boutique.svc.cluster.local port: 50051 labels: app: online-boutique service: paymentservice---apiVersion: core.riptides.io/v1alpha1kind: Servicemetadata: name: online-boutique-email namespace: riptides-systemspec: addresses: - address: emailservice.online-boutique.svc.cluster.local port: 5000 labels: app: online-boutique service: emailservice---apiVersion: core.riptides.io/v1alpha1kind: Servicemetadata: name: online-boutique-redis namespace: riptides-systemspec: addresses: - address: redis-cart.online-boutique.svc.cluster.local port: 6379 labels: app: online-boutique service: redis-cartHow it works
Section titled “How it works”Once these resources are applied, the Riptides control plane distributes them to daemons running on each node.
-
Attests each workload — The daemon uses the configured selectors (Kubernetes labels, namespace, and process name) to match running processes. Only processes matching all selector criteria receive a SPIFFE identity.
-
Issues X.509 certificates — The control plane issues short-lived SVIDs (SPIFFE Verifiable Identity Documents) for attested workloads and rotates them before expiry.
-
Encrypts connections transparently — When the frontend opens a TCP connection to the cart service on port 7070, the kernel module intercepts the socket, performs a mutual TLS handshake, and validates both identities against the
allowedSPIFFEIDspolicy — all without any changes to application code. -
Blocks unauthorized traffic — If an attacker compromises the email service and attempts to connect to the payment service, the connection is denied because
spiffe://example.com/online-boutique/app/emailis not in the payment service’sallowedSPIFFEIDs.inboundlist.
Deploying this example
Section titled “Deploying this example”# Apply all Riptides resourcesriptides-cli ctl apply -f workload-identities.yamlriptides-cli ctl apply -f services.yaml
# Deploy the application (standard Kubernetes manifests, no sidecars needed)kubectl apply -f online-boutique/kubernetes-manifests.yamlNo application changes, no sidecar containers, no service annotations. The kernel module handles identity and encryption at the socket level.
Next steps
Section titled “Next steps”- Workload Identity concepts — how SPIFFE IDs and selectors work
- Transparent mTLS guide — detailed walkthrough of TLS modes
- Workload attestation — how the kernel module identifies processes