# CDN Zones

The [CDN Zones API](https://developer.salesforce.com/docs/commerce/commerce-api/references/zones?meta=Summary) provides for multiple use cases, ranging from bad actor targeting scenarios to security enhancement ruleset options.

The initial release of the CDN API supports the Content Delivery domain, and focuses on security improvements. Over time, Salesforce expects the CDN API to support other features, many of which we currently provide in the Business Manager eCDN.

Business Manager and the CDN Zones API manage the same eCDN zones. Use whichever fits your workflow:

- Use **Business Manager** for interactive, point-and-click setup and management. See [Create an eCDN Zone](https://help.salesforce.com/s/articleView?id=cc.b2c_creating_a_zone.htm\&language=en_US\&type=5).
- Use the **CDN Zones API** for scripted, repeatable, or self-service setup. For example, upload custom certificates to test a Shopper Commerce API (SCAPI) implementation, or configure vanity hostnames across instances.

:::note
There's one SCAPI zone for Development, Staging, and Production. SCAPI zone controls aren't available through Business Manager or the CDN Zones API on Development or Staging. Configure the SCAPI zone from the Production instance. See [SCAPI Zone](/docs/commerce/b2c-commerce/guide/cdn-zones-scapi.md). For the Business Manager click path, see [SCAPI Zone Support for B2C Commerce](https://help.salesforce.com/s/articleView?id=cc.b2c_scapi_zone.htm\&language=en_US\&type=5).

A proxy zone is per instance. A proxy zone in Production doesn't automatically replicate a corresponding proxy zone in the Development or Staging instances. See [Storefront Zone Creation](#storefront-zone-creation) and [Embedded CDN Overview](https://help.salesforce.com/s/articleView?id=cc.b2c_embedded_cdn_overview.htm\&language=en_US\&type=5).
:::

The CDN Zones API configures and manages development, staging, and production eCDN zones programmatically. Zones that you create with the API also appear in Business Manager (available in the 24.4 release and later), so you can mix the two management paths.

:::note
Since the introduction of [Selective Origin Shielding](https://help.salesforce.com/s/articleView?id=commerce.rn_b2c_selective_origin_shielding_w9698195\_21\_8\_je.htm\&type=5) and [Origin Shielding](https://help.salesforce.com/s/articleView?id=000391803\&type=1), all traffic through eCDN enforces origin shielding. This enforcement applies to all configured instances.
:::

## General Usage Guidelines

When defining API methods, keep the following in mind:

- POST methods can return a **409 Conflict** response status code when a call encounters an existing rule with the same **type** and **action**.
- Changing rules using the PUT method overwrites existing values. When updating a rule using the PUT method, make sure to include all desired values in a list payload, not just the values you want to change.

## Storefront Zone Creation

Before you call the CDN Zones API, get a short code, an API client ID, and an authorization token. For the short code, see [Base URL and Request Formation](/docs/commerce/b2c-commerce/guide/base-url.md#short-code). For the API client ID and token, see the [CDN Zones API](https://developer.salesforce.com/docs/commerce/commerce-api/references/zones?meta=Summary).

When you obtain the authorization token, make sure the tenant ID matches the instance you're configuring:

- For development, use `<realm>_dev`.
- For staging, use `<realm>_stg`.
- For production, use `<realm>_prd`.

Use the returned values on later calls as `{shortcode}` and `{organizationId}`. The organization ID uses that same instance suffix. See [Instance ID](/docs/commerce/b2c-commerce/guide/base-url.md#instance-id).

Use the [B2C CLI](/docs/commerce/b2c-commerce/guide/b2c-developer-tooling.md):

```bash
# Required scopes: sfcc.cdn-zones.rw
export SFCC_CLIENT_ID='your-account-manager-client-id'
export SFCC_CLIENT_SECRET='your-account-manager-client-secret'
export SFCC_SHORTCODE='your-short-code'

npx @salesforce/b2c-cli ecdn zones create \
  --tenant-id abcd_stg --domain-name www.example.com
```

When you create a new storefront zone, it is created as a proxy zone and is configured with a `zoneName` that ends in `ecdn.net`. Use separate zones for development, staging, and production instances. A proxy zone in Production doesn't automatically replicate a corresponding proxy zone in the Development or Staging instances.

You can also create each zone with [createStorefrontZone](https://developer.salesforce.com/docs/commerce/commerce-api/references/zones?meta=createStorefrontZone), once per domain name. For example, call it with `{"domainName": "mystore.com"}` and `{"domainName": "mystore.co.uk"}`. The response contains the zone name and the zone ID that you use to certify each hostname. Zone names use the format `stg-<realm_id>-<dashed-domain>.cc-ecdn.net`, for example `stg-abcd-mystore-com.cc-ecdn.net` and `stg-abcd-mystore-co-uk.cc-ecdn.net`. To list zones and zone IDs, call [getZonesInfo](https://developer.salesforce.com/docs/commerce/commerce-api/references/zones?meta=getZonesInfo) and page with the `offset` or `limit` query parameters.

For each storefront zone that you create, you must create a custom hostname and update your storefront’s DNS records to send traffic to that custom hostname (CNAME):

1. Determine your custom hostname, for example: `examplecustomhost.com`.
2. Certify the hostname. For a self-managed certificate, see [eCDN Custom Certificates](/docs/commerce/b2c-commerce/guide/cdn-zones-custom-certs.md). For an eCDN managed certificate, see [eCDN Automatic Certificates](/docs/commerce/b2c-commerce/guide/cdn-zones-automatic-certs.md).
3. Get the DNS CNAME record value from [getZonesInfo](https://developer.salesforce.com/docs/commerce/commerce-api/references/zones?meta=getZonesInfo)'s name property. For example: `www.example.com CNAME commcloud.prod-abcd-example-com.cc-ecdn.net`
4. Configure your DNS to send traffic to the zone with your custom hostname (CNAME). For example: `prod-bcnx-examplecustomhost-com.cc-ecdn.net`. For the Business Manager path, including a root domain and HTTP and HTTPS redirects, see [DNS Mapping for eCDN Zones in B2C Commerce](https://help.salesforce.com/s/articleView?id=cc.b2c_dns_mapping_for_ecdn_zones.htm\&language=en_US\&type=5) and [Map DNS to an eCDN Zone for B2C Commerce](https://help.salesforce.com/s/articleView?id=cc.b2c_map_dns_to_ecdn_zone.htm\&language=en_US\&type=5).

See [Create an eCDN Zone](https://help.salesforce.com/s/articleView?id=cc.b2c_creating_a_zone.htm\&language=en_US\&type=5) for details on creating zones using Business Manager.

## Validate the Hostname and Cut Over DNS

After you create the zone and certificate, validate each hostname and update DNS to cut site traffic over to eCDN. You can optionally stack a third-party CDN, such as Akamai, in front.

### Pre-validate the hostname

Pre-validation is optional. It is required if you want to avoid downtime when cutting traffic over to eCDN, or if you want to stack a third-party CDN such as Akamai.

For each hostname, submit the TXT records to your DNS provider to validate control over the domain. The TXT record name and value are listed in the response of [getCertificates](https://developer.salesforce.com/docs/commerce/commerce-api/references/zones?meta=getCertificates) for a hostname that isn't validated.

Example TXT validation record:

```txt
_cf-custom-hostname.stg.mystore.com. IN TXT 3adc7a39-12d7-4baf-be1b-c5ea5295181b
```

If B2C Commerce Engineering completed the eCDN configurations, they provide the TXT validation record.

:::important
Submit validation records as soon as possible. After the configurations are created, automated validation checks run up to 4 hours apart for 7 days. If you don't complete validation within 7 days, you can request that B2C Commerce Engineering manually restart the validation checks.
:::

### Update DNS

To send traffic directly to eCDN, update DNS to the CNAME values. The CNAME target uses this format: `commcloud.<zone_name>`. Step 3 of [Storefront Zone Creation](#storefront-zone-creation) shows an example.

:::note
If you don't pre-validate the hostname, pointing traffic directly to eCDN serves as validation. This approach results in downtime for the period between when you update DNS and the next validation check.
:::

### Stack a third-party CDN

Stacking a third-party CDN requires a validated hostname. Connections to eCDN must use Server Name Indication (SNI).

- On Akamai, SNI support for upstream connections is disabled by default. Refer to the Akamai [documentation on configuring Origin Server behavior](https://techdocs.akamai.com/property-mgr/docs/the-third-party-origin#4-set-up-the-origin-server-behavior), and enable the SNI Transport Layer Security (TLS) Extension.
- For all other CDNs, work with the CDN provider to determine how to enable SNI to the origin if it's not enabled by default. For guidance on suggested Business Manager settings, see [Configure an External CDN or Third-Party Proxy](https://help.salesforce.com/s/articleView?id=cc.b2c_configuring_an_external_cdn.htm\&language=en_US\&type=5). Use the target value from the CNAME as the origin server.

### Delete the TXT validation records

Before you delete the records, confirm that the hostname is validated and that traffic is flowing through eCDN.

### After cutover

B2C Commerce Engineering services include lockdown protections for production and development instances. Business Manager supports eCDN for staging instances, so Business Manager traffic goes through only your Business Manager hostname, for example `staging-<realm>-<customer>.demandware.net`.

Revert to the `*.demandware.net` certificate at the origin when a custom certificate is installed on the staging POD. B2C Commerce Engineering validates that traffic is flowing through eCDN for the configured hostnames, then reverts the origin certificate to the standard `*.demandware.net` certificate so the Salesforce Commerce API can connect to the staging instance.

B2C Commerce Engineering creates and activates the staging Business Manager zone. If you created the eCDN zone and certificate yourself, contact [Salesforce Support](https://help.salesforce.com/s/articleView?id=002619633\&type=1) and ask them to have Engineering create that zone. Engineering creates it automatically when the staging instance already has a custom certificate. To opt out, contact [Salesforce Support](https://help.salesforce.com/s/articleView?id=002619633\&type=1).

## Access Control Usage Guidelines

Access control rules should now be configured using eCDN custom rules. When configuring access control rules, keep the following in mind:

- When specifying more than one IP address or Country Code value in an allowlist or blocklist, include them all in a single expression using the `in` operator and list notation. This practice makes sure that you do not issue more calls than necessary when a rule is employed. For details, see the [eCDN Custom Rules guide.](https://developer.salesforce.com/docs/commerce/commerce-api/guide/cdn-zones-custom-rules.md)

- You can specify any two-letter combination as a Country Code. However, the API recognizes only valid Country Codes in ISO 3166-1 alpha-2 (two-letter code) format. For more information, see the International Organization for Standardization (ISO) [3166 Country Code page](https://www.iso.org/iso-3166-country-codes.html).

- Regardless of their use, any Country Codes for countries embargoed or sanctioned by the United States remain blocked. For more information, see the US Department of Commerce [Bureau of Industry and Security page](https://www.bis.doc.gov/index.php/policy-guidance/country-guidance/sanctioned-destinations).

- Make sure that any IP addresses that you include in Business Manager eCDN allowlists do not contradict IP Access or Regional Access deny rule settings in the CDN API.

  :::note
  Allowlist settings in Business Manager override any contradicting rules in the CDN API.
  :::

- IP and Regional access rules execute in a specific order: 1) embargoed countries (no override due to platform compliance), 2) IP access lists in Business Manager, 3) CDN API IP access deny lists, 4) CDN API Regional Access allowlists, and 5) any customer-requested IP or Regional blocking by Salesforce.

:::note
When using firewall rules, all remaining traffic following any configured allowlist rules was blocked. Custom rules provide more flexibility and allow you to control this behavior as needed.
:::

## CDN Stacking

The CDN API can enforce that all traffic navigates through a third-party proxy into the eCDN before accessing the B2C Commerce infrastructure. In the following use case, an architect wants to stack another, third-party CDN, or any cloud proxy, in front of the B2C Commerce eCDN and leverage features of that third-party proxy.

### Create a CDN Stacking Rule

To create a CDN stacking rule, use the following method:

`POST /organizations/{organizationId}/zones/{zoneId}/firewall-custom/rules`

Example body:

```json
{
  "description": "IP Allowlist",
  "expression": "(ip.src in {123.123.0.0/32 123.123.0.1/32 123.124.127.0/32})",
  "actions": ["skip_custom_rules"]
}
```

For more information on creating allowlists using custom rules, refer to the [eCDN Custom Rules guide.](https://developer.salesforce.com/docs/commerce/commerce-api/guide/cdn-zones-custom-rules.md)

### Update a CDN Stacking Rule

To update an existing CDN stacking rule, use the following method to obtain the specific rule ID that you want to update:

`GET /organizations/{organizationId}/zones/{zoneId}/firewall-custom/rules`

Include the rule ID in the following method to update the rule:

`PATCH /organizations/{organizationId}/zones/{zoneId}/firewall-custom/rules/{ruleId}`

Example body:

```json
{
  "expression": "(ip.src in {123.123.0.0 123.123.0.1 123.124.127.0})"
}
```

## IP Access Control

The API provides the ability to use a blocklist to deny specific CIDR or IP addresses. The API can prevent known bad actors from accessing the storefront as they attempt to harm or access your web application.

### Create an Access Control Rule

To create an access control rule, use the following method:

`POST /organizations/{organizationId}/zones/{zoneId}/firewall-custom/rules`

Example body:

```json
{
  "description": "IP Blocklist",
  "expression": "(ip.src in {123.123.0.0/32 123.123.0.1/32 123.124.127.0/32})",
  "actions": ["block"]
}
```

### Update an Access Control Rule

To update an existing access control rule, use the following method to obtain the specific rule ID that you want to update:

`GET /organizations/{organizationId}/zones/{zoneId}/firewall-custom/rules`

Include the rule ID in the following method to update the rule:

`PATCH /organizations/{organizationId}/zones/{zoneId}/firewall-custom/rules/{ruleId}`

Example body:

```json
{
  "expression": "(ip.src in {123.123.0.0 123.123.0.1 123.124.127.0})"
}
```

## Region Access Control

The API provides the ability to block or allow traffic from specific countries. The API can restrict storefront access to certain countries. In the following use case, a security-conscious eCom director wants to limit orders to within the United Kingdom, and disallow orders from outside of this region.

### Create a Region Access Control Rule

To create a region access control rule, use the following method:

`POST /organizations/{organizationId}/zones/{zoneId}/firewall-custom/rules`

Example body:

```json
{
  "description": "Country Allowlist",
  "expression": "(ip.geoip.country in {\"UK\"})",
  "actions": ["skip_custom_rules"]
}
```

### Update a Region Access Control Rule

To update an existing access control rule, use the following method to obtain the specific rule ID that you want to update:

`GET /organizations/{organizationId}/zones/{zoneId}/firewall-custom/rules`

Include the rule ID in the following method to update the rule:

`PATCH /organizations/{organizationId}/zones/{zoneId}/firewall-custom/rules/{ruleId}`

Example body:

```json
{
  "expression": "(ip.geoip.country in {\"UK\" \"US\"})"
}
```

## Site Testing

To test changes before pushing to a production instance, create a custom hostname for your Development instance.

## Application Firewall Rule Enhancements

Company security teams want to safeguard their storefront against a landscape in which application attacks continually change. In this use case, the API enables the team to address existing attack vectors, and provides protections against new vulnerabilities as Salesforce updates the ruleset. To enable Salesforce to manage these rulesets for you, use “Default” as the action in the API.

:::note
The API updates each rule individually, and reports back if an error occurs. However, when using the ruleset group method to change an action, we recommend that you check that all rules update appropriately as a best practice. If you determine that a rule was updated inappropriately, rerun the group change.
:::

When turning on a Web Application Firewall (WAF) group, we recommend the following general process:

1. Put the group in monitor mode for 7 days.
2. Check logs for any triggered WAF events.
3. Check that the WAF rule would stop bad actors properly, or if any WAF rules were triggered incorrectly.
4. Change the group to default mode.
5. Check the default setting for any rules triggered over the monitoring period, and adjust as necessary. For example, if the default setting for a triggered rule is “monitor,” change the rule setting to “challenge” or “block”.

### Turn a WAF Group On in Monitor Mode

To update an existing access control rule, use the following method to obtain the specific rule ID that you want to update:

`GET /organizations/{organizationId}/zones/{zoneId}/waf/groups`

Include the group ID in the following method to turn on the group, and place it in **monitor** mode:

`PUT /organizations/{organizationId}/zones/{zoneId}/waf/groups/{groupId}`

Example body:

```json
{
  "action": "monitor",
  "mode": "on"
}
```

### Check WAF Rule Settings

Use the following method to obtain a list of all WAF rules, and locate the rule ID of the rule that you want to check:

`GET /organizations/{organizationId}/zones/{zoneId}/waf/rules`

Include the rule ID in the following method to view information specific to the rule:

`GET /organizations/{organizationId}/zones/{zoneId}/waf/rules/{ruleId}`

### Set a WAF Group to Default Mode

Use the following method to obtain a list of all WAF groups, and locate the group ID of the group that you want to set to default mode:

`GET /organizations/{organizationId}/zones/{zoneId}/waf/groups`

Include the group ID in the following method to turn on the group, and place it in **default** mode:

`PUT /organizations/{organizationId}/zones/{zoneId}/waf/groups/{groupId}`

Example body:

```json
{
  "action": "default",
  "mode": "on"
}
```

### Modify a WAF Rule

Use the following method to obtain a list of all WAF rules in a WAF group, and locate the rule ID of the rule that you want to modify:

`GET /organizations/{organizationId}/zones/{zoneId}/waf/rules`

Include the rule ID in the following method to modify the rule:

`PUT /organizations/{organizationId}/zones/{zoneId}/waf/rules/{ruleId}`

Example body:

```json
{
  "action": "challenge"
}
```

## Brotli Compression

Brotli is a compression algorithm developed by Google. Developed to decrease the size of transmissions, and best used for text compression, Brotli compression is applied intelligently for large files to reduce downloaded bytes to the browser and improve site performance.

Use the following method to obtain the current state of the API speed settings:

`GET /organizations/{organizationId}/zones/{zoneId}/speed-settings`

To modify the Brotli compression setting:

`PATCH /organizations/{organizationId}/zones/{zoneId}/speed-settings`

Example body:

```json
{
  "brotliCompression": "on"
}
```

## HTTP/2 Prioritization

HTTP/2 is a major revision of the HTTP network protocol. When enabled, HTTP/2 is used on supporting browsers to decrease latency and improve browser page load speed.

Use the following method to obtain the current state of the API speed settings:

`GET /organizations/{organizationId}/zones/{zoneId}/speed-settings`

To modify the HTTP/2 prioritization setting:

`PATCH /organizations/{organizationId}/zones/{zoneId}/speed-settings`

Example body:

```json
{
  "http2Prioritization": "on"
}
```

## Rule Firing Investigation

Using the WAF eCDN logs in Business Manager, view which firewall rules are firing. By knowing the rule ID, use the CDN API endpoints to obtain context and details about why a specific rule is firing for a given HTTP request.

## Glossary of Terms

**Cache**: Where the CDN stores copies of resources that it returns to end users. What the cache stores, and for how long, is determined by the cache-control headers returned by the origin. By default, only static content is stored in cache.

**CDN Hostname**: The part of a zone configured by clients to indicate traffic configured for the CDN (for example, `www.customer.com.cdn.cloudflare.net`). The CDN Hostname is the *target* for client hostnames. You can use this hostname to spoof host files to direct traffic to the CDN for testing purposes.

**Client**: The primary user (customer) of the CDN service.

**Client Domain**: The DNS zone owned and maintained by the client (for example, `https://www.customer.com`).

**Client Hostname**: Hostnames tied to client-owned domains that clients configure to direct traffic to the CDN hostname.

**Consumer**: The end user, that is, the consumer of the resources proxied by the CDN.

**Custom Rule**: A rule that enables the client to set up firewall policies based on various request parameters. These rules expand previous firewall rule functionality with an extended list of fields and actions. With custom rules, you have complete control over the rule expression and increased flexibility to tailor rules to your traffic needs.

**Origin**: The source of truth, meaning where actual resources are stored. The origin is what the CDN proxies and protects.

**Resource**: Any content owned and managed by the client that can be delivered using the Internet, such as web pages, images, JavaScript, CSS, fonts, and so on.

**WAF Group**: A collection of WAF rules compiled under a single unit. WAF Groups enable batch update of all rules in a particular group.

**WAF Rule**: A WAF policy designed to defend against a specific application vulnerability or attack.

**Web Application Firewall (WAF)**: Firewall that enables clients to protect the origin from various *application* level attacks, such as SQL injection, cross-site scripting (XSS), and so on. By definition, a WAF is stateless and uses a request signature to identify threats.

**Zone**: The container of hostnames and properties. Each zone is tied to a single origin.
