configure crowdsec captcha with cloudflare turnstile
This commit is contained in:
@@ -327,6 +327,7 @@
|
||||
# format: json
|
||||
access:
|
||||
enabled: true
|
||||
timezone: Europe/Paris
|
||||
# format: json
|
||||
podSecurityContext:
|
||||
runAsGroup: 65532
|
||||
|
||||
@@ -5,77 +5,6 @@
|
||||
# debugger: on_failed
|
||||
|
||||
tasks:
|
||||
- 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: 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
|
||||
- name: Setup crowdsec middleware for traefik
|
||||
include_role:
|
||||
name: crowdsec
|
||||
@@ -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:DNS Write",
|
||||
"account:Cloudflare Tunnel Write",
|
||||
"account:Turnstile Sites Write",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user