configure crowdsec captcha with cloudflare turnstile
This commit is contained in:
@@ -327,6 +327,7 @@
|
|||||||
# format: json
|
# format: json
|
||||||
access:
|
access:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
timezone: Europe/Paris
|
||||||
# format: json
|
# format: json
|
||||||
podSecurityContext:
|
podSecurityContext:
|
||||||
runAsGroup: 65532
|
runAsGroup: 65532
|
||||||
|
|||||||
@@ -5,77 +5,6 @@
|
|||||||
# debugger: on_failed
|
# debugger: on_failed
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: Récupérer le nom du pod CrowdSec LAPI
|
- name: Setup crowdsec middleware for traefik
|
||||||
kubernetes.core.k8s_info:
|
include_role:
|
||||||
kind: Pod
|
name: crowdsec
|
||||||
namespace: tools
|
|
||||||
label_selectors:
|
|
||||||
- k8s-app = crowdsec
|
|
||||||
- type = lapi
|
|
||||||
register: crowdsec_lapi_pods
|
|
||||||
|
|
||||||
- name: Vérifier qu'un pod a été trouvé
|
|
||||||
assert:
|
|
||||||
that: crowdsec_lapi_pods.resources | length > 0
|
|
||||||
fail_msg: "Aucun pod CrowdSec LAPI trouvé dans le namespace 'tools' avec les labels 'k8s-app=crowdsec, type=lapi'."
|
|
||||||
|
|
||||||
- name: Définir le nom du pod CrowdSec LAPI
|
|
||||||
set_fact:
|
|
||||||
crowdsec_lapi_pod_name: "{{ crowdsec_lapi_pods.resources[0].metadata.name }}"
|
|
||||||
|
|
||||||
- name: Récupérer la clé API du bouncer CrowdSec
|
|
||||||
kubernetes.core.k8s_exec:
|
|
||||||
namespace: tools
|
|
||||||
pod: "{{ crowdsec_lapi_pod_name }}"
|
|
||||||
container: crowdsec-lapi
|
|
||||||
command: >
|
|
||||||
cscli bouncers add traefik-plugin
|
|
||||||
register: bouncer_key_result
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- name: Supprimer le bouncer existant en cas d'échec
|
|
||||||
kubernetes.core.k8s_exec:
|
|
||||||
namespace: tools
|
|
||||||
pod: "{{ crowdsec_lapi_pod_name }}"
|
|
||||||
container: crowdsec-lapi
|
|
||||||
command: >
|
|
||||||
cscli bouncers delete traefik-plugin
|
|
||||||
when: bouncer_key_result.failed
|
|
||||||
|
|
||||||
- name: Réessayer de récupérer la clé API
|
|
||||||
kubernetes.core.k8s_exec:
|
|
||||||
namespace: tools
|
|
||||||
pod: "{{ crowdsec_lapi_pod_name }}"
|
|
||||||
container: crowdsec-lapi
|
|
||||||
command: >
|
|
||||||
cscli bouncers add traefik-plugin
|
|
||||||
register: bouncer_key_result
|
|
||||||
when: bouncer_key_result.failed
|
|
||||||
|
|
||||||
- name: Créer le Middleware Traefik pour CrowdSec
|
|
||||||
kubernetes.core.k8s:
|
|
||||||
state: present
|
|
||||||
definition:
|
|
||||||
apiVersion: traefik.io/v1alpha1
|
|
||||||
kind: Middleware
|
|
||||||
metadata:
|
|
||||||
name: crowdsec
|
|
||||||
namespace: kube-system
|
|
||||||
spec:
|
|
||||||
plugin:
|
|
||||||
crowdsec-bouncer:
|
|
||||||
enabled: true
|
|
||||||
crowdsecMode: stream
|
|
||||||
crowdsecLapiScheme: http
|
|
||||||
crowdsecLapiHost: crowdsec-service.tools.svc.cluster.local:8080
|
|
||||||
crowdsecLapiKey: "{{ bouncer_key_result.stdout_lines[2].strip() }}"
|
|
||||||
htttTimeoutSeconds: 60
|
|
||||||
crowdsecAppsecEnabled: false
|
|
||||||
crowdsecAppsecHost: crowdsec:7422
|
|
||||||
crowdsecAppsecFailureBlock: true
|
|
||||||
crowdsecAppsecUnreachableBlock: true
|
|
||||||
forwardedHeadersTrustedIPs:
|
|
||||||
- 10.0.10.23/32
|
|
||||||
- 10.0.20.0/24
|
|
||||||
clientTrustedIPs:
|
|
||||||
- 192.168.1.0/24
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
traefik_pvc_name: traefik
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
---
|
||||||
|
- name: Inject captcha.html into Traefik PVC
|
||||||
|
block:
|
||||||
|
|
||||||
|
# ---------------------
|
||||||
|
# Scale to 0
|
||||||
|
# ---------------------
|
||||||
|
- name: Scale Traefik to 0
|
||||||
|
kubernetes.core.k8s_scale:
|
||||||
|
api_version: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
namespace: kube-system
|
||||||
|
name: traefik
|
||||||
|
replicas: 0
|
||||||
|
|
||||||
|
# ---------------------
|
||||||
|
# Create Job
|
||||||
|
# ---------------------
|
||||||
|
- name: Deploy captcha injection Job
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
state: present
|
||||||
|
namespace: kube-system
|
||||||
|
definition:
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: inject-captcha
|
||||||
|
spec:
|
||||||
|
backoffLimit: 0
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
restartPolicy: Never
|
||||||
|
volumes:
|
||||||
|
- name: traefik-data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ traefik_pvc_name }}"
|
||||||
|
containers:
|
||||||
|
- name: write-captcha
|
||||||
|
image: alpine:3.20
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
echo "Writing captcha.html into PVC..."
|
||||||
|
cat << 'EOF' > /data/captcha.html
|
||||||
|
{{ lookup('template', 'captcha.html.j2') | indent(20) }}
|
||||||
|
EOF
|
||||||
|
volumeMounts:
|
||||||
|
- name: traefik-data
|
||||||
|
mountPath: /data
|
||||||
|
|
||||||
|
# ---------------------
|
||||||
|
# Wait for job success
|
||||||
|
# ---------------------
|
||||||
|
- name: Wait for Job completion
|
||||||
|
kubernetes.core.k8s_info:
|
||||||
|
api_version: batch/v1
|
||||||
|
kind: Job
|
||||||
|
name: inject-captcha
|
||||||
|
namespace: kube-system
|
||||||
|
register: job_status
|
||||||
|
until: job_status.resources[0].status.succeeded | default(0) | int > 0
|
||||||
|
retries: 20
|
||||||
|
delay: 5
|
||||||
|
|
||||||
|
# ---------------------
|
||||||
|
# Clean Job
|
||||||
|
# ---------------------
|
||||||
|
- name: Remove captcha injection Job
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
state: absent
|
||||||
|
api_version: batch/v1
|
||||||
|
kind: Job
|
||||||
|
name: inject-captcha
|
||||||
|
namespace: kube-system
|
||||||
|
|
||||||
|
rescue:
|
||||||
|
- name: Log failure
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "An error occurred during captcha injection. Traefik will still be scaled back up."
|
||||||
|
|
||||||
|
always:
|
||||||
|
# ---------------------
|
||||||
|
# Ensure Traefik is scaled back to 1 NO MATTER WHAT
|
||||||
|
# ---------------------
|
||||||
|
- name: Ensure Traefik is scaled back to 1
|
||||||
|
kubernetes.core.k8s_scale:
|
||||||
|
api_version: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
namespace: kube-system
|
||||||
|
name: traefik
|
||||||
|
replicas: 1
|
||||||
|
wait: yes
|
||||||
|
wait_timeout: 300
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
- name: Créer le ServiceAccount pour l'authentification Vault
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
state: present
|
||||||
|
definition:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: factory-ansible-tool-crowdsec-traefik-plugin
|
||||||
|
namespace: kube-system
|
||||||
|
wait: yes
|
||||||
|
wait_timeout: 30
|
||||||
|
|
||||||
|
- name: Créer la ressource VaultAuth
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
state: present
|
||||||
|
definition:
|
||||||
|
apiVersion: secrets.hashicorp.com/v1beta1
|
||||||
|
kind: VaultAuth
|
||||||
|
metadata:
|
||||||
|
name: factory-ansible-tool-crowdsec
|
||||||
|
namespace: kube-system
|
||||||
|
spec:
|
||||||
|
method: kubernetes
|
||||||
|
mount: kubernetes
|
||||||
|
kubernetes:
|
||||||
|
role: factory_crowdsec_conf
|
||||||
|
serviceAccount: factory-ansible-tool-crowdsec-traefik-plugin
|
||||||
|
audiences:
|
||||||
|
- vault
|
||||||
|
wait: yes
|
||||||
|
wait_timeout: 30
|
||||||
|
|
||||||
|
- name: Créer la ressource VaultStaticSecret
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
state: present
|
||||||
|
definition:
|
||||||
|
apiVersion: secrets.hashicorp.com/v1beta1
|
||||||
|
kind: VaultStaticSecret
|
||||||
|
metadata:
|
||||||
|
name: factory-ansible-tool-crowdsec-turnstile-secret
|
||||||
|
namespace: kube-system
|
||||||
|
spec:
|
||||||
|
type: kv-v2
|
||||||
|
mount: kvv2
|
||||||
|
path: cms/factory/turnstile
|
||||||
|
destination:
|
||||||
|
name: factory-ansible-tool-crowdsec-traefik-plugin-captcha-params
|
||||||
|
create: true
|
||||||
|
refreshAfter: 30s
|
||||||
|
vaultAuthRef: factory-ansible-tool-crowdsec
|
||||||
|
wait: yes
|
||||||
|
wait_timeout: 30
|
||||||
|
|
||||||
|
- name: Récupérer le secret Kubernetes
|
||||||
|
kubernetes.core.k8s_info:
|
||||||
|
kind: Secret
|
||||||
|
name: factory-ansible-tool-crowdsec-traefik-plugin-captcha-params
|
||||||
|
namespace: kube-system
|
||||||
|
register: crowdsec_captcha_secret
|
||||||
|
|
||||||
|
- name: Récupérer le nom du pod CrowdSec LAPI
|
||||||
|
kubernetes.core.k8s_info:
|
||||||
|
kind: Pod
|
||||||
|
namespace: tools
|
||||||
|
label_selectors:
|
||||||
|
- k8s-app = crowdsec
|
||||||
|
- type = lapi
|
||||||
|
register: crowdsec_lapi_pods
|
||||||
|
|
||||||
|
- name: Vérifier qu'un pod a été trouvé
|
||||||
|
assert:
|
||||||
|
that: crowdsec_lapi_pods.resources | length > 0
|
||||||
|
fail_msg: "Aucun pod CrowdSec LAPI trouvé dans le namespace 'tools' avec les labels 'k8s-app=crowdsec, type=lapi'."
|
||||||
|
|
||||||
|
- name: Définir le nom du pod CrowdSec LAPI
|
||||||
|
set_fact:
|
||||||
|
crowdsec_lapi_pod_name: "{{ crowdsec_lapi_pods.resources[0].metadata.name }}"
|
||||||
|
|
||||||
|
- name: Récupérer la clé API du bouncer CrowdSec
|
||||||
|
kubernetes.core.k8s_exec:
|
||||||
|
namespace: tools
|
||||||
|
pod: "{{ crowdsec_lapi_pod_name }}"
|
||||||
|
container: crowdsec-lapi
|
||||||
|
command: >
|
||||||
|
cscli bouncers add traefik-plugin
|
||||||
|
register: bouncer_key_result
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Supprimer le bouncer existant en cas d'échec
|
||||||
|
kubernetes.core.k8s_exec:
|
||||||
|
namespace: tools
|
||||||
|
pod: "{{ crowdsec_lapi_pod_name }}"
|
||||||
|
container: crowdsec-lapi
|
||||||
|
command: >
|
||||||
|
cscli bouncers delete traefik-plugin
|
||||||
|
when: bouncer_key_result.failed
|
||||||
|
|
||||||
|
- name: Réessayer de récupérer la clé API
|
||||||
|
kubernetes.core.k8s_exec:
|
||||||
|
namespace: tools
|
||||||
|
pod: "{{ crowdsec_lapi_pod_name }}"
|
||||||
|
container: crowdsec-lapi
|
||||||
|
command: >
|
||||||
|
cscli bouncers add traefik-plugin
|
||||||
|
register: bouncer_key_result
|
||||||
|
when: bouncer_key_result.failed
|
||||||
|
|
||||||
|
- name: Inject captcha.html into Traefik PVC
|
||||||
|
include_tasks: inject_captcha_html.yml
|
||||||
|
|
||||||
|
- name: Créer le Middleware Traefik pour CrowdSec
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
state: present
|
||||||
|
definition:
|
||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: crowdsec
|
||||||
|
namespace: kube-system
|
||||||
|
spec:
|
||||||
|
plugin:
|
||||||
|
crowdsec-bouncer:
|
||||||
|
enabled: true
|
||||||
|
logLevel: DEBUG
|
||||||
|
crowdsecMode: stream
|
||||||
|
crowdsecLapiScheme: http
|
||||||
|
crowdsecLapiHost: crowdsec-service.tools.svc.cluster.local:8080
|
||||||
|
crowdsecLapiKey: "{{ bouncer_key_result.stdout_lines[2].strip() }}"
|
||||||
|
htttTimeoutSeconds: 60
|
||||||
|
crowdsecAppsecEnabled: false
|
||||||
|
crowdsecAppsecHost: crowdsec:7422
|
||||||
|
crowdsecAppsecFailureBlock: true
|
||||||
|
crowdsecAppsecUnreachableBlock: true
|
||||||
|
forwardedHeadersTrustedIPs:
|
||||||
|
- 10.0.10.23/32
|
||||||
|
- 10.0.20.0/24
|
||||||
|
clientTrustedIPs:
|
||||||
|
- 192.168.1.0/24
|
||||||
|
- 10.42.0.0/16
|
||||||
|
captchaProvider: turnstile
|
||||||
|
captchaSiteKey: "{{ crowdsec_captcha_secret.resources[0].data.sitekey | b64decode }}"
|
||||||
|
captchaSecretKey: "{{ crowdsec_captcha_secret.resources[0].data.secret | b64decode }}"
|
||||||
|
captchaHTMLFilePath: "/data/captcha.html"
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Captcha verification</title>
|
||||||
|
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form method="POST">
|
||||||
|
<div class="cf-turnstile"
|
||||||
|
data-sitekey="{{ crowdsec_captcha_secret.resources[0].data.sitekey | b64decode }}"
|
||||||
|
data-theme="auto"
|
||||||
|
data-size="normal">
|
||||||
|
</div>
|
||||||
|
<button type="submit">Valider</button>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -71,6 +71,7 @@ module "cf_arcodange_cms_token" {
|
|||||||
"zone:Zone Settings Write",
|
"zone:Zone Settings Write",
|
||||||
"zone:DNS Write",
|
"zone:DNS Write",
|
||||||
"account:Cloudflare Tunnel Write",
|
"account:Cloudflare Tunnel Write",
|
||||||
|
"account:Turnstile Sites Write",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user