mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-18 05:29:40 +03:00
Initial commit - 611 cybersecurity skills across all subdomains
This commit is contained in:
@@ -0,0 +1,376 @@
|
||||
---
|
||||
name: deploying-cloudflare-access-for-zero-trust
|
||||
description: >
|
||||
Deploying Cloudflare Access with Cloudflare Tunnel to provide zero trust access
|
||||
to self-hosted and private applications, configuring identity-aware access policies,
|
||||
device posture checks, and WARP client enrollment for VPN replacement.
|
||||
domain: cybersecurity
|
||||
subdomain: zero-trust-architecture
|
||||
tags: [cloudflare, cloudflare-access, zero-trust, cloudflare-tunnel, warp, ztna, cloudflare-one]
|
||||
version: "1.0"
|
||||
author: mahipal
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# Deploying Cloudflare Access for Zero Trust
|
||||
|
||||
## When to Use
|
||||
|
||||
- When replacing VPN infrastructure with identity-aware application access using Cloudflare One
|
||||
- When exposing self-hosted internal applications through Cloudflare Tunnel without opening inbound ports
|
||||
- When implementing ZTNA for a distributed workforce accessing web applications, SSH, and RDP services
|
||||
- When needing a cost-effective zero trust solution with integrated DLP, CASB, and SWG capabilities
|
||||
- When securing contractor and third-party access to specific applications without full network access
|
||||
|
||||
**Do not use** for applications requiring persistent UDP connections not supported by Cloudflare Tunnel, for environments requiring air-gapped or fully on-premises access control, or when regulatory requirements prohibit routing traffic through third-party cloud infrastructure.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Cloudflare account with Zero Trust subscription (Free for up to 50 users, paid plans for larger teams)
|
||||
- Domain name managed by Cloudflare DNS (or ability to add CNAME records)
|
||||
- Linux, Windows, or macOS server to run `cloudflared` tunnel daemon
|
||||
- Identity provider: Okta, Microsoft Entra ID, Google Workspace, GitHub, or any SAML/OIDC provider
|
||||
- Cloudflare WARP client for device-level enrollment (optional but recommended)
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 1: Create a Cloudflare Tunnel to Internal Applications
|
||||
|
||||
Install `cloudflared` and create a persistent tunnel to expose internal services.
|
||||
|
||||
```bash
|
||||
# Install cloudflared on Ubuntu/Debian
|
||||
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb \
|
||||
-o cloudflared.deb
|
||||
sudo dpkg -i cloudflared.deb
|
||||
|
||||
# Authenticate cloudflared with your Cloudflare account
|
||||
cloudflared tunnel login
|
||||
|
||||
# Create a named tunnel
|
||||
cloudflared tunnel create internal-apps
|
||||
# Output: Created tunnel internal-apps with id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
|
||||
# Configure tunnel routes to internal applications
|
||||
cat > ~/.cloudflared/config.yml << 'EOF'
|
||||
tunnel: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
credentials-file: /home/admin/.cloudflared/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json
|
||||
|
||||
ingress:
|
||||
- hostname: wiki.company.com
|
||||
service: http://localhost:8080
|
||||
- hostname: git.company.com
|
||||
service: http://10.1.1.50:3000
|
||||
- hostname: grafana.company.com
|
||||
service: http://10.1.1.60:3000
|
||||
- hostname: ssh.company.com
|
||||
service: ssh://localhost:22
|
||||
- hostname: rdp.company.com
|
||||
service: rdp://10.1.1.100:3389
|
||||
# Catch-all rule (required)
|
||||
- service: http_status:404
|
||||
EOF
|
||||
|
||||
# Route DNS to the tunnel
|
||||
cloudflared tunnel route dns internal-apps wiki.company.com
|
||||
cloudflared tunnel route dns internal-apps git.company.com
|
||||
cloudflared tunnel route dns internal-apps grafana.company.com
|
||||
|
||||
# Run tunnel as a systemd service
|
||||
sudo cloudflared service install
|
||||
sudo systemctl enable cloudflared
|
||||
sudo systemctl start cloudflared
|
||||
|
||||
# Verify tunnel status
|
||||
cloudflared tunnel info internal-apps
|
||||
```
|
||||
|
||||
### Step 2: Configure Identity Provider Integration
|
||||
|
||||
Set up authentication with your organization's identity provider.
|
||||
|
||||
```bash
|
||||
# Using Cloudflare API to configure Okta as IdP
|
||||
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/identity_providers" \
|
||||
-H "Authorization: Bearer ${CF_API_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{
|
||||
"name": "Corporate Okta",
|
||||
"type": "okta",
|
||||
"config": {
|
||||
"client_id": "OKTA_CLIENT_ID",
|
||||
"client_secret": "OKTA_CLIENT_SECRET",
|
||||
"okta_account": "company.okta.com",
|
||||
"api_token": "OKTA_API_TOKEN",
|
||||
"claims": ["email", "groups", "name"],
|
||||
"email_claim_name": "email"
|
||||
}
|
||||
}'
|
||||
|
||||
# Configure Microsoft Entra ID as additional IdP
|
||||
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/identity_providers" \
|
||||
-H "Authorization: Bearer ${CF_API_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{
|
||||
"name": "Microsoft Entra ID",
|
||||
"type": "azureAD",
|
||||
"config": {
|
||||
"client_id": "AZURE_APP_CLIENT_ID",
|
||||
"client_secret": "AZURE_APP_CLIENT_SECRET",
|
||||
"directory_id": "AZURE_TENANT_ID",
|
||||
"support_groups": true,
|
||||
"claims": ["email", "groups", "name"]
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
### Step 3: Create Access Applications and Policies
|
||||
|
||||
Define Access applications with identity-aware policies for each internal service.
|
||||
|
||||
```bash
|
||||
# Create Access application for internal wiki
|
||||
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps" \
|
||||
-H "Authorization: Bearer ${CF_API_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{
|
||||
"name": "Internal Wiki",
|
||||
"domain": "wiki.company.com",
|
||||
"type": "self_hosted",
|
||||
"session_duration": "8h",
|
||||
"auto_redirect_to_identity": true,
|
||||
"http_only_cookie_attribute": true,
|
||||
"same_site_cookie_attribute": "lax",
|
||||
"logo_url": "https://company.com/wiki-logo.png",
|
||||
"allowed_idps": ["OKTA_IDP_ID", "AZURE_IDP_ID"]
|
||||
}'
|
||||
|
||||
# Create Allow policy for the wiki application
|
||||
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps/{app_id}/policies" \
|
||||
-H "Authorization: Bearer ${CF_API_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{
|
||||
"name": "Allow Engineering Team",
|
||||
"decision": "allow",
|
||||
"precedence": 1,
|
||||
"include": [
|
||||
{"group": {"id": "ENGINEERING_GROUP_ID"}},
|
||||
{"okta": {"name": "Engineering", "identity_provider_id": "OKTA_IDP_ID"}}
|
||||
],
|
||||
"require": [
|
||||
{"device_posture": {"integration_uid": "CROWDSTRIKE_INTEGRATION_ID"}}
|
||||
]
|
||||
}'
|
||||
|
||||
# Create Access application for SSH access
|
||||
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps" \
|
||||
-H "Authorization: Bearer ${CF_API_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{
|
||||
"name": "SSH Access",
|
||||
"domain": "ssh.company.com",
|
||||
"type": "ssh",
|
||||
"session_duration": "4h",
|
||||
"auto_redirect_to_identity": true
|
||||
}'
|
||||
```
|
||||
|
||||
### Step 4: Deploy WARP Client for Device Enrollment
|
||||
|
||||
Enroll corporate devices using Cloudflare WARP for private network access and device posture.
|
||||
|
||||
```bash
|
||||
# Create device enrollment rule
|
||||
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/devices/policy" \
|
||||
-H "Authorization: Bearer ${CF_API_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{
|
||||
"name": "Corporate Device Enrollment",
|
||||
"match": "identity.email matches \".*@company\\.com$\"",
|
||||
"precedence": 100,
|
||||
"enabled": true,
|
||||
"gateway_unique_id": "GATEWAY_ID",
|
||||
"support_url": "https://helpdesk.company.com/warp-help"
|
||||
}'
|
||||
|
||||
# Install WARP on macOS via MDM (Jamf/Intune)
|
||||
# Download: https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/download-warp/
|
||||
# Deploy with MDM configuration profile:
|
||||
cat > warp_mdm_config.plist << 'EOF'
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>organization</key>
|
||||
<string>company</string>
|
||||
<key>auto_connect</key>
|
||||
<integer>1</integer>
|
||||
<key>switch_locked</key>
|
||||
<true/>
|
||||
<key>onboarding</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
EOF
|
||||
|
||||
# Install Cloudflare root certificate for TLS inspection
|
||||
# Download from: https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/user-side-certificates/
|
||||
sudo cp cloudflare-root-ca.pem /usr/local/share/ca-certificates/cloudflare-root-ca.crt
|
||||
sudo update-ca-certificates
|
||||
|
||||
# Configure split tunnel to route private network through WARP
|
||||
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/devices/policy/{policy_id}/fallback_domains" \
|
||||
-H "Authorization: Bearer ${CF_API_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '[
|
||||
{"suffix": "internal.corp", "description": "Internal corporate domain"},
|
||||
{"suffix": "10.0.0.0/8", "description": "Private network range"}
|
||||
]'
|
||||
```
|
||||
|
||||
### Step 5: Configure Device Posture Checks
|
||||
|
||||
Integrate endpoint security signals into Access policies.
|
||||
|
||||
```bash
|
||||
# Add CrowdStrike device posture integration
|
||||
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/devices/posture/integration" \
|
||||
-H "Authorization: Bearer ${CF_API_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{
|
||||
"name": "CrowdStrike Falcon",
|
||||
"type": "crowdstrike_s2s",
|
||||
"config": {
|
||||
"api_url": "https://api.crowdstrike.com",
|
||||
"client_id": "CS_API_CLIENT_ID",
|
||||
"client_secret": "CS_API_CLIENT_SECRET",
|
||||
"customer_id": "CS_CUSTOMER_ID"
|
||||
},
|
||||
"interval": "10m"
|
||||
}'
|
||||
|
||||
# Create device posture rule for disk encryption
|
||||
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/devices/posture" \
|
||||
-H "Authorization: Bearer ${CF_API_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{
|
||||
"name": "Disk Encryption Required",
|
||||
"type": "disk_encryption",
|
||||
"match": [{"platform": "windows"}, {"platform": "mac"}],
|
||||
"input": {"requireAll": true}
|
||||
}'
|
||||
|
||||
# Create device posture rule for OS version
|
||||
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/devices/posture" \
|
||||
-H "Authorization: Bearer ${CF_API_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{
|
||||
"name": "Minimum OS Version",
|
||||
"type": "os_version",
|
||||
"match": [{"platform": "windows"}],
|
||||
"input": {"version": "10.0.19045", "operator": ">="}
|
||||
}'
|
||||
```
|
||||
|
||||
### Step 6: Set Up Audit Logging and Analytics
|
||||
|
||||
Configure logging for access decisions and tunnel health monitoring.
|
||||
|
||||
```bash
|
||||
# Enable Logpush for Access audit logs to S3
|
||||
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/logpush/jobs" \
|
||||
-H "Authorization: Bearer ${CF_API_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{
|
||||
"name": "access-audit-logs",
|
||||
"output_options": {
|
||||
"field_names": ["RayID","Action","Allowed","AppDomain","AppUUID","Connection","Country","CreatedAt","Email","IPAddress","PurposeJustificationPrompt","PurposeJustificationResponse","TemporaryAccessDuration","UserUID"],
|
||||
"timestamp_format": "rfc3339"
|
||||
},
|
||||
"destination_conf": "s3://security-logs-bucket/cloudflare-access/?region=us-east-1&access-key-id=AKID&secret-access-key=SECRET",
|
||||
"dataset": "access_requests",
|
||||
"enabled": true
|
||||
}'
|
||||
|
||||
# Query access logs via GraphQL Analytics API
|
||||
curl -X POST "https://api.cloudflare.com/client/v4/graphql" \
|
||||
-H "Authorization: Bearer ${CF_API_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{
|
||||
"query": "{ viewer { accounts(filter: {accountTag: \"ACCOUNT_ID\"}) { accessLoginRequestsAdaptiveGroups(filter: {datetime_gt: \"2026-02-22T00:00:00Z\"}, limit: 100, orderBy: [count_DESC]) { dimensions { action appName userEmail country } count } } } }"
|
||||
}'
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
| Term | Definition |
|
||||
|------|------------|
|
||||
| Cloudflare Tunnel | Encrypted outbound-only connection from your infrastructure to Cloudflare's network, exposing internal services without opening inbound firewall ports |
|
||||
| Cloudflare Access | Identity-aware reverse proxy evaluating every request against access policies before granting access to protected applications |
|
||||
| WARP Client | Cloudflare's endpoint agent that routes device traffic through Cloudflare's network for policy enforcement and private network access |
|
||||
| Access Application | Configuration object defining a protected resource (self-hosted, SaaS, or infrastructure) with associated access policies |
|
||||
| Device Posture | Endpoint health signals (OS version, disk encryption, EDR status) evaluated as conditions in Access policies |
|
||||
| Cloudflare One | Unified SASE platform combining ZTNA (Access), SWG (Gateway), CASB, DLP, and RBI |
|
||||
|
||||
## Tools & Systems
|
||||
|
||||
- **Cloudflare Access**: Identity-aware application proxy providing per-request authorization
|
||||
- **Cloudflare Tunnel (cloudflared)**: Daemon creating encrypted tunnels from internal networks to Cloudflare edge
|
||||
- **WARP Client**: Cross-platform endpoint agent for device enrollment, DNS filtering, and private network routing
|
||||
- **Cloudflare Gateway**: Secure Web Gateway providing DNS/HTTP filtering and DLP inspection
|
||||
- **Cloudflare Logpush**: Real-time log streaming to external SIEM and storage destinations
|
||||
- **Access for Infrastructure**: SSH and RDP access with short-lived certificates and session recording
|
||||
|
||||
## Common Scenarios
|
||||
|
||||
### Scenario: Startup with 200 Employees Deploying Zero Trust from Scratch
|
||||
|
||||
**Context**: A SaaS startup with 200 employees and no existing VPN wants to provide secure access to internal tools (Grafana, internal APIs, staging environments) running on AWS. Budget is limited, and the team has no dedicated security staff.
|
||||
|
||||
**Approach**:
|
||||
1. Start with Cloudflare Zero Trust free tier (up to 50 users) for proof of concept
|
||||
2. Deploy one `cloudflared` tunnel on an EC2 instance in the production VPC
|
||||
3. Expose Grafana, internal wiki, and staging apps through tunnel with DNS routing
|
||||
4. Configure Google Workspace as IdP for SSO authentication
|
||||
5. Create Access policies requiring @company.com email domain for all applications
|
||||
6. Add device posture checks for disk encryption and OS version
|
||||
7. Upgrade to paid plan and deploy WARP client to all employee laptops via MDM
|
||||
8. Enable Gateway DNS filtering and HTTP inspection for malware protection
|
||||
9. Configure Logpush to send access logs to Datadog for monitoring
|
||||
|
||||
**Pitfalls**: Cloudflare root certificate must be installed on all devices for TLS inspection to work; some applications may break with TLS interception. Tunnel failover requires running multiple `cloudflared` instances or using Cloudflare's replicas feature. Access policies should always include a default deny rule. WebSocket applications may require specific tunnel configuration.
|
||||
|
||||
## Output Format
|
||||
|
||||
```
|
||||
Cloudflare Zero Trust Deployment Report
|
||||
==================================================
|
||||
Organization: StartupCorp
|
||||
Team Name: startupcorp
|
||||
Deployment Date: 2026-02-23
|
||||
|
||||
TUNNEL INFRASTRUCTURE:
|
||||
Active Tunnels: 2 (primary + failover)
|
||||
Tunnel Status: Healthy
|
||||
Connected Edge: Washington DC, Ashburn
|
||||
Ingress Routes: 8
|
||||
|
||||
ACCESS APPLICATIONS:
|
||||
Self-Hosted Apps: 6
|
||||
SaaS Apps: 3
|
||||
SSH/Infrastructure: 2
|
||||
Total Policies: 15
|
||||
|
||||
DEVICE ENROLLMENT:
|
||||
Enrolled Devices: 187 / 200
|
||||
WARP Connected: 182 / 187 (97.3%)
|
||||
Posture Compliant: 175 / 187 (93.6%)
|
||||
|
||||
ACCESS METRICS (last 30 days):
|
||||
Total Requests: 89,432
|
||||
Allowed: 88,756 (99.2%)
|
||||
Blocked: 676 (0.8%)
|
||||
Unique Users: 195
|
||||
Countries: 12
|
||||
Avg Session Duration: 6.2 hours
|
||||
```
|
||||
@@ -0,0 +1,55 @@
|
||||
# Cloudflare Access Zero Trust - Deployment Checklist
|
||||
|
||||
## Project Information
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Organization | TechStartup Inc |
|
||||
| Cloudflare Account | CF-XXXXXXX |
|
||||
| Team Name | techstartup |
|
||||
| Plan | Zero Trust Teams (50 seats) |
|
||||
| Start Date | 2026-01-25 |
|
||||
|
||||
## Identity Provider Configuration
|
||||
- [x] Primary IdP: Google Workspace (OIDC)
|
||||
- [x] MFA enforced at IdP level
|
||||
- [ ] Secondary IdP for contractors: GitHub OAuth
|
||||
- [x] Email domain restriction: @techstartup.com
|
||||
|
||||
## Tunnel Deployment
|
||||
|
||||
| Tunnel Name | Server | Network | Routes | Status |
|
||||
|-------------|--------|---------|--------|--------|
|
||||
| prod-tunnel | prod-bastion (10.1.0.5) | Production VPC | wiki, grafana, api | Healthy |
|
||||
| staging-tunnel | staging-bastion (10.2.0.5) | Staging VPC | staging-* | Healthy |
|
||||
|
||||
## Access Applications
|
||||
|
||||
| Application | Type | Domain | Session | Policies | Status |
|
||||
|-------------|------|--------|---------|----------|--------|
|
||||
| Internal Wiki | self_hosted | wiki.techstartup.com | 8h | 2 (Allow Eng, Deny All) | Active |
|
||||
| Grafana | self_hosted | grafana.techstartup.com | 8h | 2 (Allow SRE, Deny All) | Active |
|
||||
| Internal API | self_hosted | api.techstartup.com | 4h | 3 (Allow Backend, Service Token, Deny All) | Active |
|
||||
| Staging Apps | self_hosted | staging.techstartup.com | 4h | 2 (Allow Eng, Deny All) | Active |
|
||||
| SSH Jump | ssh | ssh.techstartup.com | 2h | 1 (Allow SRE) | Active |
|
||||
|
||||
## Device Posture Rules
|
||||
- [x] Disk encryption: Required (Windows BitLocker, macOS FileVault)
|
||||
- [x] OS version: Windows >= 10.0.19045, macOS >= 14.0
|
||||
- [x] Firewall: Enabled
|
||||
- [ ] CrowdStrike integration: Pending deployment
|
||||
|
||||
## WARP Enrollment
|
||||
|
||||
| Platform | Enrolled | Total | Coverage |
|
||||
|----------|----------|-------|----------|
|
||||
| macOS | 32 | 35 | 91.4% |
|
||||
| Windows | 12 | 13 | 92.3% |
|
||||
| Linux | 2 | 2 | 100% |
|
||||
| Total | 46 | 50 | 92.0% |
|
||||
|
||||
## Sign-Off
|
||||
|
||||
| Role | Name | Date | Approved |
|
||||
|------|------|------|----------|
|
||||
| CTO | _________________ | __________ | [ ] |
|
||||
| Security Lead | _________________ | __________ | [ ] |
|
||||
@@ -0,0 +1,33 @@
|
||||
# Cloudflare Access Zero Trust - Standards & References
|
||||
|
||||
## NIST SP 800-207: Zero Trust Architecture
|
||||
- **Section 2**: ZTA Tenets - Cloudflare Access implements per-request identity verification
|
||||
- **Section 3.2**: Enhanced Identity Governance - Access policies enforce continuous authorization
|
||||
- **Section 4.2**: Cloud-Based SDP - Cloudflare Tunnel maps to software-defined perimeter architecture
|
||||
- **URL**: https://csrc.nist.gov/publications/detail/sp/800-207/final
|
||||
|
||||
## CISA Zero Trust Maturity Model v2.0
|
||||
- **Identity**: SSO with MFA via integrated IdP support
|
||||
- **Device**: WARP client posture checks for OS, encryption, EDR
|
||||
- **Network**: Cloudflare Tunnel eliminates inbound firewall rules
|
||||
- **Application**: Per-application Access policies with session controls
|
||||
- **URL**: https://www.cisa.gov/zero-trust-maturity-model
|
||||
|
||||
## Cloudflare Documentation
|
||||
- **Cloudflare One Overview**: https://developers.cloudflare.com/cloudflare-one/
|
||||
- **Cloudflare Access**: https://developers.cloudflare.com/cloudflare-one/policies/access/
|
||||
- **Cloudflare Tunnel**: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/
|
||||
- **WARP Deployment**: https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/
|
||||
- **Device Posture**: https://developers.cloudflare.com/cloudflare-one/identity/devices/
|
||||
- **Logpush**: https://developers.cloudflare.com/logs/about/
|
||||
- **Zero Trust Reference Architecture**: https://developers.cloudflare.com/reference-architecture/implementation-guides/zero-trust/
|
||||
|
||||
## SOC 2 Type II
|
||||
- Cloudflare maintains SOC 2 Type II certification
|
||||
- Access audit logs provide evidence for CC6.1 (Logical Access), CC6.3 (Role-Based Access)
|
||||
- **URL**: https://www.cloudflare.com/trust-hub/compliance-resources/
|
||||
|
||||
## GDPR
|
||||
- Cloudflare processes data per EU GDPR requirements
|
||||
- Data localization options for EU-based traffic
|
||||
- **URL**: https://www.cloudflare.com/trust-hub/gdpr/
|
||||
@@ -0,0 +1,65 @@
|
||||
# Cloudflare Access Zero Trust Deployment Workflow
|
||||
|
||||
## Phase 1: Account Setup (Day 1)
|
||||
|
||||
1. Create Cloudflare account and navigate to Zero Trust dashboard
|
||||
2. Select team name (organization identifier for WARP enrollment)
|
||||
3. Choose subscription plan based on user count
|
||||
4. Configure authentication: add primary IdP (Okta, Entra ID, Google Workspace)
|
||||
5. Add secondary IdP for contractors or partners if needed
|
||||
6. Enable MFA requirements at the IdP level
|
||||
|
||||
## Phase 2: Tunnel Deployment (Day 2-3)
|
||||
|
||||
### 2.1 Install cloudflared
|
||||
1. Install `cloudflared` on a server within the private network
|
||||
2. Authenticate with `cloudflared tunnel login`
|
||||
3. Create named tunnel: `cloudflared tunnel create <name>`
|
||||
4. Configure ingress rules in `config.yml` mapping hostnames to internal services
|
||||
5. Route DNS: `cloudflared tunnel route dns <tunnel> <hostname>`
|
||||
|
||||
### 2.2 High Availability
|
||||
1. Deploy multiple `cloudflared` instances for redundancy
|
||||
2. Use `cloudflared tunnel run --protocol quic` for better performance
|
||||
3. Configure systemd service for automatic restart
|
||||
4. Monitor tunnel health via Cloudflare dashboard
|
||||
|
||||
### 2.3 Private Network Routing
|
||||
1. Add private network routes: `cloudflared tunnel route ip add 10.0.0.0/8 <tunnel-id>`
|
||||
2. Configure split tunnel in WARP device settings
|
||||
3. Set up DNS fallback domains for private DNS resolution
|
||||
|
||||
## Phase 3: Access Application Configuration (Day 4-5)
|
||||
|
||||
1. Create Access applications for each internal service
|
||||
2. Define access policies per application:
|
||||
- Include rules: email domains, IdP groups, service tokens
|
||||
- Require rules: device posture, country restrictions
|
||||
- Exclude rules: specific users or IPs
|
||||
3. Configure session duration per application sensitivity
|
||||
4. Enable purpose justification for sensitive applications
|
||||
5. Test access with pilot users
|
||||
|
||||
## Phase 4: WARP Client Deployment (Week 2)
|
||||
|
||||
1. Create device enrollment policies with email domain restrictions
|
||||
2. Deploy WARP client via MDM (Intune, Jamf, SCCM)
|
||||
3. Install Cloudflare root certificate for TLS inspection
|
||||
4. Configure split tunnel settings for private network access
|
||||
5. Enable device posture checks: OS version, disk encryption, firewall
|
||||
|
||||
## Phase 5: Gateway and DLP Configuration (Week 3)
|
||||
|
||||
1. Enable DNS filtering with block categories (malware, phishing)
|
||||
2. Configure HTTP inspection policies
|
||||
3. Set up DLP profiles for sensitive data detection
|
||||
4. Enable browser isolation for high-risk web categories
|
||||
5. Configure CASB for SaaS application monitoring
|
||||
|
||||
## Phase 6: Monitoring and Optimization (Ongoing)
|
||||
|
||||
1. Enable Logpush to SIEM (S3, Splunk, Datadog)
|
||||
2. Monitor Access audit logs for denied requests
|
||||
3. Review tunnel health metrics
|
||||
4. Optimize split tunnel configuration
|
||||
5. Conduct quarterly access policy reviews
|
||||
@@ -0,0 +1,246 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Cloudflare Access Zero Trust - Deployment Audit Tool
|
||||
|
||||
Queries Cloudflare API to audit Access applications, policies, tunnel
|
||||
health, and device enrollment for zero trust compliance validation.
|
||||
|
||||
Requirements:
|
||||
pip install requests
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
import requests
|
||||
|
||||
CF_API_BASE = "https://api.cloudflare.com/client/v4"
|
||||
|
||||
|
||||
class CloudflareAccessAuditor:
|
||||
"""Audit Cloudflare Zero Trust Access deployment."""
|
||||
|
||||
def __init__(self, api_token: str, account_id: str):
|
||||
self.api_token = api_token
|
||||
self.account_id = account_id
|
||||
self.headers = {
|
||||
"Authorization": f"Bearer {api_token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
def _get(self, endpoint: str, params: dict = None) -> dict:
|
||||
"""Make authenticated GET request."""
|
||||
url = f"{CF_API_BASE}/accounts/{self.account_id}/{endpoint}"
|
||||
resp = requests.get(url, headers=self.headers, params=params or {}, timeout=30)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def audit_access_applications(self) -> dict[str, Any]:
|
||||
"""Audit all Access applications and their configurations."""
|
||||
print("\n[1/5] Auditing Access Applications...")
|
||||
data = self._get("access/apps")
|
||||
apps = data.get("result", [])
|
||||
|
||||
stats = {
|
||||
"total": len(apps),
|
||||
"self_hosted": 0,
|
||||
"saas": 0,
|
||||
"ssh": 0,
|
||||
"vnc": 0,
|
||||
"without_policies": 0,
|
||||
"session_durations": {},
|
||||
"apps": []
|
||||
}
|
||||
|
||||
for app in apps:
|
||||
app_type = app.get("type", "unknown")
|
||||
name = app.get("name", "unknown")
|
||||
domain = app.get("domain", "N/A")
|
||||
session = app.get("session_duration", "24h")
|
||||
policies_count = len(app.get("policies", []))
|
||||
|
||||
if app_type == "self_hosted":
|
||||
stats["self_hosted"] += 1
|
||||
elif app_type == "saas":
|
||||
stats["saas"] += 1
|
||||
elif app_type == "ssh":
|
||||
stats["ssh"] += 1
|
||||
elif app_type == "vnc":
|
||||
stats["vnc"] += 1
|
||||
|
||||
if policies_count == 0:
|
||||
stats["without_policies"] += 1
|
||||
print(f" [WARN] App '{name}' has no access policies!")
|
||||
|
||||
stats["session_durations"][session] = stats["session_durations"].get(session, 0) + 1
|
||||
stats["apps"].append({
|
||||
"name": name, "type": app_type, "domain": domain,
|
||||
"session": session, "policies": policies_count
|
||||
})
|
||||
print(f" [{app_type.upper()}] {name} ({domain}) - {policies_count} policies, session: {session}")
|
||||
|
||||
return stats
|
||||
|
||||
def audit_tunnels(self) -> dict[str, Any]:
|
||||
"""Audit Cloudflare Tunnel health and configuration."""
|
||||
print("\n[2/5] Auditing Cloudflare Tunnels...")
|
||||
data = self._get("cfd_tunnel", params={"is_deleted": "false"})
|
||||
tunnels = data.get("result", [])
|
||||
|
||||
stats = {
|
||||
"total": len(tunnels),
|
||||
"healthy": 0,
|
||||
"degraded": 0,
|
||||
"inactive": 0,
|
||||
"tunnels": []
|
||||
}
|
||||
|
||||
for tunnel in tunnels:
|
||||
name = tunnel.get("name", "unknown")
|
||||
status = tunnel.get("status", "unknown")
|
||||
connections = tunnel.get("connections", [])
|
||||
created = tunnel.get("created_at", "")
|
||||
|
||||
if status == "healthy":
|
||||
stats["healthy"] += 1
|
||||
elif status == "degraded":
|
||||
stats["degraded"] += 1
|
||||
print(f" [WARN] Tunnel '{name}' is degraded")
|
||||
else:
|
||||
stats["inactive"] += 1
|
||||
print(f" [WARN] Tunnel '{name}' is inactive")
|
||||
|
||||
stats["tunnels"].append({
|
||||
"name": name, "status": status,
|
||||
"connections": len(connections), "created": created
|
||||
})
|
||||
|
||||
print(f" Total: {stats['total']}, Healthy: {stats['healthy']}, "
|
||||
f"Degraded: {stats['degraded']}, Inactive: {stats['inactive']}")
|
||||
return stats
|
||||
|
||||
def audit_device_posture(self) -> dict[str, Any]:
|
||||
"""Audit device posture rules configuration."""
|
||||
print("\n[3/5] Auditing Device Posture Rules...")
|
||||
data = self._get("devices/posture")
|
||||
rules = data.get("result", [])
|
||||
|
||||
stats = {
|
||||
"total": len(rules),
|
||||
"types": {},
|
||||
"rules": []
|
||||
}
|
||||
|
||||
for rule in rules:
|
||||
name = rule.get("name", "unknown")
|
||||
rule_type = rule.get("type", "unknown")
|
||||
stats["types"][rule_type] = stats["types"].get(rule_type, 0) + 1
|
||||
stats["rules"].append({"name": name, "type": rule_type})
|
||||
print(f" [{rule_type}] {name}")
|
||||
|
||||
required_types = {"disk_encryption", "os_version", "firewall"}
|
||||
missing = required_types - set(stats["types"].keys())
|
||||
if missing:
|
||||
print(f" [WARN] Missing recommended posture types: {missing}")
|
||||
|
||||
return stats
|
||||
|
||||
def audit_device_enrollment(self) -> dict[str, Any]:
|
||||
"""Audit enrolled devices."""
|
||||
print("\n[4/5] Auditing Device Enrollment...")
|
||||
data = self._get("devices")
|
||||
devices = data.get("result", [])
|
||||
|
||||
stats = {
|
||||
"total": len(devices),
|
||||
"os_distribution": {},
|
||||
"active": 0,
|
||||
"revoked": 0
|
||||
}
|
||||
|
||||
for device in devices:
|
||||
os_type = device.get("os_version", "unknown").split(" ")[0] if device.get("os_version") else "unknown"
|
||||
stats["os_distribution"][os_type] = stats["os_distribution"].get(os_type, 0) + 1
|
||||
if device.get("revoked_at"):
|
||||
stats["revoked"] += 1
|
||||
else:
|
||||
stats["active"] += 1
|
||||
|
||||
print(f" Total: {stats['total']}, Active: {stats['active']}, Revoked: {stats['revoked']}")
|
||||
print(f" OS Distribution: {stats['os_distribution']}")
|
||||
return stats
|
||||
|
||||
def generate_report(self, apps, tunnels, posture, devices) -> str:
|
||||
"""Generate comprehensive audit report."""
|
||||
print("\n[5/5] Generating report...")
|
||||
now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
|
||||
|
||||
report = f"""
|
||||
Cloudflare Zero Trust Access Audit Report
|
||||
{'=' * 55}
|
||||
Account: {self.account_id}
|
||||
Generated: {now}
|
||||
|
||||
1. ACCESS APPLICATIONS
|
||||
Total applications: {apps['total']}
|
||||
Self-hosted: {apps['self_hosted']}
|
||||
SaaS: {apps['saas']}
|
||||
SSH/Infrastructure: {apps['ssh']}
|
||||
Without policies: {apps['without_policies']}
|
||||
Session durations: {apps['session_durations']}
|
||||
|
||||
2. TUNNEL INFRASTRUCTURE
|
||||
Total tunnels: {tunnels['total']}
|
||||
Healthy: {tunnels['healthy']}
|
||||
Degraded: {tunnels['degraded']}
|
||||
Inactive: {tunnels['inactive']}
|
||||
|
||||
3. DEVICE POSTURE
|
||||
Posture rules defined: {posture['total']}
|
||||
Rule types: {posture['types']}
|
||||
|
||||
4. DEVICE ENROLLMENT
|
||||
Total devices: {devices['total']}
|
||||
Active: {devices['active']}
|
||||
Revoked: {devices['revoked']}
|
||||
|
||||
5. RECOMMENDATIONS
|
||||
"""
|
||||
recs = []
|
||||
if apps['without_policies'] > 0:
|
||||
recs.append(f" - {apps['without_policies']} app(s) without policies - add access rules immediately")
|
||||
if tunnels['degraded'] > 0 or tunnels['inactive'] > 0:
|
||||
recs.append(f" - {tunnels['degraded'] + tunnels['inactive']} tunnel(s) need attention")
|
||||
if "disk_encryption" not in posture.get("types", {}):
|
||||
recs.append(" - Add disk encryption posture rule")
|
||||
if "os_version" not in posture.get("types", {}):
|
||||
recs.append(" - Add OS version posture rule")
|
||||
if not recs:
|
||||
recs.append(" - No critical issues found")
|
||||
report += "\n".join(recs)
|
||||
return report
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: python process.py <cf_api_token> <account_id>")
|
||||
sys.exit(1)
|
||||
|
||||
auditor = CloudflareAccessAuditor(sys.argv[1], sys.argv[2])
|
||||
apps = auditor.audit_access_applications()
|
||||
tunnels = auditor.audit_tunnels()
|
||||
posture = auditor.audit_device_posture()
|
||||
devices = auditor.audit_device_enrollment()
|
||||
report = auditor.generate_report(apps, tunnels, posture, devices)
|
||||
print(report)
|
||||
|
||||
filename = f"cloudflare_zt_audit_{datetime.now().strftime('%Y%m%d')}.txt"
|
||||
with open(filename, "w") as f:
|
||||
f.write(report)
|
||||
print(f"\nReport saved to: {filename}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user