From f75cb8aab2b9a2d1eef82b397a5d7c4b78c13522 Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Thu, 27 Nov 2025 19:08:48 -0500 Subject: [PATCH] Add comprehensive plugin usage examples for Docker, Kubernetes, and Swarm - Introduced multiple detailed plugin examples for Cloudflare IP restoration, IP whitelisting, JWT validation, and combined usage. - Added configurations for `docker-compose`, `Kubernetes`, and `Swarm` showcasing individual and multi-plugin use cases. - Included clear prerequisites, setup steps, and testing procedures for each example. - Documented advanced scenarios like path blocking, custom IP lists, and JWT validation for production environments. --- examples/docker/README.md | 211 +++++++++++++ examples/docker/docker-compose-cloudflare.yml | 60 ++++ .../docker/docker-compose-ip-whitelist.yml | 57 ++++ .../docker/docker-compose-jwt-validator.yml | 66 ++++ .../docker-compose-plugins-combined.yml | 106 +++++++ examples/kubernetes/README.md | 269 ++++++++++++++++ examples/kubernetes/cloudflare.yml | 103 +++++++ examples/kubernetes/ip-whitelist.yml | 96 ++++++ examples/kubernetes/jwt-validator.yml | 113 +++++++ examples/kubernetes/plugins-combined.yml | 233 ++++++++++++++ examples/swarm/README.md | 286 ++++++++++++++++++ examples/swarm/cloudflare.yml | 78 +++++ examples/swarm/ip-whitelist.yml | 73 +++++ examples/swarm/jwt-validator.yml | 89 ++++++ examples/swarm/plugins-combined.yml | 137 +++++++++ 15 files changed, 1977 insertions(+) create mode 100644 examples/docker/docker-compose-cloudflare.yml create mode 100644 examples/docker/docker-compose-ip-whitelist.yml create mode 100644 examples/docker/docker-compose-jwt-validator.yml create mode 100644 examples/docker/docker-compose-plugins-combined.yml create mode 100644 examples/kubernetes/cloudflare.yml create mode 100644 examples/kubernetes/ip-whitelist.yml create mode 100644 examples/kubernetes/jwt-validator.yml create mode 100644 examples/kubernetes/plugins-combined.yml create mode 100644 examples/swarm/cloudflare.yml create mode 100644 examples/swarm/ip-whitelist.yml create mode 100644 examples/swarm/jwt-validator.yml create mode 100644 examples/swarm/plugins-combined.yml diff --git a/examples/docker/README.md b/examples/docker/README.md index 6a6f927..ce0640b 100644 --- a/examples/docker/README.md +++ b/examples/docker/README.md @@ -149,6 +149,217 @@ labels: --- +## Plugin Examples + +### JWT Validator Plugin + +Protect your API with JWT token validation: + +```yaml +version: "3" + +services: + haproxy: + image: byjg/easy-haproxy:4.6.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ./jwt_pubkey.pem:/etc/haproxy/jwt_keys/api_pubkey.pem:ro + environment: + EASYHAPROXY_DISCOVER: docker + HAPROXY_USERNAME: admin + HAPROXY_PASSWORD: password + HAPROXY_STATS_PORT: 1936 + ports: + - "80:80/tcp" + - "443:443/tcp" + - "1936:1936/tcp" + + api: + image: my-api:latest + labels: + easyhaproxy.http.host: api.example.com + easyhaproxy.http.port: 80 + easyhaproxy.http.localport: 8080 + # Enable JWT validation + easyhaproxy.http.plugins: jwt_validator + easyhaproxy.http.plugin.jwt_validator.algorithm: RS256 + easyhaproxy.http.plugin.jwt_validator.issuer: https://auth.example.com/ + easyhaproxy.http.plugin.jwt_validator.audience: https://api.example.com + easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/haproxy/jwt_keys/api_pubkey.pem +``` + +**What it validates:** +- Authorization header presence +- JWT signing algorithm +- JWT issuer and audience +- JWT signature using public key +- JWT expiration time + +**Test:** +```bash +# Without token - should fail +curl http://api.example.com/endpoint +# Response: Missing Authorization HTTP header + +# With valid JWT token +curl -H "Authorization: Bearer eyJhbGc..." http://api.example.com/endpoint +# Response: Success +``` + +**Generate test public key:** +```bash +# Generate private key +openssl genrsa -out jwt_private.pem 2048 + +# Extract public key +openssl rsa -in jwt_private.pem -pubout -out jwt_pubkey.pem +``` + +--- + +### Cloudflare IP Restoration Plugin + +Restore original visitor IPs when using Cloudflare CDN: + +```yaml +version: "3" + +services: + haproxy: + image: byjg/easy-haproxy:4.6.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ./cloudflare_ips.lst:/etc/haproxy/cloudflare_ips.lst:ro + environment: + EASYHAPROXY_DISCOVER: docker + ports: + - "80:80/tcp" + - "443:443/tcp" + + webapp: + image: my-webapp:latest + labels: + easyhaproxy.http.host: myapp.com + easyhaproxy.http.port: 80 + easyhaproxy.http.localport: 3000 + # Enable Cloudflare plugin + easyhaproxy.http.plugins: cloudflare +``` + +**Setup Cloudflare IP list:** +```bash +# Download Cloudflare IP ranges +curl https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst +curl https://www.cloudflare.com/ips-v6 >> cloudflare_ips.lst +``` + +**What it does:** +- Detects requests from Cloudflare IPs +- Restores original visitor IP from `CF-Connecting-IP` header +- Your application logs show real visitor IPs, not Cloudflare IPs + +--- + +### IP Whitelist Plugin + +Restrict access to specific IP addresses: + +```yaml +version: "3" + +services: + haproxy: + image: byjg/easy-haproxy:4.6.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + EASYHAPROXY_DISCOVER: docker + ports: + - "80:80/tcp" + + admin_panel: + image: admin-panel:latest + labels: + easyhaproxy.http.host: admin.example.com + easyhaproxy.http.port: 80 + easyhaproxy.http.localport: 8080 + # Enable IP whitelist + easyhaproxy.http.plugins: ip_whitelist + easyhaproxy.http.plugin.ip_whitelist.allowed_ips: 192.168.1.0/24,10.0.0.5 + easyhaproxy.http.plugin.ip_whitelist.status_code: 403 +``` + +**Allowed IP formats:** +- Single IP: `10.0.0.5` +- CIDR range: `192.168.1.0/24` +- Multiple (comma-separated): `192.168.1.0/24,10.0.0.5,172.16.0.100` + +**Test:** +```bash +# From allowed IP +curl http://admin.example.com +# Response: Success + +# From blocked IP +curl http://admin.example.com +# Response: HTTP 403 Forbidden +``` + +--- + +### Multiple Plugins Combined + +Combine multiple plugins for enhanced security: + +```yaml +version: "3" + +services: + haproxy: + image: byjg/easy-haproxy:4.6.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ./cloudflare_ips.lst:/etc/haproxy/cloudflare_ips.lst:ro + environment: + EASYHAPROXY_DISCOVER: docker + ports: + - "80:80/tcp" + - "443:443/tcp" + + webapp: + image: webapp:latest + labels: + easyhaproxy.http.host: myapp.example.com + easyhaproxy.http.port: 80 + easyhaproxy.http.localport: 8080 + # Enable multiple plugins + easyhaproxy.http.plugins: cloudflare,deny_pages + # Block specific paths + easyhaproxy.http.plugin.deny_pages.paths: /admin,/wp-admin,/wp-login.php,/.env + easyhaproxy.http.plugin.deny_pages.status_code: 404 + + api: + image: api:latest + labels: + easyhaproxy.http.host: api.example.com + easyhaproxy.http.port: 80 + easyhaproxy.http.localport: 3000 + # Combine JWT + IP whitelist + path blocking + easyhaproxy.http.plugins: jwt_validator,ip_whitelist,deny_pages + easyhaproxy.http.plugin.jwt_validator.algorithm: RS256 + easyhaproxy.http.plugin.jwt_validator.issuer: https://auth.example.com/ + easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/haproxy/jwt_keys/api.pem + easyhaproxy.http.plugin.ip_whitelist.allowed_ips: 192.168.0.0/16,10.0.0.0/8 + easyhaproxy.http.plugin.deny_pages.paths: /internal,/debug +``` + +**Plugin execution order:** +1. IP Whitelist (blocks non-whitelisted IPs) +2. Deny Pages (blocks specific paths) +3. JWT Validator (validates authentication) + +--- + ## Common Configuration Options ### Environment Variables (HAProxy Container) diff --git a/examples/docker/docker-compose-cloudflare.yml b/examples/docker/docker-compose-cloudflare.yml new file mode 100644 index 0000000..fc2a14a --- /dev/null +++ b/examples/docker/docker-compose-cloudflare.yml @@ -0,0 +1,60 @@ +# Cloudflare IP Restoration Plugin Example +# +# This example demonstrates restoring original visitor IPs when using Cloudflare CDN +# +# Prerequisites: +# 1. Download Cloudflare IP ranges: +# curl https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst +# curl https://www.cloudflare.com/ips-v6 >> cloudflare_ips.lst +# +# 2. Add to /etc/hosts: +# 127.0.0.1 myapp.local +# +# 3. Start the stack: +# docker compose -f docker-compose-cloudflare.yml up -d +# +# 4. Test (simulating Cloudflare request): +# # Without CF-Connecting-IP header: +# curl -H "Host: myapp.local" http://127.0.0.1/ +# +# # With CF-Connecting-IP header (simulating Cloudflare): +# curl -H "Host: myapp.local" -H "CF-Connecting-IP: 203.0.113.50" http://127.0.0.1/ +# +# Note: This plugin is most useful when your site is actually behind Cloudflare. +# Without Cloudflare, the request won't come from Cloudflare IPs, so the plugin +# won't activate. This example is for demonstration and testing purposes. + +version: "3" + +services: + haproxy: + image: byjg/easy-haproxy:4.6.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + # Mount Cloudflare IP list + - ./cloudflare_ips.lst:/etc/haproxy/cloudflare_ips.lst:ro + environment: + EASYHAPROXY_DISCOVER: docker + HAPROXY_CUSTOMERRORS: "true" + HAPROXY_USERNAME: admin + HAPROXY_PASSWORD: password + HAPROXY_STATS_PORT: 1936 + ports: + - "80:80/tcp" + - "1936:1936/tcp" + + # Web application behind Cloudflare + webapp: + image: byjg/static-httpserver + environment: + TITLE: "App Behind Cloudflare" + labels: + easyhaproxy.http.host: myapp.local + easyhaproxy.http.port: 80 + easyhaproxy.http.localport: 8080 + + # Enable Cloudflare plugin + easyhaproxy.http.plugins: cloudflare + + # Optional: Specify custom IP list path + # easyhaproxy.http.plugin.cloudflare.ip_list_path: /etc/haproxy/cloudflare_ips.lst diff --git a/examples/docker/docker-compose-ip-whitelist.yml b/examples/docker/docker-compose-ip-whitelist.yml new file mode 100644 index 0000000..e4b28b3 --- /dev/null +++ b/examples/docker/docker-compose-ip-whitelist.yml @@ -0,0 +1,57 @@ +# IP Whitelist Plugin Example +# +# This example demonstrates restricting access to specific IP addresses +# +# Prerequisites: +# 1. Add to /etc/hosts: +# 127.0.0.1 admin.local +# +# 2. Start the stack: +# docker compose -f docker-compose-ip-whitelist.yml up -d +# +# 3. Test from localhost (127.0.0.1 is whitelisted): +# curl http://admin.local/ +# # Response: Success (200 OK) +# +# 4. Test from non-whitelisted IP: +# # You'll need to test from another machine or configure the example +# # with your actual IP address in the allowed_ips label +# +# Note: Update the allowed_ips label with your actual IP addresses/networks + +version: "3" + +services: + haproxy: + image: byjg/easy-haproxy:4.6.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + EASYHAPROXY_DISCOVER: docker + HAPROXY_CUSTOMERRORS: "true" + HAPROXY_USERNAME: admin + HAPROXY_PASSWORD: password + HAPROXY_STATS_PORT: 1936 + ports: + - "80:80/tcp" + - "1936:1936/tcp" + + # Admin panel with IP whitelist + admin: + image: byjg/static-httpserver + environment: + TITLE: "Admin Panel - IP Restricted" + labels: + easyhaproxy.http.host: admin.local + easyhaproxy.http.port: 80 + easyhaproxy.http.localport: 8080 + + # Enable IP whitelist plugin + easyhaproxy.http.plugins: ip_whitelist + + # Allow localhost and private networks + # UPDATE THIS with your actual IPs/networks! + easyhaproxy.http.plugin.ip_whitelist.allowed_ips: 127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12 + + # Status code to return for blocked IPs + easyhaproxy.http.plugin.ip_whitelist.status_code: 403 diff --git a/examples/docker/docker-compose-jwt-validator.yml b/examples/docker/docker-compose-jwt-validator.yml new file mode 100644 index 0000000..2b50bbf --- /dev/null +++ b/examples/docker/docker-compose-jwt-validator.yml @@ -0,0 +1,66 @@ +# JWT Validator Plugin Example +# +# This example demonstrates JWT token validation for API protection +# +# Prerequisites: +# 1. Generate RSA key pair: +# openssl genrsa -out jwt_private.pem 2048 +# openssl rsa -in jwt_private.pem -pubout -out jwt_pubkey.pem +# +# 2. Add to /etc/hosts: +# 127.0.0.1 api.local +# +# 3. Start the stack: +# docker compose -f docker-compose-jwt-validator.yml up -d +# +# 4. Test without token (should fail): +# curl http://api.local/ +# # Response: Missing Authorization HTTP header +# +# 5. Generate test JWT at https://jwt.io with: +# - Algorithm: RS256 +# - Payload: {"iss":"https://auth.example.com/","aud":"https://api.example.com","exp":9999999999} +# - Use your jwt_private.pem for signing +# +# 6. Test with token: +# TOKEN="eyJhbGc..." +# curl -H "Authorization: Bearer $TOKEN" http://api.local/ +# # Response: Success + +version: "3" + +services: + haproxy: + image: byjg/easy-haproxy:4.6.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + # Mount the public key for JWT verification + - ./jwt_pubkey.pem:/etc/haproxy/jwt_keys/api_pubkey.pem:ro + environment: + EASYHAPROXY_DISCOVER: docker + HAPROXY_CUSTOMERRORS: "true" + HAPROXY_USERNAME: admin + HAPROXY_PASSWORD: password + HAPROXY_STATS_PORT: 1936 + ports: + - "80:80/tcp" + - "1936:1936/tcp" + + # API service protected by JWT + api: + image: byjg/static-httpserver + environment: + TITLE: "Protected API - JWT Required" + labels: + easyhaproxy.http.host: api.local + easyhaproxy.http.port: 80 + easyhaproxy.http.localport: 8080 + + # Enable JWT validator plugin + easyhaproxy.http.plugins: jwt_validator + + # JWT validator configuration + easyhaproxy.http.plugin.jwt_validator.algorithm: RS256 + easyhaproxy.http.plugin.jwt_validator.issuer: https://auth.example.com/ + easyhaproxy.http.plugin.jwt_validator.audience: https://api.example.com/ + easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/haproxy/jwt_keys/api_pubkey.pem diff --git a/examples/docker/docker-compose-plugins-combined.yml b/examples/docker/docker-compose-plugins-combined.yml new file mode 100644 index 0000000..742b554 --- /dev/null +++ b/examples/docker/docker-compose-plugins-combined.yml @@ -0,0 +1,106 @@ +# Multiple Plugins Combined Example +# +# This example demonstrates using multiple plugins together for enhanced security +# +# Prerequisites: +# 1. Generate JWT keys: +# openssl genrsa -out jwt_private.pem 2048 +# openssl rsa -in jwt_private.pem -pubout -out jwt_pubkey.pem +# +# 2. Download Cloudflare IPs: +# curl https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst +# curl https://www.cloudflare.com/ips-v6 >> cloudflare_ips.lst +# +# 3. Add to /etc/hosts: +# 127.0.0.1 website.local api.local admin.local +# +# 4. Start the stack: +# docker compose -f docker-compose-plugins-combined.yml up -d +# +# 5. Test each service: +# # Public website (Cloudflare + path blocking) +# curl http://website.local/ +# curl http://website.local/admin # Should be blocked (404) +# +# # Protected API (JWT required) +# curl http://api.local/ # Should fail - no JWT +# curl -H "Authorization: Bearer " http://api.local/ # Success +# +# # Admin panel (IP whitelist only) +# curl http://admin.local/ # Success from localhost + +version: "3" + +services: + haproxy: + image: byjg/easy-haproxy:4.6.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ./cloudflare_ips.lst:/etc/haproxy/cloudflare_ips.lst:ro + - ./jwt_pubkey.pem:/etc/haproxy/jwt_keys/api_pubkey.pem:ro + environment: + EASYHAPROXY_DISCOVER: docker + HAPROXY_CUSTOMERRORS: "true" + HAPROXY_USERNAME: admin + HAPROXY_PASSWORD: password + HAPROXY_STATS_PORT: 1936 + ports: + - "80:80/tcp" + - "1936:1936/tcp" + + # Public website with Cloudflare + path blocking + website: + image: byjg/static-httpserver + environment: + TITLE: "Public Website" + labels: + easyhaproxy.http.host: website.local + easyhaproxy.http.port: 80 + easyhaproxy.http.localport: 8080 + + # Combine Cloudflare IP restoration + deny pages + easyhaproxy.http.plugins: cloudflare,deny_pages + + # Block admin paths, config files, etc. + easyhaproxy.http.plugin.deny_pages.paths: /admin,/wp-admin,/wp-login.php,/.env,/config + easyhaproxy.http.plugin.deny_pages.status_code: 404 + + # Protected API with JWT validation + path blocking + api: + image: byjg/static-httpserver + environment: + TITLE: "Protected API" + labels: + easyhaproxy.http.host: api.local + easyhaproxy.http.port: 80 + easyhaproxy.http.localport: 8080 + + # JWT validation + block internal endpoints + easyhaproxy.http.plugins: jwt_validator,deny_pages + + # JWT configuration + easyhaproxy.http.plugin.jwt_validator.algorithm: RS256 + easyhaproxy.http.plugin.jwt_validator.issuer: https://auth.example.com/ + easyhaproxy.http.plugin.jwt_validator.audience: https://api.example.com + easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/haproxy/jwt_keys/api_pubkey.pem + + # Block internal/debug endpoints + easyhaproxy.http.plugin.deny_pages.paths: /internal,/debug,/metrics + easyhaproxy.http.plugin.deny_pages.status_code: 403 + + # Admin panel with strict IP restrictions + admin: + image: byjg/static-httpserver + environment: + TITLE: "Admin Panel" + labels: + easyhaproxy.http.host: admin.local + easyhaproxy.http.port: 80 + easyhaproxy.http.localport: 8080 + + # IP whitelist only (strictest security) + easyhaproxy.http.plugins: ip_whitelist + + # Only allow local and private networks + easyhaproxy.http.plugin.ip_whitelist.allowed_ips: 127.0.0.1,192.168.0.0/16,10.0.0.0/8 + easyhaproxy.http.plugin.ip_whitelist.status_code: 403 diff --git a/examples/kubernetes/README.md b/examples/kubernetes/README.md index 0718de9..7bac331 100644 --- a/examples/kubernetes/README.md +++ b/examples/kubernetes/README.md @@ -288,6 +288,275 @@ See [Using Plugins with Kubernetes](../../docs/kubernetes.md#using-plugins-with- --- +## Plugin Examples + +### JWT Validator Plugin + +Complete example with JWT validation for API protection: + +```yaml +--- +# Create ConfigMap with public key +apiVersion: v1 +kind: ConfigMap +metadata: + name: jwt-keys + namespace: default +data: + api_pubkey.pem: | + -----BEGIN PUBLIC KEY----- + MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA... + -----END PUBLIC KEY----- + +--- +# Mount public key into EasyHAProxy pod +# Add this to your EasyHAProxy deployment: +# volumeMounts: +# - name: jwt-keys +# mountPath: /etc/haproxy/jwt_keys +# volumes: +# - name: jwt-keys +# configMap: +# name: jwt-keys + +--- +apiVersion: v1 +kind: Service +metadata: + name: api-service + namespace: default +spec: + ports: + - port: 8080 + selector: + app: api + type: ClusterIP + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: api + namespace: default +spec: + replicas: 3 + selector: + matchLabels: + app: api + template: + metadata: + labels: + app: api + spec: + containers: + - name: api + image: my-api:latest + ports: + - containerPort: 8080 + +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: easyhaproxy-ingress + # Enable JWT validator + easyhaproxy.plugins: "jwt_validator" + easyhaproxy.plugin.jwt_validator.algorithm: "RS256" + easyhaproxy.plugin.jwt_validator.issuer: "https://auth.example.com/" + easyhaproxy.plugin.jwt_validator.audience: "https://api.example.com" + easyhaproxy.plugin.jwt_validator.pubkey_path: "/etc/haproxy/jwt_keys/api_pubkey.pem" + name: api-ingress + namespace: default +spec: + rules: + - host: api.example.com + http: + paths: + - backend: + service: + name: api-service + port: + number: 8080 + pathType: ImplementationSpecific +``` + +**Test:** +```bash +# Without JWT token - should fail +curl http://api.example.com/users +# Response: Missing Authorization HTTP header + +# With valid JWT token +TOKEN="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." +curl -H "Authorization: Bearer $TOKEN" http://api.example.com/users +# Response: Success +``` + +--- + +### Cloudflare IP Restoration Plugin + +Restore original visitor IPs when behind Cloudflare: + +```yaml +--- +# Create ConfigMap with Cloudflare IP ranges +apiVersion: v1 +kind: ConfigMap +metadata: + name: cloudflare-ips + namespace: easyhaproxy +data: + cloudflare_ips.lst: | + 173.245.48.0/20 + 103.21.244.0/22 + 103.22.200.0/22 + 103.31.4.0/22 + 141.101.64.0/18 + 108.162.192.0/18 + 190.93.240.0/20 + 188.114.96.0/20 + 197.234.240.0/22 + 198.41.128.0/17 + 162.158.0.0/15 + 104.16.0.0/13 + 104.24.0.0/14 + 172.64.0.0/13 + 131.0.72.0/22 + +--- +# Mount ConfigMap into EasyHAProxy pod +# Add this to your EasyHAProxy deployment: +# volumeMounts: +# - name: cloudflare-ips +# mountPath: /etc/haproxy/cloudflare_ips.lst +# subPath: cloudflare_ips.lst +# volumes: +# - name: cloudflare-ips +# configMap: +# name: cloudflare-ips + +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: easyhaproxy-ingress + # Enable Cloudflare plugin + easyhaproxy.plugins: "cloudflare" + name: webapp-ingress + namespace: default +spec: + rules: + - host: myapp.example.com + http: + paths: + - backend: + service: + name: webapp-service + port: + number: 8080 + pathType: ImplementationSpecific +``` + +**Download latest Cloudflare IPs:** +```bash +curl https://www.cloudflare.com/ips-v4 +curl https://www.cloudflare.com/ips-v6 +``` + +--- + +### IP Whitelist Plugin + +Restrict admin panel to office IPs only: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: easyhaproxy-ingress + # Enable IP whitelist + easyhaproxy.plugins: "ip_whitelist" + easyhaproxy.plugin.ip_whitelist.allowed_ips: "203.0.113.0/24,198.51.100.42" + easyhaproxy.plugin.ip_whitelist.status_code: "403" + name: admin-ingress + namespace: default +spec: + rules: + - host: admin.example.com + http: + paths: + - backend: + service: + name: admin-service + port: + number: 8080 + pathType: ImplementationSpecific +``` + +**Test:** +```bash +# From allowed IP (203.0.113.50) +curl http://admin.example.com +# Response: Success + +# From blocked IP +curl http://admin.example.com +# Response: HTTP 403 Forbidden +``` + +--- + +### Multiple Plugins Combined + +Combine Cloudflare + JWT + Path Blocking for maximum security: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: easyhaproxy-ingress + # Enable multiple plugins + easyhaproxy.plugins: "cloudflare,jwt_validator,deny_pages" + + # Cloudflare - restore real IPs + # (no config needed if using default path) + + # JWT Validator - validate tokens + easyhaproxy.plugin.jwt_validator.algorithm: "RS256" + easyhaproxy.plugin.jwt_validator.issuer: "https://auth.example.com/" + easyhaproxy.plugin.jwt_validator.audience: "https://api.example.com" + easyhaproxy.plugin.jwt_validator.pubkey_path: "/etc/haproxy/jwt_keys/api_pubkey.pem" + + # Deny Pages - block sensitive paths + easyhaproxy.plugin.deny_pages.paths: "/internal,/debug,/admin" + easyhaproxy.plugin.deny_pages.status_code: "404" + name: secure-api-ingress + namespace: production +spec: + rules: + - host: api.example.com + http: + paths: + - backend: + service: + name: api-service + port: + number: 8080 + pathType: ImplementationSpecific +``` + +**Plugin execution order:** +1. Cloudflare IP restoration (sets correct visitor IP) +2. Deny Pages (blocks blacklisted paths) +3. JWT Validator (validates authentication) + +--- + ## Creating SSL Secrets ### From Certificate Files diff --git a/examples/kubernetes/cloudflare.yml b/examples/kubernetes/cloudflare.yml new file mode 100644 index 0000000..734d228 --- /dev/null +++ b/examples/kubernetes/cloudflare.yml @@ -0,0 +1,103 @@ +# Cloudflare IP Restoration Plugin Example for Kubernetes +# +# This example demonstrates restoring original visitor IPs when using Cloudflare CDN +# +# Prerequisites: +# 1. EasyHAProxy installed in your cluster +# +# 2. Download Cloudflare IP ranges and create ConfigMap: +# curl https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst +# curl https://www.cloudflare.com/ips-v6 >> cloudflare_ips.lst +# kubectl create configmap cloudflare-ips \ +# --from-file=cloudflare_ips.lst=cloudflare_ips.lst \ +# -n easyhaproxy +# +# 3. Mount the ConfigMap in EasyHAProxy deployment (add to volumeMounts and volumes): +# volumeMounts: +# - name: cloudflare-ips +# mountPath: /etc/haproxy/cloudflare_ips.lst +# subPath: cloudflare_ips.lst +# volumes: +# - name: cloudflare-ips +# configMap: +# name: cloudflare-ips +# +# 4. Apply this manifest: +# kubectl apply -f cloudflare.yml +# +# 5. Test: +# curl http://myapp.example.local/ +# +# Note: This plugin is most useful when your site is actually behind Cloudflare. + +--- +apiVersion: v1 +kind: Service +metadata: + name: webapp-service + namespace: default +spec: + ports: + - port: 8080 + targetPort: 8080 + selector: + app: webapp + type: ClusterIP + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: webapp + namespace: default +spec: + replicas: 3 + selector: + matchLabels: + app: webapp + template: + metadata: + labels: + app: webapp + spec: + containers: + - name: webapp + image: byjg/static-httpserver + ports: + - containerPort: 8080 + env: + - name: TITLE + value: "App Behind Cloudflare" + resources: + limits: + cpu: '0.1' + memory: '64Mi' + requests: + cpu: '0.05' + memory: '32Mi' + +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: easyhaproxy-ingress + + # Enable Cloudflare plugin + easyhaproxy.plugins: "cloudflare" + + # Optional: Specify custom IP list path + # easyhaproxy.plugin.cloudflare.ip_list_path: "/etc/haproxy/cloudflare_ips.lst" + name: webapp-ingress-cloudflare + namespace: default +spec: + rules: + - host: myapp.example.local + http: + paths: + - backend: + service: + name: webapp-service + port: + number: 8080 + pathType: ImplementationSpecific diff --git a/examples/kubernetes/ip-whitelist.yml b/examples/kubernetes/ip-whitelist.yml new file mode 100644 index 0000000..4603d43 --- /dev/null +++ b/examples/kubernetes/ip-whitelist.yml @@ -0,0 +1,96 @@ +# IP Whitelist Plugin Example for Kubernetes +# +# This example demonstrates restricting access to specific IP addresses +# +# Prerequisites: +# 1. EasyHAProxy installed in your cluster +# +# 2. Update the allowed_ips annotation with your actual IP addresses/networks +# +# 3. Apply this manifest: +# kubectl apply -f ip-whitelist.yml +# +# 4. Test from allowed IP: +# curl http://admin.example.local/ +# # Response: Success (200 OK) +# +# 5. Test from non-allowed IP: +# # Response: HTTP 403 Forbidden +# +# Note: Update the allowed_ips annotation with your actual office/VPN IPs + +--- +apiVersion: v1 +kind: Service +metadata: + name: admin-service + namespace: default +spec: + ports: + - port: 8080 + targetPort: 8080 + selector: + app: admin + type: ClusterIP + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: admin + namespace: default +spec: + replicas: 2 + selector: + matchLabels: + app: admin + template: + metadata: + labels: + app: admin + spec: + containers: + - name: admin + image: byjg/static-httpserver + ports: + - containerPort: 8080 + env: + - name: TITLE + value: "Admin Panel - IP Restricted" + resources: + limits: + cpu: '0.1' + memory: '64Mi' + requests: + cpu: '0.05' + memory: '32Mi' + +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: easyhaproxy-ingress + + # Enable IP whitelist plugin + easyhaproxy.plugins: "ip_whitelist" + + # Allow specific IPs and networks + # UPDATE THIS with your actual office/VPN IPs! + easyhaproxy.plugin.ip_whitelist.allowed_ips: "203.0.113.0/24,198.51.100.42,10.0.0.0/8" + + # Status code to return for blocked IPs + easyhaproxy.plugin.ip_whitelist.status_code: "403" + name: admin-ingress-whitelist + namespace: default +spec: + rules: + - host: admin.example.local + http: + paths: + - backend: + service: + name: admin-service + port: + number: 8080 + pathType: ImplementationSpecific diff --git a/examples/kubernetes/jwt-validator.yml b/examples/kubernetes/jwt-validator.yml new file mode 100644 index 0000000..f3d7b90 --- /dev/null +++ b/examples/kubernetes/jwt-validator.yml @@ -0,0 +1,113 @@ +# JWT Validator Plugin Example for Kubernetes +# +# This example demonstrates JWT token validation for API protection in Kubernetes +# +# Prerequisites: +# 1. EasyHAProxy installed in your cluster +# 2. Generate RSA key pair: +# openssl genrsa -out jwt_private.pem 2048 +# openssl rsa -in jwt_private.pem -pubout -out jwt_pubkey.pem +# +# 3. Create ConfigMap with public key: +# kubectl create configmap jwt-keys --from-file=api_pubkey.pem=jwt_pubkey.pem +# +# 4. Mount the ConfigMap in EasyHAProxy deployment (add to volumeMounts and volumes): +# volumeMounts: +# - name: jwt-keys +# mountPath: /etc/haproxy/jwt_keys +# volumes: +# - name: jwt-keys +# configMap: +# name: jwt-keys +# +# 5. Apply this manifest: +# kubectl apply -f jwt-validator.yml +# +# 6. Test without token (should fail): +# curl http://api.example.local/ +# # Response: Missing Authorization HTTP header +# +# 7. Generate test JWT at https://jwt.io with: +# - Algorithm: RS256 +# - Payload: {"iss":"https://auth.example.com/","aud":"https://api.example.com","exp":9999999999} +# - Use your jwt_private.pem for signing +# +# 8. Test with token: +# TOKEN="eyJhbGc..." +# curl -H "Authorization: Bearer $TOKEN" http://api.example.local/ +# # Response: Success + +--- +apiVersion: v1 +kind: Service +metadata: + name: api-service + namespace: default +spec: + ports: + - port: 8080 + targetPort: 8080 + selector: + app: api + type: ClusterIP + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: api + namespace: default +spec: + replicas: 3 + selector: + matchLabels: + app: api + template: + metadata: + labels: + app: api + spec: + containers: + - name: api + image: byjg/static-httpserver + ports: + - containerPort: 8080 + env: + - name: TITLE + value: "Protected API - JWT Required" + resources: + limits: + cpu: '0.1' + memory: '64Mi' + requests: + cpu: '0.05' + memory: '32Mi' + +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: easyhaproxy-ingress + + # Enable JWT validator plugin + easyhaproxy.plugins: "jwt_validator" + + # JWT validator configuration + easyhaproxy.plugin.jwt_validator.algorithm: "RS256" + easyhaproxy.plugin.jwt_validator.issuer: "https://auth.example.com/" + easyhaproxy.plugin.jwt_validator.audience: "https://api.example.com" + easyhaproxy.plugin.jwt_validator.pubkey_path: "/etc/haproxy/jwt_keys/api_pubkey.pem" + name: api-ingress-jwt + namespace: default +spec: + rules: + - host: api.example.local + http: + paths: + - backend: + service: + name: api-service + port: + number: 8080 + pathType: ImplementationSpecific diff --git a/examples/kubernetes/plugins-combined.yml b/examples/kubernetes/plugins-combined.yml new file mode 100644 index 0000000..321aeef --- /dev/null +++ b/examples/kubernetes/plugins-combined.yml @@ -0,0 +1,233 @@ +# Multiple Plugins Combined Example for Kubernetes +# +# This example demonstrates using multiple plugins together for enhanced security +# +# Prerequisites: +# 1. EasyHAProxy installed in your cluster +# +# 2. Generate JWT keys and create ConfigMap: +# openssl genrsa -out jwt_private.pem 2048 +# openssl rsa -in jwt_private.pem -pubout -out jwt_pubkey.pem +# kubectl create configmap jwt-keys --from-file=api_pubkey.pem=jwt_pubkey.pem +# +# 3. Download Cloudflare IPs and create ConfigMap: +# curl https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst +# curl https://www.cloudflare.com/ips-v6 >> cloudflare_ips.lst +# kubectl create configmap cloudflare-ips \ +# --from-file=cloudflare_ips.lst=cloudflare_ips.lst \ +# -n easyhaproxy +# +# 4. Mount ConfigMaps in EasyHAProxy deployment +# +# 5. Apply this manifest: +# kubectl apply -f plugins-combined.yml +# +# This creates three services with different security profiles: +# - Public website: Cloudflare + path blocking +# - Protected API: JWT validation + path blocking +# - Admin panel: Strict IP whitelist + +--- +# Public website service +apiVersion: v1 +kind: Service +metadata: + name: website-service + namespace: default +spec: + ports: + - port: 8080 + selector: + app: website + type: ClusterIP + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: website + namespace: default +spec: + replicas: 3 + selector: + matchLabels: + app: website + template: + metadata: + labels: + app: website + spec: + containers: + - name: website + image: byjg/static-httpserver + env: + - name: TITLE + value: "Public Website" + resources: + requests: + cpu: '0.05' + memory: '32Mi' + +--- +# Public website ingress with Cloudflare + path blocking +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: easyhaproxy-ingress + # Cloudflare IP restoration + deny pages + easyhaproxy.plugins: "cloudflare,deny_pages" + easyhaproxy.plugin.deny_pages.paths: "/admin,/wp-admin,/wp-login.php,/.env,/config" + easyhaproxy.plugin.deny_pages.status_code: "404" + name: website-ingress + namespace: default +spec: + rules: + - host: website.example.local + http: + paths: + - backend: + service: + name: website-service + port: + number: 8080 + pathType: ImplementationSpecific + +--- +# API service +apiVersion: v1 +kind: Service +metadata: + name: api-service + namespace: default +spec: + ports: + - port: 8080 + selector: + app: api + type: ClusterIP + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: api + namespace: default +spec: + replicas: 5 + selector: + matchLabels: + app: api + template: + metadata: + labels: + app: api + spec: + containers: + - name: api + image: byjg/static-httpserver + env: + - name: TITLE + value: "Protected API" + resources: + requests: + cpu: '0.05' + memory: '32Mi' + +--- +# API ingress with JWT + path blocking +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: easyhaproxy-ingress + # JWT validation + block internal endpoints + easyhaproxy.plugins: "jwt_validator,deny_pages" + # JWT config + easyhaproxy.plugin.jwt_validator.algorithm: "RS256" + easyhaproxy.plugin.jwt_validator.issuer: "https://auth.example.com/" + easyhaproxy.plugin.jwt_validator.audience: "https://api.example.com" + easyhaproxy.plugin.jwt_validator.pubkey_path: "/etc/haproxy/jwt_keys/api_pubkey.pem" + # Block internal paths + easyhaproxy.plugin.deny_pages.paths: "/internal,/debug,/metrics" + easyhaproxy.plugin.deny_pages.status_code: "403" + name: api-ingress + namespace: default +spec: + rules: + - host: api.example.local + http: + paths: + - backend: + service: + name: api-service + port: + number: 8080 + pathType: ImplementationSpecific + +--- +# Admin service +apiVersion: v1 +kind: Service +metadata: + name: admin-service + namespace: default +spec: + ports: + - port: 8080 + selector: + app: admin + type: ClusterIP + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: admin + namespace: default +spec: + replicas: 2 + selector: + matchLabels: + app: admin + template: + metadata: + labels: + app: admin + spec: + containers: + - name: admin + image: byjg/static-httpserver + env: + - name: TITLE + value: "Admin Panel" + resources: + requests: + cpu: '0.05' + memory: '32Mi' + +--- +# Admin ingress with strict IP whitelist +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: easyhaproxy-ingress + # IP whitelist only (strictest security) + easyhaproxy.plugins: "ip_whitelist" + # UPDATE with your office/VPN IPs! + easyhaproxy.plugin.ip_whitelist.allowed_ips: "203.0.113.0/24,10.0.0.0/8" + easyhaproxy.plugin.ip_whitelist.status_code: "403" + name: admin-ingress + namespace: default +spec: + rules: + - host: admin.example.local + http: + paths: + - backend: + service: + name: admin-service + port: + number: 8080 + pathType: ImplementationSpecific diff --git a/examples/swarm/README.md b/examples/swarm/README.md index e7173b4..a4d5568 100644 --- a/examples/swarm/README.md +++ b/examples/swarm/README.md @@ -324,6 +324,292 @@ networks: --- +## Plugin Examples + +### JWT Validator Plugin + +Secure your API with JWT token validation in Swarm: + +```yaml +version: "3" + +services: + haproxy: + image: byjg/easy-haproxy:4.6.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - jwt_keys:/etc/haproxy/jwt_keys + deploy: + replicas: 1 + environment: + EASYHAPROXY_DISCOVER: swarm + ports: + - "80:80/tcp" + - "443:443/tcp" + networks: + - easyhaproxy + + api: + image: my-api:latest + deploy: + replicas: 5 + labels: + easyhaproxy.http.host: "api.example.com" + easyhaproxy.http.port: "80" + easyhaproxy.http.localport: "8080" + # Enable JWT validation + easyhaproxy.http.plugins: "jwt_validator" + easyhaproxy.http.plugin.jwt_validator.algorithm: "RS256" + easyhaproxy.http.plugin.jwt_validator.issuer: "https://auth.example.com/" + easyhaproxy.http.plugin.jwt_validator.audience: "https://api.example.com" + easyhaproxy.http.plugin.jwt_validator.pubkey_path: "/etc/haproxy/jwt_keys/api_pubkey.pem" + networks: + - easyhaproxy + +networks: + easyhaproxy: + external: true + +volumes: + jwt_keys: +``` + +**Deploy public key using Docker config:** +```bash +# Create Docker config with public key +docker config create jwt_api_pubkey ./api_pubkey.pem + +# Update EasyHAProxy service to use config +docker service update \ + --config-add source=jwt_api_pubkey,target=/etc/haproxy/jwt_keys/api_pubkey.pem \ + easyhaproxy_haproxy +``` + +**Test:** +```bash +# Without token +curl http://api.example.com/users +# Response: Missing Authorization HTTP header + +# With valid token +curl -H "Authorization: Bearer eyJhbGc..." http://api.example.com/users +# Response: Success +``` + +--- + +### Cloudflare IP Restoration Plugin + +Restore original visitor IPs in Swarm environment: + +```yaml +version: "3" + +services: + haproxy: + image: byjg/easy-haproxy:4.6.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + configs: + - source: cloudflare_ips + target: /etc/haproxy/cloudflare_ips.lst + deploy: + replicas: 1 + environment: + EASYHAPROXY_DISCOVER: swarm + ports: + - "80:80/tcp" + - "443:443/tcp" + networks: + - easyhaproxy + + webapp: + image: webapp:latest + deploy: + replicas: 3 + labels: + easyhaproxy.http.host: "myapp.example.com" + easyhaproxy.http.port: "80" + easyhaproxy.http.localport: "8080" + # Enable Cloudflare plugin + easyhaproxy.http.plugins: "cloudflare" + networks: + - easyhaproxy + +networks: + easyhaproxy: + external: true + +configs: + cloudflare_ips: + file: ./cloudflare_ips.lst +``` + +**Create Cloudflare IP list:** +```bash +# Download Cloudflare IPs +curl https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst +curl https://www.cloudflare.com/ips-v6 >> cloudflare_ips.lst + +# Deploy stack +docker stack deploy -c cloudflare-stack.yml myapp +``` + +--- + +### IP Whitelist Plugin + +Restrict admin panel to specific IPs in Swarm: + +```yaml +version: "3" + +services: + admin: + image: admin-panel:latest + deploy: + replicas: 2 + labels: + easyhaproxy.http.host: "admin.example.com" + easyhaproxy.http.port: "80" + easyhaproxy.http.localport: "4000" + # Enable IP whitelist + easyhaproxy.http.plugins: "ip_whitelist" + # Allow office network and VPN + easyhaproxy.http.plugin.ip_whitelist.allowed_ips: "203.0.113.0/24,198.51.100.0/24,10.8.0.0/16" + easyhaproxy.http.plugin.ip_whitelist.status_code: "403" + networks: + - easyhaproxy + +networks: + easyhaproxy: + external: true +``` + +**Test:** +```bash +# From office IP (203.0.113.50) +curl http://admin.example.com +# Response: Success + +# From home/blocked IP +curl http://admin.example.com +# Response: HTTP 403 Forbidden +``` + +--- + +### Multiple Plugins Combined + +Production-ready setup with multiple security layers: + +```yaml +version: "3" + +services: + haproxy: + image: byjg/easy-haproxy:4.6.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + configs: + - source: cloudflare_ips + target: /etc/haproxy/cloudflare_ips.lst + - source: jwt_pubkey + target: /etc/haproxy/jwt_keys/api_pubkey.pem + deploy: + replicas: 1 + placement: + constraints: + - node.role == manager + environment: + EASYHAPROXY_DISCOVER: swarm + EASYHAPROXY_SSL_MODE: "loose" + EASYHAPROXY_CERTBOT_EMAIL: admin@example.com + ports: + - "80:80/tcp" + - "443:443/tcp" + - "1936:1936/tcp" + networks: + - easyhaproxy + + # Public website with Cloudflare + website: + image: website:latest + deploy: + replicas: 4 + labels: + easyhaproxy.http.host: "example.com" + easyhaproxy.http.port: "80" + easyhaproxy.http.localport: "3000" + easyhaproxy.http.certbot: "true" + easyhaproxy.http.redirect_ssl: "true" + # Cloudflare + block sensitive paths + easyhaproxy.http.plugins: "cloudflare,deny_pages" + easyhaproxy.http.plugin.deny_pages.paths: "/admin,/.env,/config" + easyhaproxy.http.plugin.deny_pages.status_code: "404" + networks: + - easyhaproxy + + # Authenticated API with JWT + api: + image: api:latest + deploy: + replicas: 6 + labels: + easyhaproxy.http.host: "api.example.com" + easyhaproxy.http.port: "80" + easyhaproxy.http.localport: "8080" + easyhaproxy.http.certbot: "true" + # Cloudflare + JWT + block internal endpoints + easyhaproxy.http.plugins: "cloudflare,jwt_validator,deny_pages" + easyhaproxy.http.plugin.jwt_validator.algorithm: "RS256" + easyhaproxy.http.plugin.jwt_validator.issuer: "https://auth.example.com/" + easyhaproxy.http.plugin.jwt_validator.audience: "https://api.example.com" + easyhaproxy.http.plugin.jwt_validator.pubkey_path: "/etc/haproxy/jwt_keys/api_pubkey.pem" + easyhaproxy.http.plugin.deny_pages.paths: "/internal,/metrics" + networks: + - easyhaproxy + + # Admin panel with strict IP restrictions + admin: + image: admin:latest + deploy: + replicas: 2 + labels: + easyhaproxy.http.host: "admin.example.com" + easyhaproxy.http.port: "80" + easyhaproxy.http.localport: "4000" + easyhaproxy.http.certbot: "true" + # IP whitelist only (no public access) + easyhaproxy.http.plugins: "ip_whitelist" + easyhaproxy.http.plugin.ip_whitelist.allowed_ips: "203.0.113.0/24" + easyhaproxy.http.plugin.ip_whitelist.status_code: "403" + networks: + - easyhaproxy + +networks: + easyhaproxy: + external: true + +configs: + cloudflare_ips: + file: ./cloudflare_ips.lst + jwt_pubkey: + file: ./api_pubkey.pem +``` + +**Deploy:** +```bash +docker stack deploy -c production-stack.yml production +``` + +**Security layers:** +- **Website**: Cloudflare IP restoration + path blocking +- **API**: Cloudflare + JWT validation + internal path blocking +- **Admin**: Strict IP whitelist (office network only) + +--- + ## Scaling Services Scale services dynamically: diff --git a/examples/swarm/cloudflare.yml b/examples/swarm/cloudflare.yml new file mode 100644 index 0000000..f3c1520 --- /dev/null +++ b/examples/swarm/cloudflare.yml @@ -0,0 +1,78 @@ +# Cloudflare IP Restoration Plugin Example for Docker Swarm +# +# This example demonstrates restoring original visitor IPs when using Cloudflare CDN +# +# Prerequisites: +# 1. Docker Swarm initialized: +# docker swarm init +# +# 2. Create overlay network: +# docker network create --driver overlay --attachable easyhaproxy +# +# 3. Download Cloudflare IPs and create Docker config: +# curl https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst +# curl https://www.cloudflare.com/ips-v6 >> cloudflare_ips.lst +# docker config create cloudflare_ips cloudflare_ips.lst +# +# 4. Deploy the stack: +# docker stack deploy -c cloudflare.yml webapp +# +# 5. Test: +# curl http:/// +# +# Note: This plugin is most useful when your site is actually behind Cloudflare. + +version: "3.7" + +services: + haproxy: + image: byjg/easy-haproxy:4.6.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + configs: + - source: cloudflare_ips + target: /etc/haproxy/cloudflare_ips.lst + deploy: + replicas: 1 + placement: + constraints: + - node.role == manager + environment: + EASYHAPROXY_DISCOVER: swarm + HAPROXY_USERNAME: admin + HAPROXY_PASSWORD: password + HAPROXY_STATS_PORT: 1936 + ports: + - "80:80/tcp" + - "443:443/tcp" + - "1936:1936/tcp" + networks: + - easyhaproxy + + # Web application behind Cloudflare + webapp: + image: byjg/static-httpserver + environment: + TITLE: "App Behind Cloudflare" + deploy: + replicas: 4 + labels: + easyhaproxy.http.host: "myapp.example.com" + easyhaproxy.http.port: "80" + easyhaproxy.http.localport: "8080" + + # Enable Cloudflare plugin + easyhaproxy.http.plugins: "cloudflare" + + # Optional: Specify custom IP list path + # easyhaproxy.http.plugin.cloudflare.ip_list_path: "/etc/haproxy/cloudflare_ips.lst" + networks: + - easyhaproxy + +networks: + easyhaproxy: + external: true + +configs: + cloudflare_ips: + external: true diff --git a/examples/swarm/ip-whitelist.yml b/examples/swarm/ip-whitelist.yml new file mode 100644 index 0000000..829925b --- /dev/null +++ b/examples/swarm/ip-whitelist.yml @@ -0,0 +1,73 @@ +# IP Whitelist Plugin Example for Docker Swarm +# +# This example demonstrates restricting access to specific IP addresses in Swarm +# +# Prerequisites: +# 1. Docker Swarm initialized: +# docker swarm init +# +# 2. Create overlay network: +# docker network create --driver overlay --attachable easyhaproxy +# +# 3. Update allowed_ips label with your actual IP addresses/networks +# +# 4. Deploy the stack: +# docker stack deploy -c ip-whitelist.yml admin +# +# 5. Test from allowed IP: +# curl http:/// +# # Response: Success (200 OK) +# +# 6. Test from non-allowed IP: +# # Response: HTTP 403 Forbidden + +version: "3.7" + +services: + haproxy: + image: byjg/easy-haproxy:4.6.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + deploy: + replicas: 1 + placement: + constraints: + - node.role == manager + environment: + EASYHAPROXY_DISCOVER: swarm + HAPROXY_USERNAME: admin + HAPROXY_PASSWORD: password + HAPROXY_STATS_PORT: 1936 + ports: + - "80:80/tcp" + - "1936:1936/tcp" + networks: + - easyhaproxy + + # Admin panel with IP restrictions + admin: + image: byjg/static-httpserver + environment: + TITLE: "Admin Panel - IP Restricted" + deploy: + replicas: 3 + labels: + easyhaproxy.http.host: "admin.example.com" + easyhaproxy.http.port: "80" + easyhaproxy.http.localport: "8080" + + # Enable IP whitelist plugin + easyhaproxy.http.plugins: "ip_whitelist" + + # Allow specific IPs and networks + # UPDATE THIS with your actual office/VPN IPs! + easyhaproxy.http.plugin.ip_whitelist.allowed_ips: "203.0.113.0/24,198.51.100.0/24,10.0.0.0/8" + + # Status code to return for blocked IPs + easyhaproxy.http.plugin.ip_whitelist.status_code: "403" + networks: + - easyhaproxy + +networks: + easyhaproxy: + external: true diff --git a/examples/swarm/jwt-validator.yml b/examples/swarm/jwt-validator.yml new file mode 100644 index 0000000..f225f52 --- /dev/null +++ b/examples/swarm/jwt-validator.yml @@ -0,0 +1,89 @@ +# JWT Validator Plugin Example for Docker Swarm +# +# This example demonstrates JWT token validation for API protection in Swarm +# +# Prerequisites: +# 1. Docker Swarm initialized: +# docker swarm init +# +# 2. Create overlay network: +# docker network create --driver overlay --attachable easyhaproxy +# +# 3. Generate JWT keys and create Docker config: +# openssl genrsa -out jwt_private.pem 2048 +# openssl rsa -in jwt_private.pem -pubout -out jwt_pubkey.pem +# docker config create jwt_api_pubkey jwt_pubkey.pem +# +# 4. Deploy the stack: +# docker stack deploy -c jwt-validator.yml api +# +# 5. Test without token (should fail): +# curl http:/// +# # Response: Missing Authorization HTTP header +# +# 6. Generate test JWT at https://jwt.io with: +# - Algorithm: RS256 +# - Payload: {"iss":"https://auth.example.com/","aud":"https://api.example.com","exp":9999999999} +# - Use your jwt_private.pem for signing +# +# 7. Test with token: +# TOKEN="eyJhbGc..." +# curl -H "Authorization: Bearer $TOKEN" http:/// +# # Response: Success + +version: "3.7" + +services: + haproxy: + image: byjg/easy-haproxy:4.6.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + configs: + - source: jwt_api_pubkey + target: /etc/haproxy/jwt_keys/api_pubkey.pem + deploy: + replicas: 1 + placement: + constraints: + - node.role == manager + environment: + EASYHAPROXY_DISCOVER: swarm + HAPROXY_USERNAME: admin + HAPROXY_PASSWORD: password + HAPROXY_STATS_PORT: 1936 + ports: + - "80:80/tcp" + - "1936:1936/tcp" + networks: + - easyhaproxy + + # Protected API service + api: + image: byjg/static-httpserver + environment: + TITLE: "Protected API - JWT Required" + deploy: + replicas: 5 + labels: + easyhaproxy.http.host: "api.example.com" + easyhaproxy.http.port: "80" + easyhaproxy.http.localport: "8080" + + # Enable JWT validator plugin + easyhaproxy.http.plugins: "jwt_validator" + + # JWT validator configuration + easyhaproxy.http.plugin.jwt_validator.algorithm: "RS256" + easyhaproxy.http.plugin.jwt_validator.issuer: "https://auth.example.com/" + easyhaproxy.http.plugin.jwt_validator.audience: "https://api.example.com" + easyhaproxy.http.plugin.jwt_validator.pubkey_path: "/etc/haproxy/jwt_keys/api_pubkey.pem" + networks: + - easyhaproxy + +networks: + easyhaproxy: + external: true + +configs: + jwt_api_pubkey: + external: true diff --git a/examples/swarm/plugins-combined.yml b/examples/swarm/plugins-combined.yml new file mode 100644 index 0000000..c9c1f59 --- /dev/null +++ b/examples/swarm/plugins-combined.yml @@ -0,0 +1,137 @@ +# Multiple Plugins Combined Example for Docker Swarm +# +# This example demonstrates using multiple plugins together for enhanced security +# +# Prerequisites: +# 1. Docker Swarm initialized: +# docker swarm init +# +# 2. Create overlay network: +# docker network create --driver overlay --attachable easyhaproxy +# +# 3. Generate JWT keys and create Docker config: +# openssl genrsa -out jwt_private.pem 2048 +# openssl rsa -in jwt_private.pem -pubout -out jwt_pubkey.pem +# docker config create jwt_api_pubkey jwt_pubkey.pem +# +# 4. Download Cloudflare IPs and create Docker config: +# curl https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst +# curl https://www.cloudflare.com/ips-v6 >> cloudflare_ips.lst +# docker config create cloudflare_ips cloudflare_ips.lst +# +# 5. Deploy the stack: +# docker stack deploy -c plugins-combined.yml production +# +# This creates three services with different security profiles: +# - Public website: Cloudflare + path blocking +# - Protected API: JWT validation + path blocking +# - Admin panel: Strict IP whitelist + +version: "3.7" + +services: + haproxy: + image: byjg/easy-haproxy:4.6.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + configs: + - source: cloudflare_ips + target: /etc/haproxy/cloudflare_ips.lst + - source: jwt_api_pubkey + target: /etc/haproxy/jwt_keys/api_pubkey.pem + deploy: + replicas: 1 + placement: + constraints: + - node.role == manager + environment: + EASYHAPROXY_DISCOVER: swarm + EASYHAPROXY_SSL_MODE: "loose" + HAPROXY_CUSTOMERRORS: "true" + HAPROXY_USERNAME: admin + HAPROXY_PASSWORD: password + HAPROXY_STATS_PORT: 1936 + ports: + - "80:80/tcp" + - "443:443/tcp" + - "1936:1936/tcp" + networks: + - easyhaproxy + + # Public website with Cloudflare + path blocking + website: + image: byjg/static-httpserver + environment: + TITLE: "Public Website" + deploy: + replicas: 4 + labels: + easyhaproxy.http.host: "website.example.com" + easyhaproxy.http.port: "80" + easyhaproxy.http.localport: "8080" + + # Cloudflare IP restoration + block sensitive paths + easyhaproxy.http.plugins: "cloudflare,deny_pages" + easyhaproxy.http.plugin.deny_pages.paths: "/admin,/wp-admin,/wp-login.php,/.env,/config" + easyhaproxy.http.plugin.deny_pages.status_code: "404" + networks: + - easyhaproxy + + # Protected API with JWT + path blocking + api: + image: byjg/static-httpserver + environment: + TITLE: "Protected API" + deploy: + replicas: 6 + labels: + easyhaproxy.http.host: "api.example.com" + easyhaproxy.http.port: "80" + easyhaproxy.http.localport: "8080" + + # JWT validation + block internal endpoints + easyhaproxy.http.plugins: "jwt_validator,deny_pages" + + # JWT configuration + easyhaproxy.http.plugin.jwt_validator.algorithm: "RS256" + easyhaproxy.http.plugin.jwt_validator.issuer: "https://auth.example.com/" + easyhaproxy.http.plugin.jwt_validator.audience: "https://api.example.com" + easyhaproxy.http.plugin.jwt_validator.pubkey_path: "/etc/haproxy/jwt_keys/api_pubkey.pem" + + # Block internal/debug paths + easyhaproxy.http.plugin.deny_pages.paths: "/internal,/debug,/metrics" + easyhaproxy.http.plugin.deny_pages.status_code: "403" + networks: + - easyhaproxy + + # Admin panel with strict IP whitelist + admin: + image: byjg/static-httpserver + environment: + TITLE: "Admin Panel" + deploy: + replicas: 2 + labels: + easyhaproxy.http.host: "admin.example.com" + easyhaproxy.http.port: "80" + easyhaproxy.http.localport: "8080" + + # IP whitelist only (strictest security) + easyhaproxy.http.plugins: "ip_whitelist" + + # Only allow office network + # UPDATE with your actual office/VPN IPs! + easyhaproxy.http.plugin.ip_whitelist.allowed_ips: "203.0.113.0/24,10.0.0.0/8" + easyhaproxy.http.plugin.ip_whitelist.status_code: "403" + networks: + - easyhaproxy + +networks: + easyhaproxy: + external: true + +configs: + cloudflare_ips: + external: true + jwt_api_pubkey: + external: true