Skip to main content
emnode / learn
Compliance Medium severity

AWS Security Hub · APIGateway

APIGateway.9: V2 stages should have access logging

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub APIGateway.9 check?

APIGateway.9 fails when an API Gateway V2 (HTTP or WebSocket) stage has no access logging configured. Access logs are distinct from execution logs — they record who called what, when, and the response, one line per request.

Why does APIGateway.9 matter?

Access logs are the request-level audit trail you reach for during an incident to trace which endpoints a compromised credential hit. A team investigating an exposed credential once found their V2 stage had eighteen months of execution metrics but zero access logs, because the settings didn't carry over when they migrated from a REST API — V1 and V2 configure logging completely differently.

How do I fix APIGateway.9?

  1. Create a CloudWatch log group and ensure the delivery permissions exist.
  2. Find stages with no access log settings and configure a destination ARN and log format via update-stage.
  3. Capture useful $context variables (requestId, identity, status, integration latency).
  4. Apply the setting through IaC so new stages are compliant at creation.

Remediation script · bash

# Verify the prerequisite first: API Gateway's account-level CloudWatch role.
# Without it, the logging setting saves but no logs ever flow.
aws apigateway get-account --query 'cloudwatchRoleArn' --output text

# Enable ERROR-level execution logging on every stage of a REST API.
REST_API=a1b2c3d4e5
for STAGE in $(aws apigateway get-stages --rest-api-id $REST_API \
  --query 'item[].stageName' --output text); do
  aws apigateway update-stage --rest-api-id $REST_API --stage-name $STAGE \
    --patch-operations op=replace,path=/*/*/logging/loglevel,value=ERROR
done

# Cap retention on the log group so storage stays bounded (do this every time you enable logging).
aws logs put-retention-policy \
  --log-group-name "API-Gateway-Execution-Logs_${REST_API}/prod" \
  --retention-in-days 90

# Example for a managed database: publish engine logs to CloudWatch (no per-event charge).
aws rds modify-db-instance --db-instance-identifier prod-db \
  --cloudwatch-logs-export-configuration 'EnableLogTypes=["error","audit"]' --apply-immediately

Full walkthrough (console steps, edge cases and verification) in the lesson Enable application and API logging.

Part of the learning path See what's happening
  • APIGateway.1 REST/WebSocket API execution logging
  • APIGateway.2 REST stages should use SSL certs for backend auth
  • APIGateway.4 API Gateway should be associated with a WAF web ACL
  • APIGateway.5 REST API cache data should be encrypted at rest
  • APIGateway.8 Routes should specify an authorization type
  • APIGateway.10 V2 integrations should use HTTPS for private connections
  • APIGateway.11 Domain names should use recommended security policies