zero-trust — Claude Code skill: what it does, how to install
Implements zero-trust network architecture with identity-based access, micro-segmentation, and continuous verification. Helps replace traditional VPNs with BeyondCorp-style controls.
npx skills add BagelHole/DevOps-Security-Agent-Skills --skill zero-trust -a claude-codeWhat zero-trust does
This skill guides the implementation of the "never trust, always verify" model. It shifts infrastructure defense away from legacy perimeter VPNs toward continuous identity verification and explicit authorization for every request.
The skill covers multiple architecture layers with concrete configuration examples. For edge application security, it includes Cloudflare Access setups using API calls and Terraform. For cluster environments, it supplies deployment manifests for oauth2-proxy paired with Nginx Ingress, along with Istio configurations for strict service-to-service mTLS.
These patterns will not work in isolation. You must have an identity provider supporting OIDC or SAML, such as Okta, Azure AD, or Google Workspace, along with an existing proxy or Kubernetes cluster.
What it helps with
- replace perimeter VPN setups with BeyondCorp access
- configure Cloudflare Access policies and device posture checks
- deploy
oauth2-proxyfor Kubernetes Ingress authentication - enforce strict mTLS communication between microservices
Example prompts for the agent
- Configure oauth2-proxy with OIDC for an internal Kubernetes Ingress.
- Generate Terraform manifests for Cloudflare Access policies.
- Set up strict mutual TLS in Istio to secure service traffic.
How to install zero-trust
1Skills CLI (Vercel)
npx skills add BagelHole/DevOps-Security-Agent-Skills --skill zero-trust -a claude-code2Manually: put the files in place
~/.claude/skills/zero-trust/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/zero-trust/
1Skills CLI (Vercel)
npx skills add BagelHole/DevOps-Security-Agent-Skills --skill zero-trust -a codex2Manually: put the files in place
.agents/skills/zero-trust/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add BagelHole/DevOps-Security-Agent-Skills --skill zero-trust -a cursor2Manually: put the files in place
.cursor/skills/zero-trust/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install BagelHole/DevOps-Security-Agent-Skills zero-trust2Manually: put the files in place
.github/skills/zero-trust/SKILL.md1Skills CLI (Vercel)
npx skills add BagelHole/DevOps-Security-Agent-Skills --skill zero-trust -a gemini-cli2Platform CLI
gemini skills install https://github.com/BagelHole/DevOps-Security-Agent-Skills --path security/network/zero-trustManually: put the files in place
.devin/skills/zero-trust/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add BagelHole/DevOps-Security-Agent-Skills --skill zero-trust -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about zero-trust
How to install zero-trust in Claude Code?
Run npx skills add BagelHole/DevOps-Security-Agent-Skills --skill zero-trust -a claude-code.
What does the zero-trust skill do?
It provides configuration guides and manifests for identity-based security. The skill covers Cloudflare Access, Terraform policies, Kubernetes oauth2-proxy deployments, and Istio mTLS.
What prerequisites are needed for this architecture?
You need an identity provider compatible with OIDC or SAML, such as Okta, Azure AD, or Google Workspace. Workload-level configurations also require a Kubernetes cluster and a proxy or service mesh.
Source text
SKILL.md · MIT
---
name: zero-trust
description: Implement zero-trust network architecture. Configure identity-based access, micro-segmentation, and continuous verification. Use when implementing modern security architectures.
license: MIT
metadata:
author: devops-skills
version: "1.0"
---
# 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
## 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
## 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
```
## BeyondCorp Implementation
### Cloudflare Access Configuration
```bash
# 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"]
}'
# 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" } }
]
}'
# 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 }
}'
```
### 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 = ["[email protected]"]
}
}
```
## Identity-Aware Proxy with OAuth2 Proxy
```yaml
# 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
---
# 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
```
## Service Mesh mTLS (Istio)
```yaml
# Enforce strict mTLS across the mesh
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system
spec:
mtls:
mode: STRICT
---
# 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/*"]
---
# Default deny all in namespace
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: production
spec: {}
```
## Micro-Segmentation with Kubernetes Network Policies
```yaml
# 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
---
# 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
---
# 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
---
# 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
```
## OPA Policy for Access Decisions
```rego
# 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
}
```
## 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
## Troubleshooting
| Problem | Cause | Solution |
|---------|-------|----------|
| Users cannot access internal apps | Identity provider misconfigured | Verify OIDC/SAML settings; check redirect URIs |
| mTLS connections failing | Certificate expired or wrong CA | Check cert expiry with `istioctl proxy-config secret`; verify CA chain |
| Network policy blocking legitimate traffic | Missing egress or ingress rule | Use `kubectl describe networkpolicy`; verify pod labels match selectors |
| Device posture check fails | MDM agent not reporting | Verify device agent is running; check compliance dashboard |
| OAuth2 proxy returns 403 | User email domain not in allow-list | Add domain to `--email-domain` flag or update group membership |
## Related Skills
- [service-mesh](../../../infrastructure/networking/service-mesh/) - mTLS implementation
- [kubernetes-hardening](../../hardening/kubernetes-hardening/) - K8s security
- [vpn-setup](../vpn-setup/) - Traditional VPN (contrast with zero trust)
© devops-skills · MIT · BagelHole/DevOps-Security-Agent-Skills