Security Best Practices Guide
This guide covers security best practices for deploying and operating Wanaku in production environments.
Secret Management
Kubernetes Secrets
Store all sensitive configuration in Kubernetes Secrets rather than ConfigMaps or plain YAML.
Example: OIDC Credentials Secret
apiVersion: v1
kind: Secret
metadata:
name: wanaku-oidc-credentials
namespace: wanaku-system
type: Opaque
stringData:
client-id: "wanaku-service"
client-secret: "<rotate-me-regularly>"
auth-server-url: "https://keycloak.example.com/realms/production"Best Practices:
- Never commit secrets to version control
- Use
stringDatafor plaintext values (auto-encoded to base64) - Restrict secret access with RBAC:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader
namespace: wanaku-system
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
resourceNames: ["wanaku-oidc-credentials"]- Rotate credentials quarterly at a minimum
- Consider external secret managers (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault) for production
Environment Variables
Inject secrets as environment variables in deployment manifests:
env:
- name: CLIENT_ID
valueFrom:
secretKeyRef:
name: wanaku-oidc-credentials
key: client-id
- name: CLIENT_SECRET
valueFrom:
secretKeyRef:
name: wanaku-oidc-credentials
key: client-secretWanaku CLI Credentials
When using wanaku CLI commands that require admin access, prefer environment variables for credentials:
export WANAKU_ADMIN_USERNAME=admin
export WANAKU_ADMIN_PASSWORD=secure-password
wanaku-keycloak-admin realm create --config wanaku-config.jsonNetwork Policies
Default Deny Ingress
Apply a default deny policy to downstream MCP server namespaces:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: wanaku-capabilities
spec:
podSelector: {}
policyTypes:
- IngressAllow Router-to-MCP-Server Communication
Allow traffic from the router namespace to downstream MCP servers:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-router-capability
namespace: wanaku-capabilities
spec:
podSelector:
matchLabels:
app: camel-capability
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: wanaku-system
ports:
- protocol: TCP
port: 9190Allow MCP Server-to-Router Registration
Allow downstream MCP servers to register with the router (port 8080):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-capability-registration
namespace: wanaku-system
spec:
podSelector:
matchLabels:
app: wanaku-router
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: wanaku-capabilities
ports:
- protocol: TCP
port: 8080Keycloak Access
Restrict Keycloak access to the router namespace only:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-router-keycloak
namespace: wanaku-system
spec:
podSelector:
matchLabels:
app: keycloak
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: wanaku-system
ports:
- protocol: TCP
port: 8080Least-Privilege Principles for Downstream MCP Servers
Service Account per MCP Server
Create dedicated service accounts for each downstream MCP server:
apiVersion: v1
kind: ServiceAccount
metadata:
name: camel-integration-capability
namespace: wanaku-capabilities
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: camel-capability-role
namespace: wanaku-capabilities
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: ["wanaku.ai"]
resources: ["wanakurouters", "wanakucapabilities"]
verbs: ["get", "list", "watch", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: camel-capability-binding
namespace: wanaku-capabilities
subjects:
- kind: ServiceAccount
name: camel-integration-capability
namespace: wanaku-capabilities
roleRef:
kind: Role
name: camel-capability-role
apiGroup: rbac.authorization.k8s.ioKeycloak Client Roles
Assign minimal roles in Keycloak for each downstream MCP server:
- Create dedicated client per MCP server (e.g.,
camel-integration-capability-prod) - Enable Service Accounts and Client Authentication
- Assign only required roles:
wanaku-servicerole for registration- Specific resource roles as needed
- Avoid realm-admin or broad roles
Container Security Context
Run MCP servers with non-root user and read-only filesystem:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
fsGroup: 10001
containers:
- name: camel-capability
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALLResource Limits
Prevent resource exhaustion attacks:
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"Audit Considerations
Enable Audit Logging
Configure Keycloak audit logging for authentication events.
For Quarkus-based Keycloak (v17+), use environment variables in your deployment:
KC_SPI_EVENTS_LISTENER_JBOSS_LOGGING_SUCCESS_EVENTS=LOGIN,REGISTER,TOKEN_REFRESH
KC_SPI_EVENTS_LISTENER_JBOSS_LOGGING_ERROR_EVENTS=LOGIN_ERROR,TOKEN_REFRESH_ERRORThe exact configuration depends on your Keycloak deployment method. Check the Keycloak documentation for your version.
Wanaku Router Audit
The router logs all management API operations. Configure log level in application.properties:
quarkus.log.category."ai.wanaku".level=INFO
quarkus.log.category."ai.wanaku.router".level=DEBUGKey events logged:
- Tool/resource registration and deletion
- Namespace creation/modification
- MCP server registration/deregistration
- Authentication successes and failures
Access Logs
Enable the HTTP access log in downstream MCP servers to track tool invocations:
# In MCP server application.properties
quarkus.http.access-log.enabled=true
quarkus.http.access-log.pattern=combinedKubernetes Audit Policy
Deploy Kubernetes audit policy to track all Wanaku CR operations:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
resources:
- group: "wanaku.ai"
resources: ["wanakurouters", "wanakucapabilities", "wanakuservicecatalogs"]
- level: RequestResponse
resources:
- group: ""
resources: ["secrets"]
resourceNames: ["wanaku-oidc-credentials"]Log Retention
- Retain audit logs for minimum 90 days
- Ship logs to centralized logging (ELK, Loki, Splunk)
- Set up alerts for:
- Failed authentication attempts > 5/minute
- Unauthorized secret access
- New MCP server registrations
- Tool/resource modifications outside change windows
TLS/mTLS Configuration
Router TLS
IMPORTANT
TLS configuration via the WanakuRouter CRD (tls.enabled, tls.secretName) is planned for a future release but is not yet available. For now, configure TLS at the Ingress (Kubernetes) or Route (OpenShift) level that fronts the Wanaku Router.
Example OpenShift Route with TLS:
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: wanaku-router
spec:
host: wanaku.example.com
to:
kind: Service
name: wanaku-router
tls:
termination: edge
insecureEdgeTerminationPolicy: RedirectmTLS (Future)
For enhanced security, plan for mTLS:
- Use cert-manager for certificate issuance
- Configure mutual TLS for service communication
- Validate peer certificates in downstream MCP servers
Compliance Checklist
| Control | Implementation | Verification |
|---|---|---|
| Encryption at rest | Infinispan encryption + PV encryption | Check PV encryption class |
| Encryption in transit | TLS 1.2+ for all endpoints | curl -v https://router |
| Secret management | K8s Secrets + external vault | Audit secret access logs |
| Authentication | OIDC with Keycloak | Verify token validation |
| Authorization | Namespace isolation + RBAC | Test cross-namespace access |
| Audit logging | Keycloak + router + K8s audit | Review log samples |
| Network segmentation | NetworkPolicies per namespace | kubectl exec connectivity tests |
| Vulnerability scanning | Image scanning in CI/CD | Check scan reports |
| Incident response | Runbook for credential rotation | Tabletop exercise |
If you find a bug, please report it. To get in touch with the community, visit the Wanaku project.