Confidentialite¶
Le code source constitue la propriété intellectuelle de l'organisation. Ce chapitre applique le modèle de classification et zones de confiance au service SCM, au niveau Confidentiel.
Rappel du niveau Confidentiel¶
| Propriété | Exigence |
|---|---|
| Accès | Restreint par rôle (RBAC) |
| Authentification | SSO + MFA obligatoire |
| Chiffrement | At-rest et in-transit |
| Journalisation | Détaillée, avec retention minimum 1 an |
| Revue d'accès | Periodique (trimestrielle) |
| Isolation réseau | Zone Chaîne logicielle uniquement |
Pour le detail complet du modèle, voir :
Permissions par dépôt¶
Modèle de rôles Gitea¶
| Rôle | Permissions | Usage |
|---|---|---|
| Owner | Administration complète du dépôt | Tech lead, responsable dépôt |
| Admin | Gestion des settings, webhooks, collaborateurs | Ops, maintainers |
| Write | Push, merge PR, gérer issues | Développeurs de l'équipe |
| Read | Clone, voir le code, commenter les PR | Relecteurs, auditeurs |
Bonnes pratiques¶
- Attribuer les permissions par équipe (pas par utilisateur individuel)
- Utiliser les organisations pour regrouper les dépôts par domaine metier
- Limiter le rôle Owner a 2-3 personnes maximum par dépôt
- Désactiver la creation de dépôts par defaut (
DEFAULT_ALLOW_CREATE_ORGANIZATION = false)
; app.ini — restreindre les creations
[service]
DISABLE_REGISTRATION = true
DEFAULT_ALLOW_CREATE_ORGANIZATION = false
[repository]
MAX_CREATION_LIMIT = 0 ; seuls les admins creent des depots
Protection de branches¶
Configurer des regles de protection sur les branches critiques (main, release/*) :
| Regle | Valeur recommandee | Justification |
|---|---|---|
| Bloquer les push directs | Oui | Forcer le passage par PR |
| Approbations requises | >= 1 | Revue par un pair minimum |
| Statut CI requis | Oui | Tests passes avant merge |
| Bloquer le force push | Oui | Preserver l'historique |
| Bloquer la suppression de branche | Oui | Protéger les branches critiques |
| Commits signes requis | Recommande | Garantir l'authenticite |
Configuration via API¶
curl -X POST "https://gitea.example.com/api/v1/repos/mon-org/mon-repo/branch_protections" \
-H "Content-Type: application/json" \
-H "Authorization: token ${GITEA_ADMIN_TOKEN}" \
-d '{
"branch_name": "main",
"enable_push": false,
"enable_push_whitelist": true,
"push_whitelist_usernames": [],
"require_signed_commits": true,
"required_approvals": 1,
"enable_status_check": true,
"status_check_contexts": ["ci/build", "ci/test"],
"block_on_rejected_reviews": true,
"block_on_outdated_branch": true,
"dismiss_stale_approvals": true
}'
Commits signes (GPG / SSH)¶
La signature des commits garantit l'authenticite de l'auteur. Gitea supporte la vérification GPG et SSH.
Configurer la signature SSH (recommande)¶
# Generer une cle de signature SSH
ssh-keygen -t ed25519 -C "dev@example.com" -f ~/.ssh/signing_key
# Configurer Git pour signer avec SSH
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/signing_key.pub
git config --global commit.gpgsign true
git config --global tag.gpgsign true
Configurer la signature GPG¶
# Generer une cle GPG
gpg --full-generate-key
# Configurer Git
git config --global user.signingkey ABCDEF1234567890
git config --global commit.gpgsign true
Politique de signature dans Gitea¶
; app.ini
[repository.signing]
SIGNING_KEY = default
INITIAL_COMMIT = always
CRUD_ACTIONS = pubkey, twofa, parentsigned
MERGES = pubkey, twofa, basesigned, commitssigned
SSH vs GPG
Privilegiez la signature SSH : les développeurs ont déjà une cle SSH pour l'accès au dépôt, pas besoin de gérer une infrastructure GPG séparée.
Journal d'audit¶
Gitea enregistre les événements d'accès et de modification dans son journal d'audit.
Événements traces¶
| Événement | Niveau | Données enregistrees |
|---|---|---|
| Connexion utilisateur | Info | User, IP, méthode (local/OIDC), date |
| Echec de connexion | Warn | User tente, IP, date |
| Creation de dépôt | Info | User, org, nom du dépôt, date |
| Suppression de dépôt | Warn | User, org, nom du dépôt, date |
| Push | Info | User, dépôt, branche, commits |
| Merge de PR | Info | User, dépôt, PR, branche cible |
| Changement de permissions | Warn | User, cible, ancien rôle, nouveau rôle |
| Creation de token API | Info | User, nom du token, scopes, date |
Configuration du journal¶
; app.ini
[log]
MODE = console, file
LEVEL = info
ROOT_PATH = /data/gitea/log
[log.file]
FILE_NAME = gitea.log
MAX_SIZE = 100 ; Mo
MAX_DAYS = 365
MAX_BACKUPS = 12
COMPRESS = true
Export vers un SIEM¶
Pour centraliser les logs dans un SIEM (ELK, Loki, Splunk), configurer un sidecar Fluentd/Fluent Bit ou un volume partage :
# Fluent Bit config
[INPUT]
Name tail
Path /data/gitea/log/gitea.log
Tag gitea
[OUTPUT]
Name loki
Match gitea
Host loki.example.com
Port 3100
Labels job=gitea
Isolation réseau¶
Zone Chaîne logicielle¶
Le service SCM est déployé dans la zone Chaîne logicielle. Les flux autorises sont strictement limites :
| Source | Destination | Port | Autorisation |
|---|---|---|---|
| Zone Chaîne logicielle | Gitea | 443, 22 | Autorise |
| Zone Entreprise | Gitea | 443 | Autorise (lecture web) |
| Zone Production | Gitea | Non | Bloque |
| Internet | Gitea | Non | Bloque |
| Gitea | Keycloak | 443 | Autorise |
| Gitea | Internet | 443 | Autorise (mirroring seulement) |
Pas d'exposition publique
Gitea ne doit jamais etre expose sur Internet. Si des contributeurs externes doivent accéder au code, utiliser un miroir push vers une plateforme publique (GitHub) ou un VPN.
Firewall applicatif¶
Configurer les regles de rate limiting dans Caddy :
# Caddyfile — rate limiting
gitea.example.com {
rate_limit {
zone gitea_api {
match {
path /api/*
}
key {remote_host}
events 100
window 1m
}
}
reverse_proxy gitea:3000
}
Sauvegardes chiffrees¶
Stratégie de sauvegarde¶
| Composant | Méthode | Fréquence | Retention | Chiffrement |
|---|---|---|---|---|
| Base PostgreSQL | pg_dump + compression | Quotidien | 30 jours | AES-256 |
| Dépôts Git | gitea dump ou rsync | Quotidien | 30 jours | AES-256 |
| Stockage LFS | Snapshot MinIO | Quotidien | 30 jours | SSE-S3 |
| Configuration | Copie app.ini + secrets | À chaque changement | 90 jours | AES-256 |
Script de sauvegarde¶
#!/bin/bash
# backup-gitea.sh
set -euo pipefail
BACKUP_DIR="/srv/backups/gitea/$(date +%Y-%m-%d)"
ENCRYPTION_KEY="/etc/gitea/backup.key"
mkdir -p "${BACKUP_DIR}"
# 1. Sauvegarde PostgreSQL
podman exec gitea-postgres pg_dump -U gitea gitea | \
gzip | \
openssl enc -aes-256-cbc -salt -pbkdf2 -pass file:"${ENCRYPTION_KEY}" \
> "${BACKUP_DIR}/postgres.sql.gz.enc"
# 2. Sauvegarde Gitea (depots + config)
podman exec gitea gitea dump -c /data/gitea/conf/app.ini -f /tmp/gitea-dump.zip
podman cp gitea:/tmp/gitea-dump.zip "${BACKUP_DIR}/"
openssl enc -aes-256-cbc -salt -pbkdf2 -pass file:"${ENCRYPTION_KEY}" \
-in "${BACKUP_DIR}/gitea-dump.zip" \
-out "${BACKUP_DIR}/gitea-dump.zip.enc"
rm "${BACKUP_DIR}/gitea-dump.zip"
# 3. Nettoyage des sauvegardes > 30 jours
find /srv/backups/gitea/ -maxdepth 1 -type d -mtime +30 -exec rm -rf {} +
echo "Sauvegarde terminee : ${BACKUP_DIR}"
Prevention des fuites de secrets¶
Secret scanning¶
Empecher les développeurs de commiter accidentellement des secrets (cles API, mots de passe, tokens) :
Pre-commit hook (côté client)¶
#!/bin/bash
# .git/hooks/pre-commit
# Detecter les patterns de secrets courants
PATTERNS=(
'AKIA[0-9A-Z]{16}' # AWS Access Key
'ghp_[a-zA-Z0-9]{36}' # GitHub Personal Token
'glpat-[a-zA-Z0-9\-]{20}' # GitLab Personal Token
'sk-[a-zA-Z0-9]{48}' # OpenAI API Key
'password\s*=\s*["\x27].+' # Mot de passe en clair
'PRIVATE KEY' # Cle privee
)
for pattern in "${PATTERNS[@]}"; do
if git diff --cached --diff-filter=ACM | grep -qP "${pattern}"; then
echo "ERREUR : Secret detecte dans le commit (pattern: ${pattern})"
echo "Utilisez un gestionnaire de secrets (Vault, .env) au lieu de commiter des secrets."
exit 1
fi
done
Pre-receive hook (côté serveur)¶
Configurer un hook pre-receive sur Gitea pour bloquer les push contenant des secrets, même si le développeur n'a pas le hook local :
#!/bin/bash
# hooks/pre-receive
while read oldrev newrev refname; do
DIFF=$(git diff --diff-filter=ACM "${oldrev}..${newrev}" 2>/dev/null || git diff-tree -r --diff-filter=ACM "${newrev}")
if echo "${DIFF}" | grep -qP 'AKIA[0-9A-Z]{16}|PRIVATE KEY|password\s*='; then
echo "REJECTED: Secret detected in push to ${refname}"
exit 1
fi
done
Defense en profondeur
Le secret scanning n'est pas infaillible. Combinez-le avec une rotation régulière des secrets et un gestionnaire de secrets (HashiCorp Vault) pour minimiser l'impact d'une fuite.