zero-trust

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Zero Trust Architecture

零信任架构

Implement "never trust, always verify" security model.
实施「永不信任,始终验证」的安全模型。

When to Use This Skill

适用场景

Use this skill when:
  • Replacing traditional perimeter-based VPN access models
  • Implementing BeyondCorp-style access to internal applications
  • Securing multi-cloud or hybrid-cloud environments
  • Enforcing identity-based access for every service interaction
  • Meeting compliance requirements for continuous verification and least privilege
  • Adopting micro-segmentation for Kubernetes or cloud workloads
在以下场景中使用本技能:
  • 替换传统基于边界的VPN访问模型
  • 为内部应用实施BeyondCorp风格的访问控制
  • 保护多云或混合云环境
  • 为每个服务交互强制实施基于身份的访问
  • 满足持续验证和最小权限的合规要求
  • 为Kubernetes或云工作负载采用微分段

Prerequisites

前置条件

  • Identity provider (IdP) supporting OIDC/SAML (Okta, Azure AD, Google Workspace)
  • Service mesh or proxy infrastructure (Istio, Envoy, Cloudflare Access)
  • Device management/MDM solution for device posture checks
  • Kubernetes cluster for workload-level examples
  • Understanding of mTLS, RBAC, and network policies
  • 支持OIDC/SAML的身份提供商(IdP)(如Okta、Azure AD、Google Workspace)
  • 服务网格或代理基础设施(如Istio、Envoy、Cloudflare Access)
  • 用于设备状态检查的设备管理/MDM解决方案
  • 用于工作负载级示例的Kubernetes集群
  • 了解mTLS、RBAC和网络策略

Core Principles

核心原则

yaml
zero_trust_principles:
  verify_explicitly:
    description: "Authenticate and authorize every access request"
    controls:
      - Strong multi-factor authentication
      - Identity-aware proxy for all applications
      - Service-to-service mTLS
      - API token validation on every request

  least_privilege:
    description: "Grant minimum access needed for the task"
    controls:
      - Just-in-time (JIT) access provisioning
      - Time-bounded access grants
      - Role-based access with fine-grained permissions
      - Regular access reviews and certification

  assume_breach:
    description: "Design systems expecting compromise has occurred"
    controls:
      - Micro-segmentation between all services
      - End-to-end encryption (data in transit and at rest)
      - Continuous monitoring and anomaly detection
      - Blast radius containment
yaml
zero_trust_principles:
  verify_explicitly:
    description: "Authenticate and authorize every access request"
    controls:
      - Strong multi-factor authentication
      - Identity-aware proxy for all applications
      - Service-to-service mTLS
      - API token validation on every request

  least_privilege:
    description: "Grant minimum access needed for the task"
    controls:
      - Just-in-time (JIT) access provisioning
      - Time-bounded access grants
      - Role-based access with fine-grained permissions
      - Regular access reviews and certification

  assume_breach:
    description: "Design systems expecting compromise has occurred"
    controls:
      - Micro-segmentation between all services
      - End-to-end encryption (data in transit and at rest)
      - Continuous monitoring and anomaly detection
      - Blast radius containment

BeyondCorp Implementation

BeyondCorp 实施方案

Cloudflare Access Configuration

Cloudflare Access 配置

bash
undefined
bash
undefined

Create an Access application for an internal service

Create an Access application for an internal service

curl -X POST "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/access/apps"
-H "Authorization: Bearer ${CF_TOKEN}"
-H "Content-Type: application/json"
-d '{ "name": "Internal Dashboard", "domain": "dashboard.internal.example.com", "type": "self_hosted", "session_duration": "12h", "auto_redirect_to_identity": true, "allowed_idps": ["google-workspace-idp-id"] }'
curl -X POST "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/access/apps"
-H "Authorization: Bearer ${CF_TOKEN}"
-H "Content-Type: application/json"
-d '{ "name": "Internal Dashboard", "domain": "dashboard.internal.example.com", "type": "self_hosted", "session_duration": "12h", "auto_redirect_to_identity": true, "allowed_idps": ["google-workspace-idp-id"] }'

Create an Access policy

Create an Access policy

curl -X POST "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/access/apps/${APP_ID}/policies"
-H "Authorization: Bearer ${CF_TOKEN}"
-H "Content-Type: application/json"
-d '{ "name": "Engineering team access", "decision": "allow", "include": [ { "group": { "id": "engineering-group-id" } } ], "require": [ { "login_method": { "id": "google-workspace-idp-id" } } ], "exclude": [ { "geo": { "country_code": "KP" } } ] }'
curl -X POST "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/access/apps/${APP_ID}/policies"
-H "Authorization: Bearer ${CF_TOKEN}"
-H "Content-Type: application/json"
-d '{ "name": "Engineering team access", "decision": "allow", "include": [ { "group": { "id": "engineering-group-id" } } ], "require": [ { "login_method": { "id": "google-workspace-idp-id" } } ], "exclude": [ { "geo": { "country_code": "KP" } } ] }'

Create a device posture rule

Create a device posture rule

curl -X POST "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/devices/posture"
-H "Authorization: Bearer ${CF_TOKEN}"
-H "Content-Type: application/json"
-d '{ "name": "Require disk encryption", "type": "disk_encryption", "match": { "platform": "linux" }, "schedule": "1h", "input": { "requireAll": true } }'
undefined
curl -X POST "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/devices/posture"
-H "Authorization: Bearer ${CF_TOKEN}"
-H "Content-Type: application/json"
-d '{ "name": "Require disk encryption", "type": "disk_encryption", "match": { "platform": "linux" }, "schedule": "1h", "input": { "requireAll": true } }'
undefined

Cloudflare Access Terraform

Cloudflare Access Terraform

hcl
resource "cloudflare_access_application" "dashboard" {
  account_id       = var.cloudflare_account_id
  name             = "Internal Dashboard"
  domain           = "dashboard.internal.example.com"
  type             = "self_hosted"
  session_duration = "12h"

  auto_redirect_to_identity = true
}

resource "cloudflare_access_policy" "engineering" {
  account_id     = var.cloudflare_account_id
  application_id = cloudflare_access_application.dashboard.id
  name           = "Engineering team"
  precedence     = 1
  decision       = "allow"

  include {
    group = [cloudflare_access_group.engineering.id]
  }

  require {
    login_method = [var.google_idp_id]
  }
}

resource "cloudflare_access_group" "engineering" {
  account_id = var.cloudflare_account_id
  name       = "Engineering"

  include {
    email_domain = ["example.com"]
  }

  require {
    group = ["engineering@example.com"]
  }
}
hcl
resource "cloudflare_access_application" "dashboard" {
  account_id       = var.cloudflare_account_id
  name             = "Internal Dashboard"
  domain           = "dashboard.internal.example.com"
  type             = "self_hosted"
  session_duration = "12h"

  auto_redirect_to_identity = true
}

resource "cloudflare_access_policy" "engineering" {
  account_id     = var.cloudflare_account_id
  application_id = cloudflare_access_application.dashboard.id
  name           = "Engineering team"
  precedence     = 1
  decision       = "allow"

  include {
    group = [cloudflare_access_group.engineering.id]
  }

  require {
    login_method = [var.google_idp_id]
  }
}

resource "cloudflare_access_group" "engineering" {
  account_id = var.cloudflare_account_id
  name       = "Engineering"

  include {
    email_domain = ["example.com"]
  }

  require {
    group = ["engineering@example.com"]
  }
}

Identity-Aware Proxy with OAuth2 Proxy

基于身份的代理(OAuth2 Proxy)

yaml
undefined
yaml
undefined

oauth2-proxy deployment for protecting internal services

oauth2-proxy deployment for protecting internal services

apiVersion: apps/v1 kind: Deployment metadata: name: oauth2-proxy namespace: auth spec: replicas: 2 selector: matchLabels: app: oauth2-proxy template: metadata: labels: app: oauth2-proxy spec: containers: - name: oauth2-proxy image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 args: - --provider=oidc - --oidc-issuer-url=https://accounts.google.com - --client-id=$(CLIENT_ID) - --client-secret=$(CLIENT_SECRET) - --email-domain=example.com - --upstream=http://internal-service.default.svc:8080 - --http-address=0.0.0.0:4180 - --cookie-secret=$(COOKIE_SECRET) - --cookie-secure=true - --cookie-httponly=true - --cookie-samesite=lax - --set-xauthrequest=true - --pass-access-token=true - --skip-provider-button=true - --session-store-type=redis - --redis-connection-url=redis://redis.auth.svc:6379 env: - name: CLIENT_ID valueFrom: secretKeyRef: name: oauth2-proxy key: client-id - name: CLIENT_SECRET valueFrom: secretKeyRef: name: oauth2-proxy key: client-secret - name: COOKIE_SECRET valueFrom: secretKeyRef: name: oauth2-proxy key: cookie-secret ports: - containerPort: 4180

apiVersion: apps/v1 kind: Deployment metadata: name: oauth2-proxy namespace: auth spec: replicas: 2 selector: matchLabels: app: oauth2-proxy template: metadata: labels: app: oauth2-proxy spec: containers: - name: oauth2-proxy image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 args: - --provider=oidc - --oidc-issuer-url=https://accounts.google.com - --client-id=$(CLIENT_ID) - --client-secret=$(CLIENT_SECRET) - --email-domain=example.com - --upstream=http://internal-service.default.svc:8080 - --http-address=0.0.0.0:4180 - --cookie-secret=$(COOKIE_SECRET) - --cookie-secure=true - --cookie-httponly=true - --cookie-samesite=lax - --set-xauthrequest=true - --pass-access-token=true - --skip-provider-button=true - --session-store-type=redis - --redis-connection-url=redis://redis.auth.svc:6379 env: - name: CLIENT_ID valueFrom: secretKeyRef: name: oauth2-proxy key: client-id - name: CLIENT_SECRET valueFrom: secretKeyRef: name: oauth2-proxy key: client-secret - name: COOKIE_SECRET valueFrom: secretKeyRef: name: oauth2-proxy key: cookie-secret ports: - containerPort: 4180

Ingress routing through oauth2-proxy

Ingress routing through oauth2-proxy

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: internal-service annotations: nginx.ingress.kubernetes.io/auth-url: "https://auth.example.com/oauth2/auth" nginx.ingress.kubernetes.io/auth-signin: "https://auth.example.com/oauth2/start?rd=$scheme://$host$request_uri" nginx.ingress.kubernetes.io/auth-response-headers: "X-Auth-Request-User,X-Auth-Request-Email" spec: rules: - host: dashboard.example.com http: paths: - path: / pathType: Prefix backend: service: name: internal-service port: number: 8080
undefined
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: internal-service annotations: nginx.ingress.kubernetes.io/auth-url: "https://auth.example.com/oauth2/auth" nginx.ingress.kubernetes.io/auth-signin: "https://auth.example.com/oauth2/start?rd=$scheme://$host$request_uri" nginx.ingress.kubernetes.io/auth-response-headers: "X-Auth-Request-User,X-Auth-Request-Email" spec: rules: - host: dashboard.example.com http: paths: - path: / pathType: Prefix backend: service: name: internal-service port: number: 8080
undefined

Service Mesh mTLS (Istio)

服务网格mTLS(Istio)

yaml
undefined
yaml
undefined

Enforce strict mTLS across the mesh

Enforce strict mTLS across the mesh

apiVersion: security.istio.io/v1beta1 kind: PeerAuthentication metadata: name: default namespace: istio-system spec: mtls: mode: STRICT

apiVersion: security.istio.io/v1beta1 kind: PeerAuthentication metadata: name: default namespace: istio-system spec: mtls: mode: STRICT

Authorization policy: frontend can call backend

Authorization policy: frontend can call backend

apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: backend-access namespace: default spec: selector: matchLabels: app: backend action: ALLOW rules: - from: - source: principals: ["cluster.local/ns/default/sa/frontend"] to: - operation: methods: ["GET", "POST"] paths: ["/api/*"]

apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: backend-access namespace: default spec: selector: matchLabels: app: backend action: ALLOW rules: - from: - source: principals: ["cluster.local/ns/default/sa/frontend"] to: - operation: methods: ["GET", "POST"] paths: ["/api/*"]

Default deny all in namespace

Default deny all in namespace

apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: deny-all namespace: production spec: {}
undefined
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: deny-all namespace: production spec: {}
undefined

Micro-Segmentation with Kubernetes Network Policies

Kubernetes网络策略实现微分段

yaml
undefined
yaml
undefined

Default deny all traffic in namespace

Default deny all traffic in namespace

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-all namespace: production spec: podSelector: {} policyTypes: - Ingress - Egress

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-all namespace: production spec: podSelector: {} policyTypes: - Ingress - Egress

Allow DNS resolution for all pods

Allow DNS resolution for all pods

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-dns namespace: production spec: podSelector: {} policyTypes: - Egress egress: - to: [] ports: - protocol: UDP port: 53 - protocol: TCP port: 53

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-dns namespace: production spec: podSelector: {} policyTypes: - Egress egress: - to: [] ports: - protocol: UDP port: 53 - protocol: TCP port: 53

Frontend: allow ingress from ingress controller, egress to backend

Frontend: allow ingress from ingress controller, egress to backend

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: frontend-policy namespace: production spec: podSelector: matchLabels: app: frontend policyTypes: - Ingress - Egress ingress: - from: - namespaceSelector: matchLabels: name: ingress-nginx ports: - protocol: TCP port: 8080 egress: - to: - podSelector: matchLabels: app: backend ports: - protocol: TCP port: 8080

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: frontend-policy namespace: production spec: podSelector: matchLabels: app: frontend policyTypes: - Ingress - Egress ingress: - from: - namespaceSelector: matchLabels: name: ingress-nginx ports: - protocol: TCP port: 8080 egress: - to: - podSelector: matchLabels: app: backend ports: - protocol: TCP port: 8080

Database: allow from backend only, no egress

Database: allow from backend only, no egress

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: database-policy namespace: production spec: podSelector: matchLabels: app: database policyTypes: - Ingress - Egress ingress: - from: - podSelector: matchLabels: app: backend ports: - protocol: TCP port: 5432
undefined
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: database-policy namespace: production spec: podSelector: matchLabels: app: database policyTypes: - Ingress - Egress ingress: - from: - podSelector: matchLabels: app: backend ports: - protocol: TCP port: 5432
undefined

OPA Policy for Access Decisions

用于访问决策的OPA策略

rego
undefined
rego
undefined

policy.rego - Zero trust access decision

policy.rego - Zero trust access decision

package zerotrust.access
import rego.v1
default allow := false
allow if { identity_verified device_compliant authorized_for_resource risk_acceptable }
identity_verified if { input.identity.authenticated == true input.identity.mfa_verified == true time.now_ns() < input.identity.session_expires_ns }
device_compliant if { input.device.encryption_enabled == true input.device.os_updated == true input.device.firewall_enabled == true input.device.certificate_valid == true }
authorized_for_resource if { some role in input.identity.roles some permission in data.role_permissions[role] permission == input.resource.required_permission }
risk_acceptable if { input.risk.score < 70 not input.risk.active_threat }
step_up_required if { input.risk.score >= 50 input.risk.score < 70 not input.identity.recent_mfa }
undefined
package zerotrust.access
import rego.v1
default allow := false
allow if { identity_verified device_compliant authorized_for_resource risk_acceptable }
identity_verified if { input.identity.authenticated == true input.identity.mfa_verified == true time.now_ns() < input.identity.session_expires_ns }
device_compliant if { input.device.encryption_enabled == true input.device.os_updated == true input.device.firewall_enabled == true input.device.certificate_valid == true }
authorized_for_resource if { some role in input.identity.roles some permission in data.role_permissions[role] permission == input.resource.required_permission }
risk_acceptable if { input.risk.score < 70 not input.risk.active_threat }
step_up_required if { input.risk.score >= 50 input.risk.score < 70 not input.identity.recent_mfa }
undefined

Implementation Steps

实施步骤

  1. Inventory assets and data flows - Map every application, service, and data store
  2. Deploy identity provider - Centralize authentication with SSO and MFA
  3. Implement identity-aware proxy - Route all access through authentication layer
  4. Enable mTLS for service mesh - Encrypt and authenticate all service communication
  5. Apply network policies - Default deny with explicit allow rules
  6. Add device posture checks - Verify device compliance before granting access
  7. Deploy continuous monitoring - Log and analyze all access decisions
  8. Iterate and refine - Review policies based on monitoring data
  1. 资产和数据流盘点 - 梳理所有应用、服务和数据存储
  2. 部署身份提供商 - 通过SSO和MFA集中认证
  3. 实施基于身份的代理 - 将所有访问路由到认证层
  4. 为服务网格启用mTLS - 加密并认证所有服务通信
  5. 应用网络策略 - 默认拒绝,仅显式允许必要流量
  6. 添加设备状态检查 - 在授予访问权限前验证设备合规性
  7. 部署持续监控 - 记录并分析所有访问决策
  8. 迭代优化 - 根据监控数据调整策略

Troubleshooting

故障排查

ProblemCauseSolution
Users cannot access internal appsIdentity provider misconfiguredVerify OIDC/SAML settings; check redirect URIs
mTLS connections failingCertificate expired or wrong CACheck cert expiry with
istioctl proxy-config secret
; verify CA chain
Network policy blocking legitimate trafficMissing egress or ingress ruleUse
kubectl describe networkpolicy
; verify pod labels match selectors
Device posture check failsMDM agent not reportingVerify device agent is running; check compliance dashboard
OAuth2 proxy returns 403User email domain not in allow-listAdd domain to
--email-domain
flag or update group membership
问题原因解决方案
用户无法访问内部应用身份提供商配置错误验证OIDC/SAML设置;检查重定向URI
mTLS连接失败证书过期或CA错误使用
istioctl proxy-config secret
检查证书有效期;验证CA链
网络策略阻止合法流量缺少出口或入口规则使用
kubectl describe networkpolicy
查看策略;验证Pod标签与选择器匹配
设备状态检查失败MDM代理未上报数据验证设备代理是否运行;检查合规性仪表板
OAuth2 proxy返回403用户邮箱域名不在允许列表将域名添加到
--email-domain
参数或更新组成员身份

Related Skills

相关技能

  • service-mesh - mTLS implementation
  • kubernetes-hardening - K8s security
  • vpn-setup - Traditional VPN (contrast with zero trust)
  • service-mesh - mTLS实现
  • kubernetes-hardening - K8s安全加固
  • vpn-setup - 传统VPN(与零信任对比)