Initial Phoenix Sankofa Cloud setup
- Complete project structure with Next.js frontend - GraphQL API backend with Apollo Server - Portal application with NextAuth - Crossplane Proxmox provider - GitOps configurations - CI/CD pipelines - Testing infrastructure (Vitest, Jest, Go tests) - Error handling and monitoring - Security hardening - UI component library - Documentation
This commit is contained in:
84
cloudflare/README.md
Normal file
84
cloudflare/README.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# Cloudflare Zero Trust Configuration
|
||||
|
||||
This directory contains all Cloudflare Zero Trust configurations for secure global access to the hybrid cloud control plane.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
cloudflare/
|
||||
├── access-policies.yaml # Access policies for applications
|
||||
├── tunnel-configs/ # Per-site tunnel configurations
|
||||
├── gateway-policies.yaml # DNS and filtering policies
|
||||
├── warp-config.json # WARP device enrollment
|
||||
└── terraform/ # Terraform modules for Cloudflare
|
||||
```
|
||||
|
||||
## Components
|
||||
|
||||
### Access Policies
|
||||
Define who can access which applications based on:
|
||||
- User identity (from Keycloak)
|
||||
- Device posture
|
||||
- IP address
|
||||
- MFA requirements
|
||||
- Time-based rules
|
||||
|
||||
### Tunnels
|
||||
Outbound-only connections from Proxmox sites and control plane to Cloudflare:
|
||||
- No public IPs required
|
||||
- Automatic reconnection
|
||||
- Load balancing across multiple tunnels
|
||||
- Health checks
|
||||
|
||||
### Gateway Policies
|
||||
DNS filtering and network security:
|
||||
- Block malicious domains
|
||||
- Log DNS queries
|
||||
- Apply policies based on user/device
|
||||
- Split DNS for internal services
|
||||
|
||||
### WARP
|
||||
Device-level VPN for employees:
|
||||
- Zero Trust network access
|
||||
- Device posture checks
|
||||
- Automatic enrollment
|
||||
|
||||
## Usage
|
||||
|
||||
### Apply Access Policies
|
||||
|
||||
```bash
|
||||
# Using Cloudflare API
|
||||
cloudflared access policy create --config access-policies.yaml
|
||||
|
||||
# Or via Terraform
|
||||
cd terraform
|
||||
terraform apply
|
||||
```
|
||||
|
||||
### Deploy Tunnels
|
||||
|
||||
1. Create tunnel in Cloudflare dashboard
|
||||
2. Copy tunnel token
|
||||
3. Update tunnel config with token
|
||||
4. Deploy cloudflared agent with config
|
||||
|
||||
```bash
|
||||
cloudflared tunnel run --config tunnel-configs/site-1.yaml
|
||||
```
|
||||
|
||||
### Configure WARP
|
||||
|
||||
1. Create WARP enrollment in Cloudflare dashboard
|
||||
2. Update warp-config.json with enrollment details
|
||||
3. Distribute config to devices
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
- Use service tokens for API access
|
||||
- Rotate tunnel tokens regularly
|
||||
- Enable MFA for all access policies
|
||||
- Use device posture checks
|
||||
- Log all access attempts
|
||||
- Review policies quarterly
|
||||
|
||||
263
cloudflare/access-policies.yaml
Normal file
263
cloudflare/access-policies.yaml
Normal file
@@ -0,0 +1,263 @@
|
||||
# Cloudflare Zero Trust Access Policies
|
||||
# These policies control who can access which applications
|
||||
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cloudflare-access-policies
|
||||
namespace: default
|
||||
data:
|
||||
# Portal Access Policy
|
||||
portal-policy: |
|
||||
{
|
||||
"name": "Portal Access",
|
||||
"application": {
|
||||
"domain": "portal.yourdomain.com",
|
||||
"name": "Hybrid Cloud Portal"
|
||||
},
|
||||
"policies": [
|
||||
{
|
||||
"name": "Allow Authenticated Users",
|
||||
"decision": "allow",
|
||||
"include": [
|
||||
{
|
||||
"email": {
|
||||
"domain": "yourdomain.com"
|
||||
}
|
||||
}
|
||||
],
|
||||
"require": [
|
||||
{
|
||||
"email": {
|
||||
"domain": "yourdomain.com"
|
||||
}
|
||||
}
|
||||
],
|
||||
"session_duration": "24h"
|
||||
},
|
||||
{
|
||||
"name": "Require MFA for Admins",
|
||||
"decision": "allow",
|
||||
"include": [
|
||||
{
|
||||
"group": {
|
||||
"name": "admins"
|
||||
}
|
||||
}
|
||||
],
|
||||
"require": [
|
||||
{
|
||||
"mfa": {}
|
||||
}
|
||||
],
|
||||
"session_duration": "8h"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Rancher Access Policy
|
||||
rancher-policy: |
|
||||
{
|
||||
"name": "Rancher Access",
|
||||
"application": {
|
||||
"domain": "rancher.yourdomain.com",
|
||||
"name": "Rancher UI"
|
||||
},
|
||||
"policies": [
|
||||
{
|
||||
"name": "Allow Admin Group",
|
||||
"decision": "allow",
|
||||
"include": [
|
||||
{
|
||||
"group": {
|
||||
"name": "admins"
|
||||
}
|
||||
},
|
||||
{
|
||||
"group": {
|
||||
"name": "platform-engineers"
|
||||
}
|
||||
}
|
||||
],
|
||||
"require": [
|
||||
{
|
||||
"mfa": {}
|
||||
},
|
||||
{
|
||||
"device_posture": {
|
||||
"check": "managed_device"
|
||||
}
|
||||
}
|
||||
],
|
||||
"session_duration": "4h"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# ArgoCD Access Policy
|
||||
argocd-policy: |
|
||||
{
|
||||
"name": "ArgoCD Access",
|
||||
"application": {
|
||||
"domain": "argocd.yourdomain.com",
|
||||
"name": "ArgoCD GitOps"
|
||||
},
|
||||
"policies": [
|
||||
{
|
||||
"name": "Allow Platform Engineers",
|
||||
"decision": "allow",
|
||||
"include": [
|
||||
{
|
||||
"group": {
|
||||
"name": "platform-engineers"
|
||||
}
|
||||
},
|
||||
{
|
||||
"group": {
|
||||
"name": "admins"
|
||||
}
|
||||
}
|
||||
],
|
||||
"require": [
|
||||
{
|
||||
"mfa": {}
|
||||
}
|
||||
],
|
||||
"session_duration": "8h"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Grafana Access Policy
|
||||
grafana-policy: |
|
||||
{
|
||||
"name": "Grafana Access",
|
||||
"application": {
|
||||
"domain": "grafana.yourdomain.com",
|
||||
"name": "Grafana Dashboards"
|
||||
},
|
||||
"policies": [
|
||||
{
|
||||
"name": "Allow All Authenticated",
|
||||
"decision": "allow",
|
||||
"include": [
|
||||
{
|
||||
"email": {
|
||||
"domain": "yourdomain.com"
|
||||
}
|
||||
}
|
||||
],
|
||||
"session_duration": "24h"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Vault Access Policy
|
||||
vault-policy: |
|
||||
{
|
||||
"name": "Vault Access",
|
||||
"application": {
|
||||
"domain": "vault.yourdomain.com",
|
||||
"name": "HashiCorp Vault"
|
||||
},
|
||||
"policies": [
|
||||
{
|
||||
"name": "Allow Admin Group Only",
|
||||
"decision": "allow",
|
||||
"include": [
|
||||
{
|
||||
"group": {
|
||||
"name": "admins"
|
||||
}
|
||||
}
|
||||
],
|
||||
"require": [
|
||||
{
|
||||
"mfa": {}
|
||||
},
|
||||
{
|
||||
"device_posture": {
|
||||
"check": "managed_device"
|
||||
}
|
||||
}
|
||||
],
|
||||
"session_duration": "2h"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Proxmox API Access Policy
|
||||
proxmox-api-policy: |
|
||||
{
|
||||
"name": "Proxmox API Access",
|
||||
"application": {
|
||||
"domain": "proxmox-api.yourdomain.com",
|
||||
"name": "Proxmox API"
|
||||
},
|
||||
"policies": [
|
||||
{
|
||||
"name": "Allow Service Accounts",
|
||||
"decision": "allow",
|
||||
"include": [
|
||||
{
|
||||
"service_token": {
|
||||
"name": "crossplane-proxmox-token"
|
||||
}
|
||||
}
|
||||
],
|
||||
"session_duration": "1h"
|
||||
},
|
||||
{
|
||||
"name": "Allow Platform Engineers",
|
||||
"decision": "allow",
|
||||
"include": [
|
||||
{
|
||||
"group": {
|
||||
"name": "platform-engineers"
|
||||
}
|
||||
}
|
||||
],
|
||||
"require": [
|
||||
{
|
||||
"mfa": {}
|
||||
}
|
||||
],
|
||||
"session_duration": "4h"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Keycloak Access Policy
|
||||
keycloak-policy: |
|
||||
{
|
||||
"name": "Keycloak Access",
|
||||
"application": {
|
||||
"domain": "keycloak.yourdomain.com",
|
||||
"name": "Keycloak Admin"
|
||||
},
|
||||
"policies": [
|
||||
{
|
||||
"name": "Allow Admin Group Only",
|
||||
"decision": "allow",
|
||||
"include": [
|
||||
{
|
||||
"group": {
|
||||
"name": "admins"
|
||||
}
|
||||
}
|
||||
],
|
||||
"require": [
|
||||
{
|
||||
"mfa": {}
|
||||
},
|
||||
{
|
||||
"device_posture": {
|
||||
"check": "managed_device"
|
||||
}
|
||||
}
|
||||
],
|
||||
"session_duration": "2h"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
149
cloudflare/gateway-policies.yaml
Normal file
149
cloudflare/gateway-policies.yaml
Normal file
@@ -0,0 +1,149 @@
|
||||
# Cloudflare Gateway Policies
|
||||
# DNS filtering and network security policies
|
||||
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cloudflare-gateway-policies
|
||||
namespace: default
|
||||
data:
|
||||
# DNS Policies
|
||||
dns-policies: |
|
||||
{
|
||||
"policies": [
|
||||
{
|
||||
"name": "Block Malicious Domains",
|
||||
"action": "block",
|
||||
"precedence": 1,
|
||||
"filters": [
|
||||
{
|
||||
"type": "dns",
|
||||
"categories": [
|
||||
"malware",
|
||||
"phishing",
|
||||
"command-and-control",
|
||||
"ransomware",
|
||||
"spyware"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Block Adult Content",
|
||||
"action": "block",
|
||||
"precedence": 2,
|
||||
"filters": [
|
||||
{
|
||||
"type": "dns",
|
||||
"categories": [
|
||||
"adult"
|
||||
]
|
||||
}
|
||||
],
|
||||
"identity": {
|
||||
"groups": [
|
||||
{
|
||||
"name": "employees"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Allow All for Admins",
|
||||
"action": "allow",
|
||||
"precedence": 100,
|
||||
"identity": {
|
||||
"groups": [
|
||||
{
|
||||
"name": "admins"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Network Policies
|
||||
network-policies: |
|
||||
{
|
||||
"policies": [
|
||||
{
|
||||
"name": "Block High Risk Ports",
|
||||
"action": "block",
|
||||
"precedence": 1,
|
||||
"rules": [
|
||||
{
|
||||
"protocol": "tcp",
|
||||
"ports": [
|
||||
"22",
|
||||
"23",
|
||||
"135",
|
||||
"139",
|
||||
"445",
|
||||
"1433",
|
||||
"3306",
|
||||
"3389",
|
||||
"5432"
|
||||
]
|
||||
}
|
||||
],
|
||||
"identity": {
|
||||
"groups": [
|
||||
{
|
||||
"name": "employees"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Allow Admin Access",
|
||||
"action": "allow",
|
||||
"precedence": 100,
|
||||
"identity": {
|
||||
"groups": [
|
||||
{
|
||||
"name": "admins"
|
||||
},
|
||||
{
|
||||
"name": "platform-engineers"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Logging Configuration
|
||||
logging-config: |
|
||||
{
|
||||
"dns": {
|
||||
"enabled": true,
|
||||
"log_all": true,
|
||||
"log_blocks": true
|
||||
},
|
||||
"network": {
|
||||
"enabled": true,
|
||||
"log_all": true,
|
||||
"log_blocks": true
|
||||
},
|
||||
"retention": {
|
||||
"days": 30
|
||||
}
|
||||
}
|
||||
|
||||
# Split DNS Configuration
|
||||
split-dns: |
|
||||
{
|
||||
"domains": [
|
||||
"yourdomain.com",
|
||||
"*.yourdomain.com",
|
||||
"*.svc.cluster.local",
|
||||
"*.local"
|
||||
],
|
||||
"dns_servers": [
|
||||
"10.0.0.53",
|
||||
"10.1.0.53",
|
||||
"10.2.0.53"
|
||||
]
|
||||
}
|
||||
|
||||
13
cloudflare/terraform/.gitignore
vendored
Normal file
13
cloudflare/terraform/.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# Terraform files
|
||||
*.tfstate
|
||||
*.tfstate.*
|
||||
.terraform/
|
||||
.terraform.lock.hcl
|
||||
terraform.tfvars
|
||||
*.tfvars
|
||||
crash.log
|
||||
override.tf
|
||||
override.tf.json
|
||||
*_override.tf
|
||||
*_override.tf.json
|
||||
|
||||
250
cloudflare/terraform/main.tf
Normal file
250
cloudflare/terraform/main.tf
Normal file
@@ -0,0 +1,250 @@
|
||||
terraform {
|
||||
required_version = ">= 1.0"
|
||||
|
||||
required_providers {
|
||||
cloudflare = {
|
||||
source = "cloudflare/cloudflare"
|
||||
version = "~> 4.0"
|
||||
}
|
||||
}
|
||||
|
||||
backend "s3" {
|
||||
# Configure your backend here
|
||||
# bucket = "your-terraform-state"
|
||||
# key = "cloudflare/terraform.tfstate"
|
||||
# region = "us-east-1"
|
||||
}
|
||||
}
|
||||
|
||||
provider "cloudflare" {
|
||||
api_token = var.cloudflare_api_token
|
||||
}
|
||||
|
||||
# Variables
|
||||
variable "cloudflare_api_token" {
|
||||
description = "Cloudflare API token"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "zone_id" {
|
||||
description = "Cloudflare Zone ID"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "account_id" {
|
||||
description = "Cloudflare Account ID"
|
||||
type = string
|
||||
}
|
||||
|
||||
# Access Applications
|
||||
resource "cloudflare_access_application" "portal" {
|
||||
zone_id = var.zone_id
|
||||
name = "Hybrid Cloud Portal"
|
||||
domain = "portal.yourdomain.com"
|
||||
session_duration = "24h"
|
||||
|
||||
cors_headers {
|
||||
allowed_methods = ["GET", "POST", "PUT", "DELETE"]
|
||||
allowed_origins = ["https://portal.yourdomain.com"]
|
||||
allow_credentials = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "cloudflare_access_application" "rancher" {
|
||||
zone_id = var.zone_id
|
||||
name = "Rancher UI"
|
||||
domain = "rancher.yourdomain.com"
|
||||
session_duration = "4h"
|
||||
}
|
||||
|
||||
resource "cloudflare_access_application" "argocd" {
|
||||
zone_id = var.zone_id
|
||||
name = "ArgoCD GitOps"
|
||||
domain = "argocd.yourdomain.com"
|
||||
session_duration = "8h"
|
||||
}
|
||||
|
||||
resource "cloudflare_access_application" "grafana" {
|
||||
zone_id = var.zone_id
|
||||
name = "Grafana Dashboards"
|
||||
domain = "grafana.yourdomain.com"
|
||||
session_duration = "24h"
|
||||
}
|
||||
|
||||
resource "cloudflare_access_application" "vault" {
|
||||
zone_id = var.zone_id
|
||||
name = "HashiCorp Vault"
|
||||
domain = "vault.yourdomain.com"
|
||||
session_duration = "2h"
|
||||
}
|
||||
|
||||
resource "cloudflare_access_application" "keycloak" {
|
||||
zone_id = var.zone_id
|
||||
name = "Keycloak Admin"
|
||||
domain = "keycloak.yourdomain.com"
|
||||
session_duration = "2h"
|
||||
}
|
||||
|
||||
# Access Policies
|
||||
resource "cloudflare_access_policy" "portal_authenticated" {
|
||||
application_id = cloudflare_access_application.portal.id
|
||||
zone_id = var.zone_id
|
||||
name = "Allow Authenticated Users"
|
||||
decision = "allow"
|
||||
precedence = 1
|
||||
|
||||
include {
|
||||
email_domain = "yourdomain.com"
|
||||
}
|
||||
}
|
||||
|
||||
resource "cloudflare_access_policy" "portal_admin_mfa" {
|
||||
application_id = cloudflare_access_application.portal.id
|
||||
zone_id = var.zone_id
|
||||
name = "Require MFA for Admins"
|
||||
decision = "allow"
|
||||
precedence = 2
|
||||
|
||||
include {
|
||||
group = cloudflare_access_group.admins.id
|
||||
}
|
||||
|
||||
require {
|
||||
mfa = true
|
||||
}
|
||||
}
|
||||
|
||||
# Access Groups
|
||||
resource "cloudflare_access_group" "admins" {
|
||||
account_id = var.account_id
|
||||
name = "admins"
|
||||
|
||||
include {
|
||||
email_domain = "yourdomain.com"
|
||||
}
|
||||
|
||||
require {
|
||||
email = ["admin@yourdomain.com"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "cloudflare_access_group" "platform_engineers" {
|
||||
account_id = var.account_id
|
||||
name = "platform-engineers"
|
||||
|
||||
include {
|
||||
email_domain = "yourdomain.com"
|
||||
}
|
||||
}
|
||||
|
||||
resource "cloudflare_access_group" "employees" {
|
||||
account_id = var.account_id
|
||||
name = "employees"
|
||||
|
||||
include {
|
||||
email_domain = "yourdomain.com"
|
||||
}
|
||||
}
|
||||
|
||||
# Tunnels
|
||||
resource "cloudflare_tunnel" "control_plane" {
|
||||
account_id = var.account_id
|
||||
name = "control-plane-tunnel"
|
||||
secret = var.tunnel_secret_control_plane
|
||||
}
|
||||
|
||||
resource "cloudflare_tunnel" "proxmox_site_1" {
|
||||
account_id = var.account_id
|
||||
name = "proxmox-site-1-tunnel"
|
||||
secret = var.tunnel_secret_site_1
|
||||
}
|
||||
|
||||
resource "cloudflare_tunnel" "proxmox_site_2" {
|
||||
account_id = var.account_id
|
||||
name = "proxmox-site-2-tunnel"
|
||||
secret = var.tunnel_secret_site_2
|
||||
}
|
||||
|
||||
resource "cloudflare_tunnel" "proxmox_site_3" {
|
||||
account_id = var.account_id
|
||||
name = "proxmox-site-3-tunnel"
|
||||
secret = var.tunnel_secret_site_3
|
||||
}
|
||||
|
||||
# Tunnel Routes
|
||||
resource "cloudflare_tunnel_route" "control_plane" {
|
||||
account_id = var.account_id
|
||||
tunnel_id = cloudflare_tunnel.control_plane.id
|
||||
network = "10.0.0.0/16"
|
||||
comment = "Control plane network"
|
||||
}
|
||||
|
||||
resource "cloudflare_tunnel_route" "site_1" {
|
||||
account_id = var.account_id
|
||||
tunnel_id = cloudflare_tunnel.proxmox_site_1.id
|
||||
network = "10.1.0.0/16"
|
||||
comment = "Proxmox site 1 network"
|
||||
}
|
||||
|
||||
resource "cloudflare_tunnel_route" "site_2" {
|
||||
account_id = var.account_id
|
||||
tunnel_id = cloudflare_tunnel.proxmox_site_2.id
|
||||
network = "10.2.0.0/16"
|
||||
comment = "Proxmox site 2 network"
|
||||
}
|
||||
|
||||
resource "cloudflare_tunnel_route" "site_3" {
|
||||
account_id = var.account_id
|
||||
tunnel_id = cloudflare_tunnel.proxmox_site_3.id
|
||||
network = "10.3.0.0/16"
|
||||
comment = "Proxmox site 3 network"
|
||||
}
|
||||
|
||||
# Gateway Policies
|
||||
resource "cloudflare_teams_list" "blocked_domains" {
|
||||
account_id = var.account_id
|
||||
name = "Blocked Domains"
|
||||
type = "DOMAIN"
|
||||
items = [
|
||||
"malware.example.com",
|
||||
"phishing.example.com"
|
||||
]
|
||||
}
|
||||
|
||||
resource "cloudflare_teams_rule" "block_malicious" {
|
||||
account_id = var.account_id
|
||||
name = "Block Malicious Domains"
|
||||
description = "Block known malicious domains"
|
||||
precedence = 1
|
||||
action = "block"
|
||||
|
||||
filters = ["dns"]
|
||||
|
||||
rule_settings {
|
||||
block_page_enabled = true
|
||||
block_reason = "This domain is blocked by security policy"
|
||||
}
|
||||
}
|
||||
|
||||
# Outputs
|
||||
output "tunnel_ids" {
|
||||
value = {
|
||||
control_plane = cloudflare_tunnel.control_plane.id
|
||||
site_1 = cloudflare_tunnel.proxmox_site_1.id
|
||||
site_2 = cloudflare_tunnel.proxmox_site_2.id
|
||||
site_3 = cloudflare_tunnel.proxmox_site_3.id
|
||||
}
|
||||
}
|
||||
|
||||
output "application_ids" {
|
||||
value = {
|
||||
portal = cloudflare_access_application.portal.id
|
||||
rancher = cloudflare_access_application.rancher.id
|
||||
argocd = cloudflare_access_application.argocd.id
|
||||
grafana = cloudflare_access_application.grafana.id
|
||||
vault = cloudflare_access_application.vault.id
|
||||
keycloak = cloudflare_access_application.keycloak.id
|
||||
}
|
||||
}
|
||||
|
||||
13
cloudflare/terraform/terraform.tfvars.example
Normal file
13
cloudflare/terraform/terraform.tfvars.example
Normal file
@@ -0,0 +1,13 @@
|
||||
# Copy this file to terraform.tfvars and fill in your values
|
||||
# terraform.tfvars should be in .gitignore
|
||||
|
||||
cloudflare_api_token = "your-cloudflare-api-token"
|
||||
zone_id = "your-zone-id"
|
||||
account_id = "your-account-id"
|
||||
|
||||
# Generate secrets with: openssl rand -base64 32
|
||||
tunnel_secret_control_plane = "your-control-plane-tunnel-secret"
|
||||
tunnel_secret_site_1 = "your-site-1-tunnel-secret"
|
||||
tunnel_secret_site_2 = "your-site-2-tunnel-secret"
|
||||
tunnel_secret_site_3 = "your-site-3-tunnel-secret"
|
||||
|
||||
40
cloudflare/terraform/variables.tf
Normal file
40
cloudflare/terraform/variables.tf
Normal file
@@ -0,0 +1,40 @@
|
||||
variable "cloudflare_api_token" {
|
||||
description = "Cloudflare API token with appropriate permissions"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "zone_id" {
|
||||
description = "Cloudflare Zone ID for yourdomain.com"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "account_id" {
|
||||
description = "Cloudflare Account ID"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "tunnel_secret_control_plane" {
|
||||
description = "Secret for control plane tunnel (generate with: openssl rand -base64 32)"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "tunnel_secret_site_1" {
|
||||
description = "Secret for Proxmox site 1 tunnel"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "tunnel_secret_site_2" {
|
||||
description = "Secret for Proxmox site 2 tunnel"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "tunnel_secret_site_3" {
|
||||
description = "Secret for Proxmox site 3 tunnel"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
77
cloudflare/tunnel-configs/control-plane.yaml
Normal file
77
cloudflare/tunnel-configs/control-plane.yaml
Normal file
@@ -0,0 +1,77 @@
|
||||
# Cloudflare Tunnel Configuration for Control Plane
|
||||
# This tunnel connects the Kubernetes control plane to Cloudflare
|
||||
|
||||
tunnel: control-plane-tunnel
|
||||
credentials-file: /etc/cloudflared/control-plane-tunnel.json
|
||||
|
||||
ingress:
|
||||
# Portal
|
||||
- hostname: portal.yourdomain.com
|
||||
service: http://portal.portal.svc.cluster.local:80
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
tcpKeepAlive: 30s
|
||||
keepAliveConnections: 100
|
||||
keepAliveTimeout: 90s
|
||||
|
||||
# Rancher
|
||||
- hostname: rancher.yourdomain.com
|
||||
service: http://rancher.rancher-system.svc.cluster.local:80
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
|
||||
# ArgoCD
|
||||
- hostname: argocd.yourdomain.com
|
||||
service: http://argocd-server.argocd.svc.cluster.local:80
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
|
||||
# Grafana
|
||||
- hostname: grafana.yourdomain.com
|
||||
service: http://kube-prometheus-stack-grafana.monitoring.svc.cluster.local:80
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
|
||||
# Vault
|
||||
- hostname: vault.yourdomain.com
|
||||
service: http://vault.vault.svc.cluster.local:8200
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
|
||||
# Keycloak
|
||||
- hostname: keycloak.yourdomain.com
|
||||
service: http://keycloak.keycloak.svc.cluster.local:8080
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
|
||||
# Kubernetes API (restricted)
|
||||
- hostname: k8s-api.yourdomain.com
|
||||
service: https://kubernetes.default.svc.cluster.local:443
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
tls:
|
||||
skipVerify: false
|
||||
|
||||
# Catch-all rule (must be last)
|
||||
- service: http_status:404
|
||||
|
||||
# Logging
|
||||
loglevel: info
|
||||
logfile: /var/log/cloudflared/control-plane-tunnel.log
|
||||
|
||||
# Metrics
|
||||
metrics: 0.0.0.0:9090
|
||||
|
||||
# Health check
|
||||
health-probe:
|
||||
enabled: true
|
||||
path: /health
|
||||
port: 8080
|
||||
|
||||
70
cloudflare/tunnel-configs/proxmox-site-1.yaml
Normal file
70
cloudflare/tunnel-configs/proxmox-site-1.yaml
Normal file
@@ -0,0 +1,70 @@
|
||||
# Cloudflare Tunnel Configuration for Proxmox Site 1 (US-East)
|
||||
# This tunnel connects Proxmox cluster to Cloudflare
|
||||
|
||||
tunnel: proxmox-site-1-tunnel
|
||||
credentials-file: /etc/cloudflared/proxmox-site-1-tunnel.json
|
||||
|
||||
ingress:
|
||||
# Proxmox Web UI
|
||||
- hostname: pve1.yourdomain.com
|
||||
service: https://pve1.local:8006
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
tls:
|
||||
skipVerify: true
|
||||
httpHostHeader: pve1.local:8006
|
||||
|
||||
# Proxmox API
|
||||
- hostname: pve1-api.yourdomain.com
|
||||
service: https://pve1.local:8006
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
tls:
|
||||
skipVerify: true
|
||||
httpHostHeader: pve1.local:8006
|
||||
|
||||
# Proxmox Node 2
|
||||
- hostname: pve2.yourdomain.com
|
||||
service: https://pve2.local:8006
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
tls:
|
||||
skipVerify: true
|
||||
httpHostHeader: pve2.local:8006
|
||||
|
||||
# Proxmox Node 3
|
||||
- hostname: pve3.yourdomain.com
|
||||
service: https://pve3.local:8006
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
tls:
|
||||
skipVerify: true
|
||||
httpHostHeader: pve3.local:8006
|
||||
|
||||
# Prometheus Exporter
|
||||
- hostname: pve1-metrics.yourdomain.com
|
||||
service: http://localhost:9221
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
|
||||
# Catch-all rule (must be last)
|
||||
- service: http_status:404
|
||||
|
||||
# Logging
|
||||
loglevel: info
|
||||
logfile: /var/log/cloudflared/proxmox-site-1-tunnel.log
|
||||
|
||||
# Metrics
|
||||
metrics: 0.0.0.0:9091
|
||||
|
||||
# Health check
|
||||
health-probe:
|
||||
enabled: true
|
||||
path: /health
|
||||
port: 8080
|
||||
|
||||
70
cloudflare/tunnel-configs/proxmox-site-2.yaml
Normal file
70
cloudflare/tunnel-configs/proxmox-site-2.yaml
Normal file
@@ -0,0 +1,70 @@
|
||||
# Cloudflare Tunnel Configuration for Proxmox Site 2 (EU-West)
|
||||
# This tunnel connects Proxmox cluster to Cloudflare
|
||||
|
||||
tunnel: proxmox-site-2-tunnel
|
||||
credentials-file: /etc/cloudflared/proxmox-site-2-tunnel.json
|
||||
|
||||
ingress:
|
||||
# Proxmox Web UI
|
||||
- hostname: pve4.yourdomain.com
|
||||
service: https://pve4.local:8006
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
tls:
|
||||
skipVerify: true
|
||||
httpHostHeader: pve4.local:8006
|
||||
|
||||
# Proxmox API
|
||||
- hostname: pve4-api.yourdomain.com
|
||||
service: https://pve4.local:8006
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
tls:
|
||||
skipVerify: true
|
||||
httpHostHeader: pve4.local:8006
|
||||
|
||||
# Proxmox Node 2
|
||||
- hostname: pve5.yourdomain.com
|
||||
service: https://pve5.local:8006
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
tls:
|
||||
skipVerify: true
|
||||
httpHostHeader: pve5.local:8006
|
||||
|
||||
# Proxmox Node 3
|
||||
- hostname: pve6.yourdomain.com
|
||||
service: https://pve6.local:8006
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
tls:
|
||||
skipVerify: true
|
||||
httpHostHeader: pve6.local:8006
|
||||
|
||||
# Prometheus Exporter
|
||||
- hostname: pve4-metrics.yourdomain.com
|
||||
service: http://localhost:9221
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
|
||||
# Catch-all rule (must be last)
|
||||
- service: http_status:404
|
||||
|
||||
# Logging
|
||||
loglevel: info
|
||||
logfile: /var/log/cloudflared/proxmox-site-2-tunnel.log
|
||||
|
||||
# Metrics
|
||||
metrics: 0.0.0.0:9092
|
||||
|
||||
# Health check
|
||||
health-probe:
|
||||
enabled: true
|
||||
path: /health
|
||||
port: 8080
|
||||
|
||||
60
cloudflare/tunnel-configs/proxmox-site-3.yaml
Normal file
60
cloudflare/tunnel-configs/proxmox-site-3.yaml
Normal file
@@ -0,0 +1,60 @@
|
||||
# Cloudflare Tunnel Configuration for Proxmox Site 3 (APAC)
|
||||
# This tunnel connects Proxmox cluster to Cloudflare
|
||||
|
||||
tunnel: proxmox-site-3-tunnel
|
||||
credentials-file: /etc/cloudflared/proxmox-site-3-tunnel.json
|
||||
|
||||
ingress:
|
||||
# Proxmox Web UI
|
||||
- hostname: pve7.yourdomain.com
|
||||
service: https://pve7.local:8006
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
tls:
|
||||
skipVerify: true
|
||||
httpHostHeader: pve7.local:8006
|
||||
|
||||
# Proxmox API
|
||||
- hostname: pve7-api.yourdomain.com
|
||||
service: https://pve7.local:8006
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
tls:
|
||||
skipVerify: true
|
||||
httpHostHeader: pve7.local:8006
|
||||
|
||||
# Proxmox Node 2
|
||||
- hostname: pve8.yourdomain.com
|
||||
service: https://pve8.local:8006
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
tls:
|
||||
skipVerify: true
|
||||
httpHostHeader: pve8.local:8006
|
||||
|
||||
# Prometheus Exporter
|
||||
- hostname: pve7-metrics.yourdomain.com
|
||||
service: http://localhost:9221
|
||||
originRequest:
|
||||
noHappyEyeballs: true
|
||||
connectTimeout: 30s
|
||||
|
||||
# Catch-all rule (must be last)
|
||||
- service: http_status:404
|
||||
|
||||
# Logging
|
||||
loglevel: info
|
||||
logfile: /var/log/cloudflared/proxmox-site-3-tunnel.log
|
||||
|
||||
# Metrics
|
||||
metrics: 0.0.0.0:9093
|
||||
|
||||
# Health check
|
||||
health-probe:
|
||||
enabled: true
|
||||
path: /health
|
||||
port: 8080
|
||||
|
||||
129
cloudflare/warp-config.json
Normal file
129
cloudflare/warp-config.json
Normal file
@@ -0,0 +1,129 @@
|
||||
{
|
||||
"organization": {
|
||||
"name": "Your Organization",
|
||||
"auth_domain": "yourdomain.com"
|
||||
},
|
||||
"enrollment": {
|
||||
"enabled": true,
|
||||
"mode": "automatic",
|
||||
"require_mfa": true,
|
||||
"device_posture_checks": [
|
||||
"managed_device",
|
||||
"os_version",
|
||||
"disk_encryption"
|
||||
]
|
||||
},
|
||||
"policies": [
|
||||
{
|
||||
"name": "Default WARP Policy",
|
||||
"description": "Default policy for all WARP devices",
|
||||
"rules": [
|
||||
{
|
||||
"action": "allow",
|
||||
"match": "any",
|
||||
"identity": {
|
||||
"groups": [
|
||||
{
|
||||
"name": "employees"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Admin WARP Policy",
|
||||
"description": "Enhanced access for administrators",
|
||||
"rules": [
|
||||
{
|
||||
"action": "allow",
|
||||
"match": "any",
|
||||
"identity": {
|
||||
"groups": [
|
||||
{
|
||||
"name": "admins"
|
||||
},
|
||||
{
|
||||
"name": "platform-engineers"
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": [
|
||||
{
|
||||
"mfa": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"device_posture": {
|
||||
"checks": [
|
||||
{
|
||||
"name": "managed_device",
|
||||
"type": "os_version",
|
||||
"enabled": true,
|
||||
"rules": [
|
||||
{
|
||||
"os": "windows",
|
||||
"min_version": "10.0.19041"
|
||||
},
|
||||
{
|
||||
"os": "macos",
|
||||
"min_version": "11.0"
|
||||
},
|
||||
{
|
||||
"os": "linux",
|
||||
"min_version": "5.4"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "disk_encryption",
|
||||
"type": "disk_encryption",
|
||||
"enabled": true,
|
||||
"require": true
|
||||
},
|
||||
{
|
||||
"name": "firewall_enabled",
|
||||
"type": "firewall",
|
||||
"enabled": true,
|
||||
"require": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"settings": {
|
||||
"gateway_proxy": {
|
||||
"enabled": true,
|
||||
"tcp_port": 4000,
|
||||
"udp_port": 4001
|
||||
},
|
||||
"split_tunnels": {
|
||||
"enabled": true,
|
||||
"exclude": [
|
||||
"*.yourdomain.com",
|
||||
"10.0.0.0/8",
|
||||
"172.16.0.0/12",
|
||||
"192.168.0.0/16"
|
||||
]
|
||||
},
|
||||
"dns": {
|
||||
"servers": [
|
||||
"1.1.1.1",
|
||||
"1.0.0.1"
|
||||
],
|
||||
"split_dns": [
|
||||
{
|
||||
"domains": [
|
||||
"yourdomain.com",
|
||||
"*.yourdomain.com"
|
||||
],
|
||||
"servers": [
|
||||
"10.0.0.53"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user