CDN Configuration Snippets for Common Scenarios cdn-configuration-snippets

This article collects practical cdn.yaml patterns for AEM as a Cloud Service. Use them together with the feature documentation for CDN traffic rules, customer-managed CDN credentials, and traffic filter rules including WAF. Deploy snippets with a Cloud Manager config pipeline.

NOTE
Replace host names, paths, IP ranges, keys, and thresholds with values that match your program. Test changes in a non-production environment before promoting them.

Customer Managed CDN customer-managed-cdn

Setting Up Edge Key Authentication for Some Domains Only edge-auth-selected-hosts

Problem: On a customer-managed CDN, you must enforce authentication for some customer hostnames while other hostnames that reach publish should stay available without that header (for example during rollout or when only one brand domain sits behind your CDN).

Solution: Require X-AEM-Edge-Key authentication only when the first hostname from X-Forwarded-Host equals your target hostname (for example example.com). The rule uses the forwardedDomain request property to perform that match and runs the authenticate action against your edge authenticator. Replace hostnames, authenticator names, and key placeholders for your program.

kind: "CDN"
version: "1"
data:
  authentication:
    authenticators:
      - name: edge-key-auth
        type: edge
        edgeKey1: ${{CDN_EDGEKEY_1}}
        edgeKey2: ${{CDN_EDGEKEY_2}}
    rules:
      - name: edge-key-auth-rule
        when: { reqProperty: forwardedDomain, equals: "example.com" }
        action:
          type: authenticate
          authenticator: edge-key-auth

Setting Up Edge Key Authentication for Requests Not Coming from VPN IPs edge-auth-trusted-ips

Problem: Setup edge key authentication for BYOCDN but allow direct access to publish domain only for VPN IPs

Solution: Require X-AEM-Edge-Key authentication only when client IP is not in the list of VPN IPs

kind: "CDN"
version: "1"
data:
  authentication:
    authenticators:
      - name: edge-key-auth
        type: edge
        edgeKey1: ${{CDN_EDGEKEY_1}}
        edgeKey2: ${{CDN_EDGEKEY_2}}
    rules:
      - name: edge-key-auth-rule
        when: { reqProperty: clientIp, notIn: ["10.0.0.1", "11.0.0.0/24", "<other VPN IPs>"] }
        action:
          type: authenticate
          authenticator: edge-key-auth

Redirects redirects

Redirecting from APEX Domain to www apex-to-www

kind: "CDN"
version: "1"
data:
 redirects:
   rules:
     - name: non-www-to-www-redirect
       when:
         reqProperty: domain
         doesNotMatch: '^www\.'
       action:
         type: redirect
         status: 301
         location:
           join:
             format: 'https://www.%s%s'
             args:
               - reqProperty: domain
               - reqProperty: url

Modifying the Cache Key cache-key

The CDN does not expose a separate “cache key” field. Because the URL participates in caching, you can split cache entries by changing the URL—for example by adding a query parameter through a request transformation.

kind: "CDN"
version: "1"
data:
  requestTransformations:
    rules:
      - name: set-request-different-cache-curl
        when:
          allOf:
            - reqProperty: tier
              equals: publish
            - reqHeader: user-agent
              matches: curl
        actions:
          - type: set
            queryParam: cache
            value: 'curl'

Redirecting to a Normalised Path trailing-slash

Send a permanent redirect when a browser requests a trailing slash on publish—for example from https://www.example.com/path/ to https://www.example.com/path.

kind: "CDN"
version: "1"
data:
  redirects:
    rules:
      - name: remove-trailing-slash
        when:
          allOf:
            - reqProperty: tier
              equals: publish
            - reqProperty: domain
              equals: www.example.com
            - reqProperty: originalPath
              matches: ^/(.+)/$
        action:
          type: redirect
          status: 301
          location:
            reqProperty: originalPath
            transform:
              - op: replace
                match: ^/(.+)/$
                replacement: https://www.example.com/\1
kind: "CDN"
version: "1"
data:
  requestTransformations:
    rules:
      - name: options-response
        when: { reqProperty: tier, equals: publish }
        actions:
        - type: set
          reqHeader: x-mycookie-info
          value:
            reqCookie: mycookie
            transform:
            - 'base64decode'
            - { op: 'replace', match: '"info":\s*"([^"]*)"', replacement: '\1'}

Cross Origin Setup cross-origin

Serving OPTIONS Requests from the CDN options-from-cdn

kind: "CDN"
version: "1"
data:
  requestTransformations:
    rules:
      - name: options-response
        when:
          allOf:
            - { reqProperty: path, like: /mypathi*  }
            - { reqProperty: method, equals: "OPTIONS" }
            - { reqHeader: Origin, equals: "https://example.com" }
        actions:
          - type: respond
            status: 200
            reason: "OK"
            headers:
              content-type: 'text/plain'
              access-control-allow-origin: { reqHeader: Origin }
              access-control-allow-methods: "*"
              access-control-allow-headers: "*"

Traffic Filters traffic-filters

Rate Limiting ASN rate-limit-asn

Problem: Per-IP rate limits can miss a distributed denial-of-service (DDoS) pattern: each address stays below the threshold, so legitimate and abusive traffic look alike at the IP layer.

Solution: Count requests by autonomous system name (clientAsName) so the limiter aggregates hosts that share the same network name. The snippet writes clientAsName to a log property on every request, then applies a rate limit on author and publish grouped by that value. Many users can share one ASN (for example a large ISP or a corporate VPN exit), so tune limits carefully and monitor CDN logs for false positives.

kind: "CDN"
version: "1"
data:
  requestTransformations:
    rules:
      - name: log-on-request
        when: "*"
        actions:
          - type: set
            logProperty: client_as_name
            value:
              reqProperty: clientAsName
  trafficFilters:
    rules:
    - name: limit-requests-client-as-name
      when:
        reqProperty: tier
        matches: "author|publish"
      rateLimit:
        limit: 60
        window: 10
        penalty: 300
        count: all
        groupBy:
          - reqProperty: clientAsName
      action: block
recommendation-more-help
fbcff2a9-b6fe-4574-b04a-21e75df764ab