ci(security): gitleaks config, branch-protection script, Forgejo runner setup doc
This commit is contained in:
parent
2d33e9d442
commit
bf82ba25e6
3 changed files with 197 additions and 0 deletions
31
.gitleaks.toml
Normal file
31
.gitleaks.toml
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Wakdo - configuration gitleaks (secret-scan)
|
||||||
|
#
|
||||||
|
# Utilise par :
|
||||||
|
# - le hook pre-commit local (defense en profondeur)
|
||||||
|
# - le job CI Forgejo Actions (.forgejo/workflows/, lot D) sur chaque PR -> dev
|
||||||
|
#
|
||||||
|
# Principe : etendre le jeu de regles par defaut de gitleaks, puis ne tolerer
|
||||||
|
# QUE les faux positifs explicitement justifies ci-dessous (placeholders de doc).
|
||||||
|
|
||||||
|
[extend]
|
||||||
|
useDefault = true
|
||||||
|
|
||||||
|
[allowlist]
|
||||||
|
description = "Faux positifs documentes - placeholders de configuration, jamais des secrets reels"
|
||||||
|
|
||||||
|
# Fichiers de template / doc : ne contiennent que des placeholders RFC 2606 / change_me.
|
||||||
|
paths = [
|
||||||
|
'''\.env\.example$''',
|
||||||
|
'''\.gitleaks\.toml$''',
|
||||||
|
'''docs/.*\.md$''',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Valeurs placeholder explicites tolerees ou qu'elles apparaissent.
|
||||||
|
regexes = [
|
||||||
|
'''change_me_strong_password''',
|
||||||
|
'''change_me_root_password''',
|
||||||
|
'''example\.com''',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Note : le vrai .env est gitignore et ne doit jamais etre commite. Ce scan est
|
||||||
|
# une defense en profondeur, pas un substitut a l'hygiene .gitignore.
|
||||||
102
docs/architecture/forgejo-actions-runner.md
Normal file
102
docs/architecture/forgejo-actions-runner.md
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
# Forgejo Actions - runner (act_runner)
|
||||||
|
|
||||||
|
Prerequis d'infrastructure pour la CI/CD Wakdo. Les workflows vivent dans
|
||||||
|
`.forgejo/workflows/` (lot D) ; ils ne s'executent que si un `act_runner` est
|
||||||
|
enregistre et en ligne sur le serveur.
|
||||||
|
|
||||||
|
## Pourquoi un runner separe de la stack app
|
||||||
|
|
||||||
|
La stack `docker-compose.yml` de Wakdo = runtime applicatif (web, app, db, cron).
|
||||||
|
Le runner CI est du **tooling** : il se rattache au depot Forgejo, pas a l'app.
|
||||||
|
On le fait tourner comme service dedie sur l'hote stark (meme lecon que
|
||||||
|
"gh dans Docker = mauvaise idee", cf. journal session 6). Cela evite que la CI
|
||||||
|
puisse impacter le runtime, et garde un cycle de vie independant.
|
||||||
|
|
||||||
|
## 1. Obtenir le token de registration (action manuelle, niveau admin)
|
||||||
|
|
||||||
|
Le token vient de l'instance Forgejo, pas du repo. Dans l'UI Forgejo :
|
||||||
|
|
||||||
|
- niveau **repo** : `Settings > Actions > Runners > Create new runner`
|
||||||
|
- ou niveau **org/instance** : `Site Administration > Actions > Runners`
|
||||||
|
|
||||||
|
Recuperer le `REGISTRATION_TOKEN` affiche. Il est a usage unique pour
|
||||||
|
l'enregistrement (pas a versionner).
|
||||||
|
|
||||||
|
## 2. Enregistrer le runner (sur stark)
|
||||||
|
|
||||||
|
Setup reel en place (image `simplyforma/forgejo-runner` deja presente sur
|
||||||
|
l'hote, data dir sous `$HOME` car `/srv` non inscriptible par `corentin`).
|
||||||
|
Le conteneur tourne sous l'uid de l'hote (`--user`) pour pouvoir ecrire
|
||||||
|
`.runner` dans le volume monte.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DATA=/home/corentin/forgejo-runner-wakdo
|
||||||
|
mkdir -p "$DATA"
|
||||||
|
|
||||||
|
docker run --rm \
|
||||||
|
--user "$(id -u):$(id -g)" \
|
||||||
|
-v "$DATA":/data --workdir /data \
|
||||||
|
--entrypoint forgejo-runner \
|
||||||
|
simplyforma/forgejo-runner:12.10.2 \
|
||||||
|
register --no-interactive \
|
||||||
|
--instance https://git.acadenice.com \
|
||||||
|
--token "<REGISTRATION_TOKEN>" \
|
||||||
|
--name stark-wakdo \
|
||||||
|
--labels 'docker:docker://node:20-bookworm,php-ci:docker://php:8.3-cli'
|
||||||
|
```
|
||||||
|
|
||||||
|
L'enregistrement ecrit `$DATA/.runner` (contient le secret du runner - ne pas
|
||||||
|
versionner, ne pas sortir de l'hote). Runner enregistre le 2026-06-15
|
||||||
|
(uuid `e4a3dbef-...`, labels `docker` + `php-ci`).
|
||||||
|
|
||||||
|
## 3. Lancer le runner en service
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DATA=/home/corentin/forgejo-runner-wakdo
|
||||||
|
DOCKER_GID=$(stat -c '%g' /var/run/docker.sock)
|
||||||
|
|
||||||
|
docker run -d --restart=always \
|
||||||
|
--name forgejo-runner-wakdo \
|
||||||
|
--user "$(id -u):$(id -g)" \
|
||||||
|
--group-add "$DOCKER_GID" \
|
||||||
|
-e HOME=/data \
|
||||||
|
-v "$DATA":/data --workdir /data \
|
||||||
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||||
|
--entrypoint forgejo-runner \
|
||||||
|
simplyforma/forgejo-runner:12.10.2 \
|
||||||
|
daemon
|
||||||
|
```
|
||||||
|
|
||||||
|
Notes :
|
||||||
|
- `--group-add $DOCKER_GID` : acces au socket Docker pour executer les jobs
|
||||||
|
dans des conteneurs (sans tourner en root).
|
||||||
|
- `-e HOME=/data` : evite l'erreur `mkdir /.cache: permission denied` (le cache
|
||||||
|
server interne ecrit sous `$HOME`).
|
||||||
|
- Verifier `docker logs forgejo-runner-wakdo` : `declared successfully` +
|
||||||
|
`[poller] launched`, et `Settings > Actions > Runners` doit montrer `stark-wakdo` **Idle**.
|
||||||
|
- Prerequis cote depot : **Actions activees** (`Settings > Actions` du depot).
|
||||||
|
|
||||||
|
## 4. Labels et usage en workflow
|
||||||
|
|
||||||
|
Les jobs ciblent un label via `runs-on`. Pour la CI PHP de Wakdo :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
jobs:
|
||||||
|
ci:
|
||||||
|
runs-on: docker # image par defaut node:20-bookworm
|
||||||
|
# les etapes installent/php via le conteneur ou une action setup-php
|
||||||
|
```
|
||||||
|
|
||||||
|
## Securite du runner
|
||||||
|
|
||||||
|
- Le `.runner` (secret) reste sur l'hote, hors du repo.
|
||||||
|
- Le socket Docker monte donne un acces privilegie : le runner ne doit executer
|
||||||
|
que des workflows du depot Wakdo (runner dedie au repo, pas partage).
|
||||||
|
- Roter le secret = re-enregistrer avec un nouveau token et supprimer l'ancien
|
||||||
|
runner dans l'UI.
|
||||||
|
|
||||||
|
## Lien avec les autres lots
|
||||||
|
|
||||||
|
- **Lot C** : ce document + prerequis infra.
|
||||||
|
- **Lot D** : `.forgejo/workflows/ci.yml` (PHPUnit + PHPStan + secret-scan gitleaks)
|
||||||
|
et auto-merge des PR sur CI verte (strategie solo dev validee).
|
||||||
64
scripts/forgejo-branch-protection.sh
Executable file
64
scripts/forgejo-branch-protection.sh
Executable file
|
|
@ -0,0 +1,64 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Wakdo - applique (idempotent) les regles de protection de branche sur Forgejo.
|
||||||
|
#
|
||||||
|
# Pourquoi un script versionne : la regle de gouvernance devient reproductible
|
||||||
|
# et auditable (Cr 7.b), pas un clic dans une UI. Roter le token = editer .env.
|
||||||
|
#
|
||||||
|
# Regle posee :
|
||||||
|
# - main et dev : push direct interdit (PR obligatoire), force-push bloque
|
||||||
|
# - required_approvals = 0 (travail solo : on ne peut pas approuver sa propre PR)
|
||||||
|
# - status check : OPTIONNEL via REQUIRE_CI=1, contextes dans CI_CONTEXTS
|
||||||
|
# (a activer en lot D, une fois les jobs .forgejo/workflows/ nommes ;
|
||||||
|
# activer avant que le workflow n'existe bloquerait tout merge)
|
||||||
|
#
|
||||||
|
# Usage :
|
||||||
|
# scripts/forgejo-branch-protection.sh # baseline (PR requise)
|
||||||
|
# REQUIRE_CI=1 CI_CONTEXTS='ci' scripts/forgejo-branch-protection.sh # + CI verte requise
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO_API="https://git.acadenice.com/api/v1/repos/AcadeNice/corentin_wakdo"
|
||||||
|
ENV_FILE="$(cd "$(dirname "$0")/.." && pwd)/.env"
|
||||||
|
|
||||||
|
TOKEN="$(grep -E '^FORGEJO_TOKEN=' "$ENV_FILE" | cut -d= -f2-)"
|
||||||
|
if [ -z "${TOKEN:-}" ]; then
|
||||||
|
echo "ERREUR : FORGEJO_TOKEN absent de $ENV_FILE" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
REQUIRE_CI="${REQUIRE_CI:-0}"
|
||||||
|
CI_CONTEXTS="${CI_CONTEXTS:-ci}"
|
||||||
|
|
||||||
|
# Construit le tableau JSON des contextes de status check si REQUIRE_CI=1.
|
||||||
|
status_check_json="false"
|
||||||
|
contexts_json="[]"
|
||||||
|
if [ "$REQUIRE_CI" = "1" ]; then
|
||||||
|
status_check_json="true"
|
||||||
|
contexts_json="$(printf '%s' "$CI_CONTEXTS" | awk -F, '{printf "["; for(i=1;i<=NF;i++){printf "%s\"%s\"", (i>1?",":""), $i}; printf "]"}')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
for branch in main dev; do
|
||||||
|
payload=$(cat <<JSON
|
||||||
|
{
|
||||||
|
"branch_name": "$branch",
|
||||||
|
"enable_push": false,
|
||||||
|
"enable_force_push": false,
|
||||||
|
"required_approvals": 0,
|
||||||
|
"enable_status_check": $status_check_json,
|
||||||
|
"status_check_contexts": $contexts_json
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
)
|
||||||
|
# PATCH si la protection existe, sinon POST pour la creer.
|
||||||
|
if curl -sf -o /dev/null -H "Authorization: token $TOKEN" "$REPO_API/branch_protections/$branch"; then
|
||||||
|
method=PATCH; url="$REPO_API/branch_protections/$branch"
|
||||||
|
else
|
||||||
|
method=POST; url="$REPO_API/branch_protections"
|
||||||
|
fi
|
||||||
|
echo "[$branch] $method (status_check=$status_check_json contexts=$contexts_json)"
|
||||||
|
curl -s -X "$method" -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
|
||||||
|
-d "$payload" "$url" >/dev/null
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "OK - protections appliquees sur main et dev."
|
||||||
Loading…
Add table
Reference in a new issue