Skip to content

Security Configuration

This guide provides comprehensive security configuration for Temporal.io enterprise deployment, covering network security, authentication, authorization, encryption, and compliance requirements.

Overview

Security configuration includes: - Network policies and segmentation - TLS/SSL certificate management - Authentication and authorization - Secrets management - RBAC configuration - Audit logging and compliance - Security scanning and vulnerability management

Network Security

Network Policies

Default Deny Policy

# k8s/security/network-policies/default-deny.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: temporal-system
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

Temporal Backend Network Policy

# k8s/security/network-policies/temporal-backend.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: temporal-backend-policy
  namespace: temporal-system
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: temporal
  policyTypes:
  - Ingress
  - Egress
  ingress:
  # Allow ingress from workers and API services
  - from:
    - namespaceSelector:
        matchLabels:
          name: temporal-app
    - podSelector:
        matchLabels:
          app.kubernetes.io/component: web
    ports:
    - protocol: TCP
      port: 7233  # Frontend service
    - protocol: TCP
      port: 7234  # History service
    - protocol: TCP
      port: 7235  # Matching service
  # Allow ingress from load balancer
  - from:
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:
    - protocol: TCP
      port: 8080  # Web UI
  egress:
  # Allow egress to database
  - to: []
    ports:
    - protocol: TCP
      port: 5432  # PostgreSQL
  # Allow egress to Redis
  - to: []
    ports:
    - protocol: TCP
      port: 6379  # Redis
  # Allow DNS resolution
  - to: []
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53
  # Allow HTTPS for external services
  - to: []
    ports:
    - protocol: TCP
      port: 443

Application Network Policy

# k8s/security/network-policies/temporal-app.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: temporal-app-policy
  namespace: temporal-app
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/part-of: temporal-app
  policyTypes:
  - Ingress
  - Egress
  ingress:
  # Allow ingress from load balancer
  - from:
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:
    - protocol: TCP
      port: 8000  # FastAPI
  egress:
  # Allow egress to Temporal backend
  - to:
    - namespaceSelector:
        matchLabels:
          name: temporal-system
    ports:
    - protocol: TCP
      port: 7233
  # Allow egress to Redis
  - to: []
    ports:
    - protocol: TCP
      port: 6379
  # Allow DNS resolution
  - to: []
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53
  # Allow HTTPS for external APIs
  - to: []
    ports:
    - protocol: TCP
      port: 443

Security Groups (AWS)

Database Security Group

# terraform/modules/security-groups/rds.tf
resource "aws_security_group" "rds" {
  name_prefix = "${var.cluster_name}-rds-"
  vpc_id      = var.vpc_id
  description = "Security group for RDS database"

  # Allow connections from EKS nodes only
  ingress {
    description     = "PostgreSQL from EKS"
    from_port       = 5432
    to_port         = 5432
    protocol        = "tcp"
    security_groups = [aws_security_group.eks_nodes.id]
  }

  # Allow connections from bastion host for administration
  ingress {
    description     = "PostgreSQL from bastion"
    from_port       = 5432
    to_port         = 5432
    protocol        = "tcp"
    security_groups = [aws_security_group.bastion.id]
  }

  egress {
    description = "All outbound traffic"
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name        = "${var.cluster_name}-rds-sg"
    Environment = var.environment
  }
}

EKS Nodes Security Group

# terraform/modules/security-groups/eks.tf
resource "aws_security_group" "eks_nodes" {
  name_prefix = "${var.cluster_name}-eks-nodes-"
  vpc_id      = var.vpc_id
  description = "Security group for EKS worker nodes"

  # Allow nodes to communicate with each other
  ingress {
    description = "Node to node communication"
    from_port   = 0
    to_port     = 65535
    protocol    = "tcp"
    self        = true
  }

  # Allow pods to communicate with the cluster API Server
  ingress {
    description     = "Cluster API Server"
    from_port       = 443
    to_port         = 443
    protocol        = "tcp"
    security_groups = [aws_security_group.eks_cluster.id]
  }

  # Allow NodePort services
  ingress {
    description = "NodePort services"
    from_port   = 30000
    to_port     = 32767
    protocol    = "tcp"
    cidr_blocks = [var.vpc_cidr]
  }

  egress {
    description = "All outbound traffic"
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name        = "${var.cluster_name}-eks-nodes-sg"
    Environment = var.environment
  }
}

TLS/SSL Configuration

Certificate Manager Setup

ClusterIssuer for Let's Encrypt

# k8s/security/certificates/cluster-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: admin@yourcompany.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - dns01:
        route53:
          region: us-west-2
          accessKeyID: AKIAIOSFODNN7EXAMPLE
          secretAccessKeySecretRef:
            name: route53-credentials
            key: secret-access-key
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    email: admin@yourcompany.com
    privateKeySecretRef:
      name: letsencrypt-staging
    solvers:
    - dns01:
        route53:
          region: us-west-2
          accessKeyID: AKIAIOSFODNN7EXAMPLE
          secretAccessKeySecretRef:
            name: route53-credentials
            key: secret-access-key

Certificate for Temporal Services

# k8s/security/certificates/temporal-cert.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: temporal-tls
  namespace: temporal-system
spec:
  secretName: temporal-tls-secret
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  commonName: temporal.yourcompany.com
  dnsNames:
  - temporal.yourcompany.com
  - temporal-web.yourcompany.com
  - temporal-frontend.temporal-system.svc.cluster.local
  usages:
  - digital signature
  - key encipherment
  - server auth
  - client auth

TLS Configuration for Temporal

Temporal TLS Configuration

# helm/values/security/tls.yaml
server:
  config:
    tls:
      frontend:
        server:
          certFile: /etc/temporal/certs/tls.crt
          keyFile: /etc/temporal/certs/tls.key
          clientCAFile: /etc/temporal/certs/ca.crt
          requireClientAuth: true
        client:
          serverName: temporal-frontend
          certFile: /etc/temporal/certs/tls.crt
          keyFile: /etc/temporal/certs/tls.key
          caFile: /etc/temporal/certs/ca.crt
      history:
        server:
          certFile: /etc/temporal/certs/tls.crt
          keyFile: /etc/temporal/certs/tls.key
          clientCAFile: /etc/temporal/certs/ca.crt
          requireClientAuth: true
        client:
          serverName: temporal-history
          certFile: /etc/temporal/certs/tls.crt
          keyFile: /etc/temporal/certs/tls.key
          caFile: /etc/temporal/certs/ca.crt
      matching:
        server:
          certFile: /etc/temporal/certs/tls.crt
          keyFile: /etc/temporal/certs/tls.key
          clientCAFile: /etc/temporal/certs/ca.crt
          requireClientAuth: true
        client:
          serverName: temporal-matching
          certFile: /etc/temporal/certs/tls.crt
          keyFile: /etc/temporal/certs/tls.key
          caFile: /etc/temporal/certs/ca.crt

Authentication and Authorization

OIDC Integration

OIDC Configuration for Temporal Web

# k8s/security/auth/oidc-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: temporal-web-auth-config
  namespace: temporal-system
data:
  config.yaml: |
    auth:
      enabled: true
      providers:
        - label: "Company SSO"
          type: oidc
          providerUrl: "https://auth.yourcompany.com"
          clientId: "temporal-web"
          clientSecret: "${OIDC_CLIENT_SECRET}"
          scopes:
            - openid
            - profile
            - email
          callbackUrl: "https://temporal.yourcompany.com/auth/callback"
          usernameAttribute: "email"
          groupsAttribute: "groups"
      authorizer:
        roleMapping:
          admin:
            - "temporal-admins"
          read:
            - "temporal-readers"
          write:
            - "temporal-writers"

External Secret for OIDC

# k8s/security/auth/oidc-secret.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: temporal-oidc-secret
  namespace: temporal-system
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  target:
    name: temporal-oidc-secret
    creationPolicy: Owner
  data:
  - secretKey: client-secret
    remoteRef:
      key: temporal/oidc
      property: client_secret

JWT Configuration

JWT Authorizer Configuration

# k8s/security/auth/jwt-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: temporal-auth-config
  namespace: temporal-system
data:
  auth.yaml: |
    authorization:
      jwtKeyProvider:
        keySourceURIs:
          - "https://auth.yourcompany.com/.well-known/jwks.json"
        refreshInterval: "1h"
      permissionsClaimName: "permissions"

    claims:
      mappers:
        - name: "admin"
          role: "admin"
          permissions:
            - "system:admin"
            - "namespace:admin"
            - "workflow:admin"
        - name: "developer"
          role: "developer"
          permissions:
            - "namespace:read"
            - "namespace:write"
            - "workflow:read"
            - "workflow:write"
        - name: "readonly"
          role: "readonly"
          permissions:
            - "namespace:read"
            - "workflow:read"

RBAC Configuration

Kubernetes RBAC for Temporal

# k8s/security/rbac/temporal-rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: temporal-admin
rules:
- apiGroups: [""]
  resources: ["pods", "services", "endpoints", "persistentvolumeclaims", "events", "configmaps", "secrets"]
  verbs: ["*"]
- apiGroups: ["apps"]
  resources: ["deployments", "daemonsets", "replicasets", "statefulsets"]
  verbs: ["*"]
- apiGroups: ["networking.k8s.io"]
  resources: ["networkpolicies"]
  verbs: ["*"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: temporal-operator
rules:
- apiGroups: [""]
  resources: ["pods", "services", "endpoints"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
  resources: ["deployments", "replicasets", "statefulsets"]
  verbs: ["get", "list", "watch", "update", "patch"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: temporal-admin-binding
subjects:
- kind: User
  name: temporal-admin@yourcompany.com
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: temporal-admin
  apiGroup: rbac.authorization.k8s.io

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: temporal-operator-binding
  namespace: temporal-system
subjects:
- kind: ServiceAccount
  name: temporal-server
  namespace: temporal-system
roleRef:
  kind: ClusterRole
  name: temporal-operator
  apiGroup: rbac.authorization.k8s.io

Secrets Management

HashiCorp Vault Integration

Vault SecretStore Configuration

# k8s/security/secrets/vault-secretstore.yaml
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: vault-backend
  namespace: temporal-system
spec:
  provider:
    vault:
      server: "https://vault.yourcompany.com"
      path: "secret"
      version: "v2"
      auth:
        kubernetes:
          mountPath: "kubernetes"
          role: "temporal-role"
          serviceAccountRef:
            name: "temporal-external-secrets"
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: temporal-external-secrets
  namespace: temporal-system
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT:role/temporal-external-secrets-role

Database Credentials Secret

# k8s/security/secrets/database-secret.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: temporal-database-secret
  namespace: temporal-system
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  target:
    name: temporal-database-credentials
    creationPolicy: Owner
    template:
      type: Opaque
      data:
        host: "{{ .host }}"
        port: "{{ .port }}"
        database: "{{ .database }}"
        username: "{{ .username }}"
        password: "{{ .password }}"
        connection_string: "postgres://{{ .username }}:{{ .password }}@{{ .host }}:{{ .port }}/{{ .database }}?sslmode=require"
  data:
  - secretKey: host
    remoteRef:
      key: temporal/database
      property: host
  - secretKey: port
    remoteRef:
      key: temporal/database
      property: port
  - secretKey: database
    remoteRef:
      key: temporal/database
      property: database
  - secretKey: username
    remoteRef:
      key: temporal/database
      property: username
  - secretKey: password
    remoteRef:
      key: temporal/database
      property: password

Application Secrets

# k8s/security/secrets/app-secrets.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: temporal-app-secrets
  namespace: temporal-app
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  target:
    name: temporal-app-secrets
    creationPolicy: Owner
  data:
  - secretKey: jwt-secret
    remoteRef:
      key: temporal/app
      property: jwt_secret
  - secretKey: encryption-key
    remoteRef:
      key: temporal/app
      property: encryption_key
  - secretKey: api-key
    remoteRef:
      key: temporal/app
      property: api_key

Encryption at Rest

Database Encryption

# terraform/modules/rds/encryption.tf
resource "aws_kms_key" "rds" {
  description             = "RDS encryption key for ${var.cluster_name}"
  deletion_window_in_days = var.environment == "production" ? 30 : 7
  enable_key_rotation     = true

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "Enable IAM User Permissions"
        Effect = "Allow"
        Principal = {
          AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
        }
        Action   = "kms:*"
        Resource = "*"
      },
      {
        Sid    = "Allow RDS Service"
        Effect = "Allow"
        Principal = {
          Service = "rds.amazonaws.com"
        }
        Action = [
          "kms:Decrypt",
          "kms:GenerateDataKey",
          "kms:CreateGrant"
        ]
        Resource = "*"
      }
    ]
  })

  tags = {
    Name        = "${var.cluster_name}-rds-kms"
    Environment = var.environment
  }
}

resource "aws_kms_alias" "rds" {
  name          = "alias/${var.cluster_name}-rds"
  target_key_id = aws_kms_key.rds.key_id
}

Kubernetes Secret Encryption

# k8s/security/encryption/secret-encryption.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
  providers:
  - kms:
      name: aws-kms
      endpoint: arn:aws:kms:us-west-2:ACCOUNT:key/KEY-ID
      cachesize: 1000
      timeout: 3s
  - identity: {}

Pod Security

Pod Security Standards

# k8s/security/pod-security/pod-security-policy.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: temporal-system
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted
---
apiVersion: v1
kind: Namespace
metadata:
  name: temporal-app
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

Security Context Configuration

# k8s/security/pod-security/security-context.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: temporal-security-context
  namespace: temporal-system
data:
  security-context.yaml: |
    securityContext:
      runAsNonRoot: true
      runAsUser: 10001
      runAsGroup: 10001
      fsGroup: 10001
      seccompProfile:
        type: RuntimeDefault
    containerSecurityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      runAsNonRoot: true
      runAsUser: 10001
      runAsGroup: 10001
      capabilities:
        drop:
        - ALL
      seccompProfile:
        type: RuntimeDefault

Audit Logging

Audit Policy Configuration

# k8s/security/audit/audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# Don't log requests for events
- level: None
  resources:
  - group: ""
    resources: ["events"]

# Don't log authenticated requests to certain non-resource URL paths
- level: None
  userGroups: ["system:authenticated"]
  nonResourceURLs:
  - "/api*" # Wildcard matching.
  - "/version"
  - "/healthz"

# Log the request body of configmap changes in kube-system
- level: Request
  resources:
  - group: ""
    resources: ["configmaps"]
  namespaces: ["kube-system"]

# Log configmap and secret changes in all other namespaces at the Metadata level
- level: Metadata
  resources:
  - group: ""
    resources: ["secrets", "configmaps"]

# Log all other requests at the Metadata level
- level: Metadata
  # Long-running requests like watches that fall under this rule will not
  # generate an audit event in RequestReceived.
  omitStages:
  - RequestReceived

Falco Security Monitoring

# k8s/security/monitoring/falco.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: falco
  namespace: kube-system
spec:
  chart: falco
  repo: https://falcosecurity.github.io/charts
  targetNamespace: falco
  valuesContent: |-
    driver:
      kind: ebpf
    falco:
      rules_file:
        - /etc/falco/falco_rules.yaml
        - /etc/falco/falco_rules.local.yaml
        - /etc/falco/k8s_audit_rules.yaml
        - /etc/falco/rules.d
      json_output: true
      json_include_output_property: true
      log_stderr: true
      log_syslog: false
      priority: debug
      buffered_outputs: false
      outputs:
        rate: 1
        max_burst: 1000
      syscall_event_drops:
        actions:
          - log
          - alert
        rate: 0.03333
        max_burst: 10
    customRules:
      temporal_rules.yaml: |-
        - rule: Temporal Database Connection
          desc: Detect connections to Temporal database
          condition: >
            spawned_process and
            proc.name=psql and
            proc.args contains "temporal"
          output: >
            Temporal database connection detected
            (user=%user.name command=%proc.cmdline pid=%proc.pid container=%container.name)
          priority: INFO
          tags: [temporal, database]

        - rule: Temporal Secret Access
          desc: Detect access to Temporal secrets
          condition: >
            ka.verb in (get, list) and
            ka.uri.param[name] contains "temporal" and
            ka.resource.resource=secrets
          output: >
            Temporal secret accessed
            (user=%ka.user.name verb=%ka.verb resource=%ka.target.name)
          priority: WARNING
          tags: [temporal, secrets]

Compliance and Security Scanning

Vulnerability Scanning with Trivy

# k8s/security/scanning/trivy-operator.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: trivy-operator
  namespace: kube-system
spec:
  chart: trivy-operator
  repo: https://aquasecurity.github.io/helm-charts/
  targetNamespace: trivy-system
  valuesContent: |-
    operator:
      scannerReportTTL: "24h"
      vulnerabilityReportsPlugin: "Trivy"
      configAuditReportsPlugin: "Trivy"

    trivy:
      serverURL: ""
      timeout: "5m0s"
      resources:
        requests:
          cpu: 100m
          memory: 100M
        limits:
          cpu: 500m
          memory: 500M

CIS Kubernetes Benchmark

#!/bin/bash
# scripts/security/run-cis-benchmark.sh

set -euo pipefail

log() {
    echo -e "\033[0;32m[$(date +'%Y-%m-%d %H:%M:%S')] $1\033[0m"
}

log "Running CIS Kubernetes Benchmark..."

# Install kube-bench
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml

# Wait for job completion
kubectl wait --for=condition=complete job/kube-bench --timeout=300s

# Get results
kubectl logs job/kube-bench > cis-benchmark-results.txt

log "CIS Benchmark completed. Results saved to cis-benchmark-results.txt"

# Clean up
kubectl delete job kube-bench

# Parse results for critical findings
CRITICAL_FINDINGS=$(grep -c "FAIL" cis-benchmark-results.txt || true)
if [[ $CRITICAL_FINDINGS -gt 0 ]]; then
    log "WARNING: Found $CRITICAL_FINDINGS critical security findings"
    grep "FAIL" cis-benchmark-results.txt
    exit 1
else
    log "No critical security findings detected"
fi

OPA Gatekeeper Policies

# k8s/security/policies/gatekeeper-constraints.yaml
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
      validation:
        type: object
        properties:
          labels:
            type: array
            items:
              type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredlabels

        violation[{"msg": msg}] {
          required := input.parameters.labels
          provided := input.review.object.metadata.labels
          missing := required[_]
          not provided[missing]
          msg := sprintf("Missing required label: %v", [missing])
        }

---
apiVersion: config.gatekeeper.sh/v1alpha1
kind: K8sRequiredLabels
metadata:
  name: must-have-temporal-labels
spec:
  match:
    kinds:
      - apiGroups: ["apps"]
        kinds: ["Deployment"]
    namespaces: ["temporal-system", "temporal-app"]
  parameters:
    labels: ["app.kubernetes.io/name", "app.kubernetes.io/version", "environment"]

Security Automation Scripts

Security Configuration Script

#!/bin/bash
# scripts/security/configure-security.sh

set -euo pipefail

ENVIRONMENT=${1:-development}

log() {
    echo -e "\033[0;32m[$(date +'%Y-%m-%d %H:%M:%S')] $1\033[0m"
}

error() {
    echo -e "\033[0;31m[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: $1\033[0m"
    exit 1
}

log "Configuring security for environment: $ENVIRONMENT"

# Apply network policies
log "Applying network policies..."
kubectl apply -f k8s/security/network-policies/

# Configure RBAC
log "Configuring RBAC..."
kubectl apply -f k8s/security/rbac/

# Setup certificate management
log "Setting up certificate management..."
kubectl apply -f k8s/security/certificates/

# Configure secrets management
log "Configuring secrets management..."
kubectl apply -f k8s/security/secrets/

# Apply pod security policies
log "Applying pod security policies..."
kubectl apply -f k8s/security/pod-security/

# Setup audit logging
log "Setting up audit logging..."
kubectl apply -f k8s/security/audit/

# Install security monitoring
log "Installing security monitoring..."
kubectl apply -f k8s/security/monitoring/

# Install OPA Gatekeeper
log "Installing OPA Gatekeeper..."
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm upgrade --install gatekeeper gatekeeper/gatekeeper \
    --namespace gatekeeper-system \
    --create-namespace

# Apply Gatekeeper policies
log "Applying Gatekeeper policies..."
kubectl apply -f k8s/security/policies/

log "Security configuration completed successfully!"

Security Validation Script

#!/bin/bash
# scripts/security/validate-security.sh

set -euo pipefail

log() {
    echo -e "\033[0;32m[$(date +'%Y-%m-%d %H:%M:%S')] $1\033[0m"
}

warn() {
    echo -e "\033[1;33m[$(date +'%Y-%m-%d %H:%M:%S')] WARNING: $1\033[0m"
}

error() {
    echo -e "\033[0;31m[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: $1\033[0m"
}

log "Validating security configuration..."

# Check network policies
log "Checking network policies..."
NETWORK_POLICIES=$(kubectl get networkpolicies -A --no-headers | wc -l)
if [[ $NETWORK_POLICIES -gt 0 ]]; then
    log "✓ Network policies are configured ($NETWORK_POLICIES policies found)"
else
    warn "✗ No network policies found"
fi

# Check pod security
log "Checking pod security..."
PRIVILEGED_PODS=$(kubectl get pods -A -o jsonpath='{.items[?(@.spec.securityContext.privileged==true)].metadata.name}' | wc -w)
if [[ $PRIVILEGED_PODS -eq 0 ]]; then
    log "✓ No privileged pods found"
else
    warn "✗ Found $PRIVILEGED_PODS privileged pods"
fi

# Check certificate management
log "Checking certificate management..."
if kubectl get clusterissuer letsencrypt-prod &>/dev/null; then
    log "✓ Certificate management is configured"
else
    error "✗ Certificate management not configured"
fi

# Check secrets encryption
log "Checking secrets encryption..."
if kubectl get secret -n kube-system | grep -q encryption-config; then
    log "✓ Secrets encryption is enabled"
else
    warn "✗ Secrets encryption not detected"
fi

# Check RBAC
log "Checking RBAC..."
CLUSTER_ROLES=$(kubectl get clusterroles | grep -c temporal || true)
if [[ $CLUSTER_ROLES -gt 0 ]]; then
    log "✓ Temporal RBAC is configured"
else
    warn "✗ Temporal RBAC not found"
fi

# Check audit logging
log "Checking audit logging..."
if kubectl get configmap -n kube-system audit-policy &>/dev/null; then
    log "✓ Audit logging is configured"
else
    warn "✗ Audit logging not configured"
fi

log "Security validation completed"

This comprehensive security configuration guide provides enterprise-grade security for Temporal.io deployments with defense-in-depth principles, compliance requirements, and automated security monitoring.