Cache-Control für AWS CloudFront konfigurieren

Sicherheitsrelevante Cache-Direktiven per Cache Policy und CloudFront Function — no-store für Login und Dashboard, stale-while-revalidate für öffentliche Seiten.

AWS CloudFront · Schritt für Schritt

Cache-Control auf AWS CloudFront

Cache-Control steuert, wie Browser und CDNs Responses zwischenspeichern. Aus Sicherheitsperspektive ist entscheidend, dass sensible Seiten wie Login, Dashboard und API-Routen nicht gecacht werden — andernfalls können personenbezogene Daten in öffentlichen Caches landen. Cache-Control ist mit 8 von 166 Punkten ein Faktor im Wolf-Agents Web Security Check.

CloudFront bietet Cache Policies für CDN-Caching und Response Headers Policies für Browser-Cache-Header. Für routenspezifische Logik — etwa no-store nur für authentifizierte Bereiche — nutzen Sie eine CloudFront Function im Viewer-Response Event, die den Cache-Control-Header basierend auf dem URI setzt.

Wichtig: Die Cache Policy steuert, wie CloudFront selbst Objekte cacht. Die Response Headers Policy bestimmt, welchen Cache-Control-Header der Browser erhält. Beide müssen zusammenspielen: Ein no-store im Browser-Header nützt wenig, wenn CloudFront die Response trotzdem cacht.

1 Schritt 1 von 3

Cache Policy und Response Headers per Terraform

Die Cache Policy steuert das CDN-Caching — welche Parameter in den Cache Key einfließen und wie lange CloudFront Objekte cacht. Die Response Headers Policy setzt den Browser-Cache-Header. Setzen Sie override = false, damit Origin-Header (z.B. von Lambda oder Ihrem Backend) Vorrang haben und routenspezifische Direktiven nicht überschrieben werden.

terraform/cache-policy.tf Terraform
# terraform/cache-policy.tf
resource "aws_cloudfront_cache_policy" "secure" {
  name        = "secure-cache-policy"
  default_ttl = 86400    # 1 Tag
  max_ttl     = 2592000  # 30 Tage
  min_ttl     = 0

  parameters_in_cache_key_and_forwarded_to_origin {
    headers_config {
      header_behavior = "none"
    }
    cookies_config {
      cookie_behavior = "none"
    }
    query_strings_config {
      query_string_behavior = "none"
    }
  }
}

# Cache-Control Header per Response Headers Policy
resource "aws_cloudfront_response_headers_policy" "cache" {
  name = "cache-control-policy"

  custom_headers_config {
    items {
      header   = "Cache-Control"
      value    = "public, max-age=86400, stale-while-revalidate=3600"
      override = false
      # override=false: Origin Cache-Control hat Vorrang
    }
  }
}

# Distribution mit Cache Policy + Response Headers Policy
resource "aws_cloudfront_distribution" "main" {
  default_cache_behavior {
    cache_policy_id            = aws_cloudfront_cache_policy.secure.id
    response_headers_policy_id = aws_cloudfront_response_headers_policy.cache.id
    viewer_protocol_policy     = "redirect-to-https"
  }
}
Cache Policy vs. Response Headers Policy

Die Cache Policy bestimmt, wie CloudFront cacht (CDN-Ebene). Die Response Headers Policy steuert, welchen Cache-Control-Header der Browser erhält. Für sensible Routen brauchen Sie beides: Eine Cache Policy mit min_ttl = 0 und no-store im Browser-Header.

2 Schritt 2 von 3

no-store per CloudFront Function für sensible Routen

Für Login-, Dashboard-, Checkout- und API-Routen setzen Sie no-store per CloudFront Function. Die Function prüft den URI im Viewer-Response Event und überschreibt den Cache-Control-Header nur für sensible Pfade. Öffentliche Seiten behalten ihren Standard-Header aus der Response Headers Policy.

cloudfront-function-cache.js CloudFront Function
// CloudFront Function — no-store für sensible Routen
// Event: Viewer Response
function handler(event) {
  var response = event.response;
  var request = event.request;
  var uri = request.uri;

  // Sensible Routen: kein Caching
  if (uri.startsWith('/login')
    || uri.startsWith('/dashboard')
    || uri.startsWith('/api/')
    || uri.startsWith('/account')
    || uri.startsWith('/checkout')) {
    response.headers['cache-control'] = {
      value: 'no-store, no-cache, must-revalidate, private'
    };
    response.headers['pragma'] = { value: 'no-cache' };
  }

  return response;
}
terraform/cloudfront-function-cache.tf Terraform
# terraform/cloudfront-function-cache.tf
resource "aws_cloudfront_function" "cache_control" {
  name    = "cache-control-routing"
  runtime = "cloudfront-js-2.0"
  comment = "no-store für sensible Routen"
  publish = true
  code    = file("cloudfront-function-cache.js")
}

# Function an Distribution binden
resource "aws_cloudfront_distribution" "main" {
  default_cache_behavior {
    function_association {
      event_type   = "viewer-response"
      function_arn = aws_cloudfront_function.cache_control.arn
    }
  }
}
CloudFront Functions haben ein 10-KB-Code-Limit. Für einfache URI-Prüfungen ist das ausreichend. Wenn Sie komplexe Logik benötigen (z.B. Cookie-basierte Entscheidungen), nutzen Sie Lambda@Edge — beachten Sie aber die us-east-1-Einschränkung.
3 Schritt 3 von 3

Verifizierung

Prüfen Sie Cache-Control für verschiedene Routen — öffentliche Seiten sollten caching erlauben, sensible Routen müssen no-store haben. Nach jeder Änderung an der Cache Policy oder der CloudFront Function müssen Sie den CloudFront-Cache invalidieren, damit die neuen Header sofort wirksam werden. Der Wolf-Agents Web Security Check analysiert Cache-Control-Direktiven automatisch.

Terminal Verifizieren
# Cache-Control für öffentliche Seite prüfen
curl -sI https://ihre-domain.de | grep -i cache-control

# Erwartete Ausgabe:
cache-control: public, max-age=86400, stale-while-revalidate=3600

# Cache-Control für Login-Seite prüfen
curl -sI https://ihre-domain.de/login | grep -i cache-control

# Erwartete Ausgabe:
cache-control: no-store, no-cache, must-revalidate, private

# Nach Policy-Änderung: Cache invalidieren
aws cloudfront create-invalidation \
  --distribution-id E1234EXAMPLE \
  --paths "/*"

Häufige Fehler

Dashboard-Seiten in CloudFront gecacht

Ohne routenspezifische Cache-Logik speichert CloudFront auch Login- und Dashboard-Seiten. Ein anderer Nutzer könnte gecachte personenbezogene Daten sehen. Setzen Sie no-store für alle authentifizierten Routen per CloudFront Function.

override=true überschreibt Origin-Header

Mit override = true in der Response Headers Policy wird der Cache-Control-Header des Origins überschrieben. Wenn Ihre Anwendung routenspezifische Cache-Header setzt, nutzen Sie override = false, damit die Origin-Direktiven Vorrang haben.

stale-while-revalidate auf API-Routen

stale-while-revalidate zeigt kurzzeitig veraltete Daten an. Auf API-Routen kann dies zu inkonsistenten Zuständen führen — etwa wenn ein Nutzer Daten ändert, aber noch die alte Version sieht. Nutzen Sie no-store oder no-cache, must-revalidate für APIs.

Cache-Invalidierung nach Policy-Änderung vergessen

Nach einer Änderung an der Response Headers Policy liefert CloudFront weiterhin gecachte Responses mit den alten Headern aus. Erstellen Sie eine Invalidierung mit aws cloudfront create-invalidation --paths "/*" nach jeder Policy-Änderung.

Compliance-Relevanz

PCI DSS fordert, dass sensible Daten nicht in Browser-Caches gespeichert werden — no-store für Zahlungs- und Authentifizierungsseiten ist eine explizite Anforderung. DSGVO erfordert den Schutz personenbezogener Daten — gecachte Dashboard-Seiten mit Nutzerdaten verletzen die Datenschutzprinzipien. BSI IT-Grundschutz empfiehlt die Kontrolle von Caching-Verhalten für sicherheitskritische Inhalte. OWASP empfiehlt no-store für alle authentifizierten Responses. Der Wolf-Agents Web Security Check prüft Cache-Control auf korrekte Konfiguration für verschiedene Seitentypen.

Wie steht Ihre Domain bei Cache-Control?

Prüfen Sie es jetzt — kostenlos, ohne Registrierung, mit 166 Prüfpunkte.