Protéger un point de terminaison web avec AWS WAF

AWSBeginner
Pratiquer maintenant

Introduction

Une application web doit bloquer un chemin d'export interne tout en gardant le contrôle de santé disponible. Vous attacherez une règle de chemin, testerez si les requêtes atteignent le backend et mettrez à jour la règle avant le nettoyage.

Terminez d'abord Premiers pas avec AWS sur LabEx et Accordez le moindre privilège à un lecteur de rapports. Cette VM neuve fournit une application et un stage d'API REST indépendant ; les ressources d'API ou de réseau précédentes ne sont pas nécessaires.

Lien avec les certifications

Ce laboratoire propose une pratique des sujets d’examen suivants.

Créer une Web ACL régionale

Dans cette étape, vous définirez une règle de requête AWS WAF dans une liste de contrôle d'accès web (Web ACL). WAF inspecte les requêtes avant qu'elles atteignent l'application. L'API REST fournie possède un stage nommé qui peut être associé à une Web ACL régionale ; ce point d'entrée diffère de l'API HTTP utilisée dans le cours API/Cognito.

Ouvrez AWS View à côté de Terminal pour comparer les règles, l'association au stage et voir si chaque requête atteint le backend. Conservez la Web ACL et le stage de référence indépendants.

Une règle combine une condition de correspondance et une action. Une action par défaut s'applique lorsqu'aucune règle ne correspond. Nous bloquerons /internal/ et autoriserons les autres chemins.

Entrez dans le répertoire du projet et confirmez l'identité d'opérateur préparée. Le fichier fourni stage-arn.txt contient l'ARN du stage de l'application, pas un identifiant d'accès. La substitution de commande stocke cette valeur pour l'association ultérieure.

cd /home/labex/project
aws sts get-caller-identity --query Arn --output text
STAGE_ARN=$(cat stage-arn.txt)

Vous devez obtenir labex-sec05-operator. Avant toute association de Web ACL, l'export interne fictif atteint le backend. curl effectue une véritable requête HTTP ; -sS retire l'affichage de progression en conservant les erreurs de connexion et -w affiche le statut de réponse.

curl -sS -w '\nHTTP %{http_code}\n' http://127.0.0.1:8090/internal/export

Vous devez obtenir HTTP 200 et une réponse fictive du backend. Écrivez un fichier de règle avec un document intégré dont le marqueur est entre guillemets : les lignes entre <<'EOF' et EOF deviennent le fichier JSON exactement comme écrites. UriPath sélectionne le chemin, STARTS_WITH recherche le préfixe et NONE évite de le transformer. Les priorités numériques les plus basses s'exécutent d'abord ; cette ACL possède une règle de priorité zéro. Les réglages de visibilité désactivent les échantillons et métriques facultatifs pour cet exercice ciblé. Enregistrez les mêmes réglages dans visibility.json pour l'ACL elle-même et sa mise à jour ultérieure.

cat > rules-internal.json <<'EOF'
[{
  "Name": "block-private-export",
  "Priority": 0,
  "Action": {"Block": {}},
  "Statement": {"ByteMatchStatement": {
    "SearchString": "/internal/",
    "FieldToMatch": {"UriPath": {}},
    "PositionalConstraint": "STARTS_WITH",
    "TextTransformations": [{"Priority": 0, "Type": "NONE"}]
  }},
  "VisibilityConfig": {"SampledRequestsEnabled": false, "CloudWatchMetricsEnabled": false, "MetricName": "labex-sec05-owned-export"}
}]
EOF

Créez l'ACL régionale avec Allow par défaut. --cli-binary-format raw-in-base64-out demande à AWS CLI v2 d'interpréter SearchString comme des octets d'entrée littéraux au lieu d'attendre une chaîne base64. file:// charge le document de règle ; --query sélectionne uniquement l'identifiant de l'ACL résultante.

cat > visibility.json <<'EOF'
{
  "SampledRequestsEnabled": false,
  "CloudWatchMetricsEnabled": false,
  "MetricName": "labex-sec05-owned-export"
}
EOF

ACL_ID=$(aws wafv2 create-web-acl \
  --name labex-sec05-owned-export \
  --scope REGIONAL \
  --default-action Allow={} \
  --visibility-config file://visibility.json \
  --rules file://rules-internal.json \
  --cli-binary-format raw-in-base64-out \
  --query Summary.Id \
  --output text)
ACL_ARN=$(aws wafv2 get-web-acl \
  --name labex-sec05-owned-export \
  --scope REGIONAL \
  --id "$ACL_ID" \
  --query WebACL.ARN \
  --output text)
aws wafv2 get-web-acl \
  --name labex-sec05-owned-export \
  --scope REGIONAL \
  --id "$ACL_ID" \
  --query 'WebACL.{Name:Name,Default:DefaultAction,Rules:Rules[].Name}'

Vous devez obtenir votre ACL, Allow par défaut et block-private-export. Créer une politique ne l'attache pas à un point de terminaison. AWS View doit toujours afficher l'absence d'association à la cible.

Associer l'ACL et tester les requêtes réelles

Dans cette étape, vous relierez votre politique au stage d'API REST fourni et comparerez une requête publique avec une requête d'export correspondant à la règle. Un stage identifie un environnement d'API déployé ; l'association applique l'ACL aux requêtes de ce stage.

WAF avant le backend

La Web ACL associée rejette le chemin interne avant qu'il atteigne le backend.

Associez uniquement votre ACL à l'ARN cible fourni. Le stage de référence indépendant possède déjà sa propre ACL de référence ; ne la remplacez pas.

aws wafv2 associate-web-acl --web-acl-arn "$ACL_ARN" --resource-arn "$STAGE_ARN"
aws wafv2 get-web-acl-for-resource \
  --resource-arn "$STAGE_ARN" \
  --query WebACL.Name \
  --output text

Vous devez obtenir labex-sec05-owned-export. Testez le chemin de santé public, qui ne correspond pas à /internal/, puis le chemin d'export interne.

curl -sS -w '\nHTTP %{http_code}\n' http://127.0.0.1:8090/health
curl -sS -w '\nHTTP %{http_code}\n' http://127.0.0.1:8090/internal/export

Vous devez obtenir HTTP 200 pour la santé et HTTP 403 avec block-private-export pour l'export. Une décision Block renvoie une réponse avant l'exécution du backend. AWS View doit afficher Executed pour la requête de santé et Not reached pour la requête bloquée. Une association native seule ne suffit pas ; ces résultats HTTP réels prouvent l'application du contrôle.

Exemple AWS View : la santé atteint le backend, tandis que l'export interne est bloqué avant l'exécution.

Mettre à jour la règle et observer le comportement réel

Dans cette étape, vous déplacerez la protection vers le préfixe admin et montrerez le changement de comportement sans redémarrer l'application. Une mise à jour de Web ACL remplace la liste des règles. Son jeton de verrouillage protège contre l'écrasement d'une modification concurrente ; obtenez-le depuis la configuration native actuelle juste avant la mise à jour et conservez-le dans une variable.

Créez le nouveau document de règle en remplaçant le préfixe d'URI dans le fichier précédent. sed transforme le texte et > écrit le nouveau fichier en conservant le document de règle d'origine.

sed 's|/internal/|/admin/|' rules-internal.json > rules-admin.json
LOCK_TOKEN=$(aws wafv2 get-web-acl \
  --name labex-sec05-owned-export \
  --scope REGIONAL \
  --id "$ACL_ID" \
  --query LockToken \
  --output text)
aws wafv2 update-web-acl \
  --name labex-sec05-owned-export \
  --scope REGIONAL \
  --id "$ACL_ID" \
  --lock-token "$LOCK_TOKEN" \
  --default-action Allow={} \
  --visibility-config file://visibility.json \
  --rules file://rules-admin.json \
  --cli-binary-format raw-in-base64-out \
  --query NextLockToken \
  --output text

Le jeton de verrouillage renvoyé identifie la nouvelle révision de l'ACL ; ce n'est pas un identifiant d'authentification. L'ancien préfixe interne doit maintenant bénéficier de l'action Allow par défaut, tandis que l'export admin doit être bloqué.

curl -sS -w '\nHTTP %{http_code}\n' http://127.0.0.1:8090/internal/export
curl -sS -w '\nHTTP %{http_code}\n' http://127.0.0.1:8090/admin/export

Vous devez obtenir HTTP 200, puis HTTP 403. AWS View doit afficher le nouveau préfixe /admin/, la requête interne précédemment bloquée et la paire actuelle interne autorisée/admin bloquée. Les requêtes utilisent la règle native actuelle ; aucun redémarrage de la VM ou de l'application n'est nécessaire. Les types de politiques non pris en charge refusent l'accès dans cet environnement ciblé : utilisez donc uniquement l'instruction enseignée ici.

Exemple AWS View après la mise à jour du préfixe : l'export interne est autorisé et l'export admin est bloqué.

Détacher et supprimer uniquement votre ACL

Dans cette étape, vous retirerez votre politique et confirmerez le retour du routage ordinaire de l'application. Terminez d'abord les contrôles fonctionnels précédents. La dissociation désactive ce contrôle sur le stage ; la suppression de l'ACL retire ensuite votre ressource de politique.

Détachez votre Web ACL du stage cible et inspectez l'association avec une requête native réussie. Vous devez obtenir une association vide, plutôt que considérer une erreur d'authentification comme preuve de suppression.

aws wafv2 disassociate-web-acl --resource-arn "$STAGE_ARN"
aws wafv2 get-web-acl-for-resource --resource-arn "$STAGE_ARN" --query WebACL

L'export admin précédemment bloqué doit maintenant atteindre de nouveau le backend fourni.

curl -sS -w '\nHTTP %{http_code}\n' http://127.0.0.1:8090/admin/export

Vous devez obtenir HTTP 200. Obtenez un jeton de verrouillage actuel, supprimez uniquement votre ACL et listez avec succès les ACL restantes. Votre nom doit être absent et labex-sec05-reference doit rester présent.

LOCK_TOKEN=$(aws wafv2 get-web-acl \
  --name labex-sec05-owned-export \
  --scope REGIONAL \
  --id "$ACL_ID" \
  --query LockToken \
  --output text)
aws wafv2 delete-web-acl \
  --name labex-sec05-owned-export \
  --scope REGIONAL \
  --id "$ACL_ID" \
  --lock-token "$LOCK_TOKEN"
aws wafv2 list-web-acls --scope REGIONAL --query 'WebACLs[].Name'

Gardez les deux stages d'API fournis et l'ACL de référence intacts. Supprimez les documents locaux de règles et de visibilité, puis exécutez la vérification de cette étape avant de retirer le profil CLI jetable.

rm -f rules-internal.json rules-admin.json visibility.json
rm -f /home/labex/.aws/credentials /home/labex/.aws/config
unset STAGE_ARN ACL_ID ACL_ARN LOCK_TOKEN

Résumé

Vous avez créé une Web ACL régionale, l'avez associée à un stage d'API REST et testé le comportement HTTP réel d'autorisation et de blocage. Une requête correspondante s'est arrêtée avant le backend, tandis que les requêtes de santé ont continué. La mise à jour du préfixe d'URI a modifié le routage réel ; la dissociation a rétabli le point de terminaison. Vous avez supprimé uniquement votre ACL et conservé les stages fournis et la politique de référence.