diff --git a/.github/workflows/code_quality.yml b/.github/workflows/code_quality.yml index 39bae0d4..835fb731 100644 --- a/.github/workflows/code_quality.yml +++ b/.github/workflows/code_quality.yml @@ -75,11 +75,6 @@ jobs: # composer: "v1" # elasticsearch: "7.10.2" - - magento: "2.4.4" - php: "8.1" - composer: "v2" - opensearch: "1.2.0" - - magento: "2.4.5" php: "8.1" composer: "v2" @@ -89,7 +84,6 @@ jobs: php: "8.2" composer: "v2" opensearch: "2.5.0" - steps: - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/shielding-check-cron-manual.yaml b/.github/workflows/shielding-check-cron-manual.yaml index 0a5ea642..2f314dbc 100644 --- a/.github/workflows/shielding-check-cron-manual.yaml +++ b/.github/workflows/shielding-check-cron-manual.yaml @@ -17,10 +17,10 @@ jobs: run: | cat ./temp.json | jq . > etc/shielding/datacenters.json rm -f ./temp.json - echo "::set-output name=diff-count::$(git diff --name-only | wc -l)" + echo "diff-count=$(git diff --name-only | wc -l)" >> "$GITHUB_OUTPUT" SHA1=`sha1sum etc/shielding/datacenters.json | awk '{print $1}'` - echo "::set-output name=sha1::$SHA1" - echo "::set-output name=pr-count::$(gh pr list --search "${SHA1} in:title is:open" --json title -q '.[] | .title' | wc -l)" + echo "sha1=$SHA1" >> "$GITHUB_OUTPUT" + echo "pr-count=$(gh pr list --search "${SHA1} in:title is:open" --json title -q '.[] | .title' | wc -l)" >> "$GITHUB_OUTPUT" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Check diff and create PR diff --git a/.github/workflows/shielding-check-cron.yaml b/.github/workflows/shielding-check-cron.yaml index 6e307601..00eda98c 100644 --- a/.github/workflows/shielding-check-cron.yaml +++ b/.github/workflows/shielding-check-cron.yaml @@ -20,10 +20,10 @@ jobs: run: | cat ./temp.json | jq . > etc/shielding/datacenters.json rm -f ./temp.json - echo "::set-output name=diff-count::$(git diff --name-only | wc -l)" + echo "diff-count=$(git diff --name-only | wc -l)" >> "$GITHUB_OUTPUT" SHA1=`sha1sum etc/shielding/datacenters.json | awk '{print $1}'` - echo "::set-output name=sha1::$SHA1" - echo "::set-output name=pr-count::$(gh pr list --search "${SHA1} in:title is:open" --json title -q '.[] | .title' | wc -l)" + echo "sha1=$SHA1" >> "$GITHUB_OUTPUT" + echo "pr-count=$(gh pr list --search "${SHA1} in:title is:open" --json title -q '.[] | .title' | wc -l)" >> "$GITHUB_OUTPUT" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Check diff and create PR diff --git a/Block/GeoIp/GetAction.php b/Block/GeoIp/GetAction.php index 23b4f3d8..80b51ddb 100644 --- a/Block/GeoIp/GetAction.php +++ b/Block/GeoIp/GetAction.php @@ -18,6 +18,7 @@ * @copyright Copyright (c) 2016 Fastly, Inc. (http://www.fastly.com) * @license BSD, see LICENSE_FASTLY_CDN.txt */ + namespace Fastly\Cdn\Block\GeoIp; use Fastly\Cdn\Model\Config; @@ -60,13 +61,14 @@ class GetAction extends AbstractBlock * @param EncoderInterface $urlEncoder */ public function __construct( - Config $config, - Context $context, - Response $response, - Url $url, + Config $config, + Context $context, + Response $response, + Url $url, EncoderInterface $urlEncoder, - array $data = [] - ) { + array $data = [] + ) + { $this->config = $config; $this->response = $response; $this->url = $url; @@ -92,8 +94,8 @@ protected function _toHtml() // @codingStandardsIgnoreLine - required by parent $currentUrl = $this->url->getCurrentUrl(); $baseUrl = $this->url->getBaseUrl(); $webTypeUrl = $this->url->getBaseUrl(['_type' => Url::URL_TYPE_WEB]); - - if (strpos($currentUrl, $baseUrl) !== false) { + + if (strpos($currentUrl, rtrim($baseUrl, "/")) !== false) { $targetUrl = $currentUrl; } else { $targetUrl = str_replace($webTypeUrl, $baseUrl, $currentUrl); @@ -109,7 +111,7 @@ protected function _toHtml() // @codingStandardsIgnoreLine - required by parent $this->response->setHeader("x-esi", "1"); } // Due to Varnish parser limitations HTTPS ESIs are not supported so we need to turn them into HTTP URLs - // This does not mean that request will go over HTTP. ESI subrequest will go out to the backend that is + // This does not mean that request will go over HTTP. ESI subrequest will go out to the backend that is // currently specified so if it's HTTPS it will go over HTTPS return sprintf( '', diff --git a/Controller/Adminhtml/FastlyCdn/Logging/CreateEndpoint.php b/Controller/Adminhtml/FastlyCdn/Logging/CreateEndpoint.php index 269421c9..aa7af25d 100644 --- a/Controller/Adminhtml/FastlyCdn/Logging/CreateEndpoint.php +++ b/Controller/Adminhtml/FastlyCdn/Logging/CreateEndpoint.php @@ -29,12 +29,11 @@ use Magento\Framework\Controller\Result\JsonFactory; /** - * Class CreateEndpoint - * @package Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Logging + * Class CreateEndpoint for Logging */ class CreateEndpoint extends Action { - const ADMIN_RESOURCE = 'Magento_Config::config'; + public const ADMIN_RESOURCE = 'Magento_Config::config'; /** * @var Http @@ -113,6 +112,11 @@ public function execute() $this->getRequest()->getParam('condition_priority') ); + $selectedConditions = $this->getRequest()->getParam('conditions', ''); + if (!$condition) { + $condition = $selectedConditions; + } + $params = array_merge( $this->getRequest()->getParam('log_endpoint'), ['response_condition' => $condition] @@ -152,17 +156,18 @@ public function execute() } /** + * * @param $clone * @param $conditionName * @param $applyIf * @param $conditionPriority - * @return string|null + * @return string * @throws \Magento\Framework\Exception\LocalizedException */ private function createCondition($clone, $conditionName, $applyIf, $conditionPriority) { if (!$conditionName || !$applyIf || !$conditionPriority) { - return null; + return ''; } $condition = [ 'name' => $conditionName, diff --git a/Controller/Adminhtml/FastlyCdn/Logging/UpdateEndpoint.php b/Controller/Adminhtml/FastlyCdn/Logging/UpdateEndpoint.php index 1f9704b8..4beffd38 100644 --- a/Controller/Adminhtml/FastlyCdn/Logging/UpdateEndpoint.php +++ b/Controller/Adminhtml/FastlyCdn/Logging/UpdateEndpoint.php @@ -29,12 +29,11 @@ use Magento\Framework\Controller\Result\JsonFactory; /** - * Class UpdateEndpoint - * @package Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Logging + * Class UpdateEndpoint for Logging */ class UpdateEndpoint extends Action { - const ADMIN_RESOURCE = 'Magento_Config::config'; + public const ADMIN_RESOURCE = 'Magento_Config::config'; /** * @var Http @@ -84,6 +83,7 @@ public function __construct( } /** + * * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Json|\Magento\Framework\Controller\ResultInterface */ public function execute() @@ -114,14 +114,15 @@ public function execute() $this->getRequest()->getParam('condition_priority') ); - $params = array_merge( - $this->getRequest()->getParam('log_endpoint'), - ['response_condition' => $condition] - ); - + $selectedConditions = $this->getRequest()->getParam('conditions', ''); + if (!$condition) { + $condition = $selectedConditions; + } + $params = $this->getRequest()->getParam('log_endpoint'); $params = array_filter($params); - //Array filter removes empty strings, but empty compression_codec param turns off compression formats - if (!isset($params['compression_codec'])){ + $params['response_condition'] = $condition; + + if (!isset($params['compression_codec'])) { $params['compression_codec'] = ""; } $endpoint = $this->api->updateLogEndpoint($clone->number, $endpointType, $params, $oldName); @@ -157,17 +158,18 @@ public function execute() } /** + * * @param $clone * @param $conditionName * @param $applyIf * @param $conditionPriority - * @return string|null + * @return string * @throws \Magento\Framework\Exception\LocalizedException */ private function createCondition($clone, $conditionName, $applyIf, $conditionPriority) { if (!$conditionName || !$applyIf || !$conditionPriority) { - return null; + return ''; } $condition = [ 'name' => $conditionName, diff --git a/Documentation/Guides/Edge-Modules/EDGE-MODULE-NETACEA-INTEGRATION.md b/Documentation/Guides/Edge-Modules/EDGE-MODULE-NETACEA-INTEGRATION.md index 1a8c961e..a1b91466 100644 --- a/Documentation/Guides/Edge-Modules/EDGE-MODULE-NETACEA-INTEGRATION.md +++ b/Documentation/Guides/Edge-Modules/EDGE-MODULE-NETACEA-INTEGRATION.md @@ -12,25 +12,8 @@ After you have enabled the module it's time to configure. You will be prompted w ## Configurable options -### Netacea API Key - -This is the API key provided to you by Netacea. - -### Netacea Secret - -This is the Secret provided to you by Netacea. - -### Netacea Ignore List - -This is the list of URL paths which integration will skip and won't apply any action to requests.
-Please note that the integration will check if a request's URL path starts with a value from the list and will decide if it should be skipped.
-Example: - - Path `/skipthis` is added to the ignore list - - Integration will skip requests which paths are starting from the `/skipthis` - - This means that requests for such websites would be skipped by the integration: - - `www.domain.com/skipthis` - - `www.domain.com/skipthisalso` - - `www.domain.com/skipthis/andthistoo` +In order to configure Netacea module please see the following documentation.
+[Netacea - Fastly/Magento](https://docs.netacea.com/netacea-plugin-information/fastly-magento/installation-and-configuration) ## Enabling diff --git a/Model/Api.php b/Model/Api.php index 37322dad..42986f17 100644 --- a/Model/Api.php +++ b/Model/Api.php @@ -534,7 +534,7 @@ public function uploadSnippet($version, array $snippet) if (isset($snippet['content'])) { $adminUrl = $this->vcl->getAdminFrontName(); $adminPathTimeout = $this->config->getAdminPathTimeout(); - $ignoredUrlParameters = $this->config->getIgnoredUrlParameters(); + $ignoredUrlParameters = (string)$this->config->getIgnoredUrlParameters(); if ($ignoredUrlParameters === "") { $queryParameters = '&'; diff --git a/Model/FrontControllerPlugin.php b/Model/FrontControllerPlugin.php index 769973f1..ae3f1aba 100644 --- a/Model/FrontControllerPlugin.php +++ b/Model/FrontControllerPlugin.php @@ -135,7 +135,7 @@ public function aroundDispatch(FrontControllerInterface $subject, callable $proc return $proceed(...$args); } - $path = strtolower($this->request->getPathInfo()); + $path = strtolower($this->request->getRequestUri()); if ($isRateLimitingEnabled && $this->sensitivePathProtection($path)) { return $this->response; @@ -167,7 +167,8 @@ private function sensitivePathProtection($path) $limit = false; foreach ($limitedPaths as $key => $value) { - if (preg_match('{' . $value->path . '}i', $path) == 1) { + $value->path = str_replace("#", "\#", $value->path); + if (preg_match('#' . $value->path . '#i', $path)) { $limit = true; break; } @@ -333,26 +334,24 @@ private function verifyBots($ip) return false; } - private function readMaintenanceIp($ip) + private function readMaintenanceIp($clientIps) { $tag = self::FASTLY_CACHE_MAINTENANCE_IP_FILE_TAG; - $data = json_decode($this->cache->load($tag)); - if (empty($data)) { - $data = []; + $allowedIps = json_decode($this->cache->load($tag)); + if (empty($allowedIps)) { + $allowedIps = []; $flagDir = $this->filesystem->getDirectoryWrite(DirectoryList::VAR_DIR); if ($flagDir->isExist('.maintenance.ip')) { $temp = $flagDir->readFile('.maintenance.ip'); - $data = explode(',', trim($temp)); - $this->cache->save(json_encode($data), $tag, []); + $allowedIps = explode(',', trim($temp)); + $this->cache->save(json_encode($allowedIps), $tag, []); } } - foreach ($data as $key => $value) { - if (!empty($value) && trim($value) == $ip) { - return true; - } - } - return false; + $ips = array_map("trim", explode(",", $clientIps)); + $isAllowed = array_intersect($allowedIps, $ips); + + return !empty($isAllowed); } private function log($message) diff --git a/Model/Layout/LayoutPlugin.php b/Model/Layout/LayoutPlugin.php index af3ec849..8ff136c8 100644 --- a/Model/Layout/LayoutPlugin.php +++ b/Model/Layout/LayoutPlugin.php @@ -98,7 +98,7 @@ public function afterGenerateElements(\Magento\Framework\View\Layout $subject): public function afterGetOutput(\Magento\Framework\View\Layout $subject, $result) // @codingStandardsIgnoreLine - unused parameter { if ($this->config->getType() === Config::FASTLY) { - $this->response->setHeader("Fastly-Module-Enabled", "1.2.211", true); + $this->response->setHeader("Fastly-Module-Enabled", "1.2.217", true); } return $result; diff --git a/Model/ResponsePlugin.php b/Model/ResponsePlugin.php index 7c62b1a4..61256b22 100644 --- a/Model/ResponsePlugin.php +++ b/Model/ResponsePlugin.php @@ -79,7 +79,10 @@ public function aroundSetHeader(Http $subject, callable $proceed, $name, $value, // Make the necessary adjustment $value = $this->cacheTags->convertCacheTags(str_replace(',', ' ', $value)); $tagsSize = $this->config->getXMagentoTagsSize(); - if (strlen($value) > $tagsSize) { + + if ($tagsSize === 0) { + $value = ""; + } else if (strlen($value) > $tagsSize) { $trimmedArgs = substr($value, 0, $tagsSize); $value = substr($trimmedArgs, 0, strrpos($trimmedArgs, ' ', -1)); } diff --git a/Release-Notes.md b/Release-Notes.md index 09e366f6..9a152457 100644 --- a/Release-Notes.md +++ b/Release-Notes.md @@ -1,5 +1,31 @@ # Fastly_Cdn Release Notes +## 1.2.217 + +- Update to Netacea module https://github.com/fastly/fastly-magento2/pull/690 + +## 1.2.216 + +- Fix for GEOIP redirection causes 404 in specific cases https://github.com/fastly/fastly-magento2/pull/694 + +## 1.2.215 + +- Fix for checking if current IP is in maintenance IP list https://github.com/fastly/fastly-magento2/pull/692 + +## 1.2.214 + +- Rate limiting doesn't work correctly when store codes are involved https://github.com/fastly/fastly-magento2/pull/689 + +## 1.2.213 + +- Update Netacea Edge Module to 5.9.0 https://github.com/fastly/fastly-magento2/pull/687 +- Add support for Brotli static compression https://github.com/fastly/fastly-magento2/pull/688 + +## 1.2.212 + +- Additional fixes to log shipping menu https://github.com/fastly/fastly-magento2/pull/684 +- Updating to DataDome Fastly Module 2.19.4 https://github.com/fastly/fastly-magento2/pull/685 + ## 1.2.211 - Fix for not being able to add log shipping jobs due to bug in Fastly Magento UI https://github.com/fastly/fastly-magento2/pull/683 diff --git a/VERSION b/VERSION index 6b545a1b..8b3e1946 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.211 +1.2.217 diff --git a/composer.json b/composer.json index 0a168d90..93e15b0d 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "zordius/lightncandy": "^1.2" }, "type": "magento2-module", - "version": "1.2.211", + "version": "1.2.217", "license": "BSD-3-Clause", "autoload": { "files": [ "registration.php" ], diff --git a/etc/fastly_edge_modules/datadome_integration.json b/etc/fastly_edge_modules/datadome_integration.json index 79175026..d888b211 100644 --- a/etc/fastly_edge_modules/datadome_integration.json +++ b/etc/fastly_edge_modules/datadome_integration.json @@ -54,12 +54,12 @@ "vcl": [ { "priority": 7, - "template": "sub set_origin_header {\n if (req.backend.is_origin) {\n if (req.backend == datadome) {\n # Remove all unexpected headers\n header.filter_except(bereq, \"x-datadome-params\", \"accept-charset\", \"accept-language\", \"x-requested-with\", \"x-fl-productid\", \"x-flapi-session-id\", \"fastly-orig-accept-encoding\", \"cache-control\", \"client-id\", \"connection\", \"pragma\", \"accept\", \"headers-list\", \"host\", \"origin\", \"server-hostname\", \"server-name\", \"x-forwarded-for\", \"user-agent\", \"referer\", \"request\", \"content-type\", \"from\", \"true-client-ip\", \"via\", \"x-real-ip\", \"sec-ch-device-memory\", \"sec-ch-ua\", \"sec-ch-ua-arch\", \"sec-ch-ua-full-version-list\", \"sec-ch-ua-mobile\", \"sec-ch-ua-model\", \"sec-ch-ua-platform\", \"sec-fetch-dest\", \"sec-fetch-mode\", \"sec-fetch-site\", \"sec-fetch-user\");\n set bereq.http.x-datadome-params:key = \"{{datadome_api_key}}\";\n set bereq.http.x-datadome-params:requestmodulename = \"FastlyMagento\";\n set bereq.http.x-datadome-params:moduleversion = \"2.19.1\";\n set bereq.http.x-datadome-params:timerequest = time.start.usec;\n set bereq.http.x-datadome-params:servername = server.identity;\n set bereq.http.x-datadome-params:serverregion = server.region;\n set bereq.http.x-datadome-params:ip = urlencode(client.ip);\n set bereq.http.x-forwarded-proto = urlencode(req.protocol);\n set bereq.http.x-datadome-params:authorizationlen = std.strlen(req.http.authorization);\n # Truncating Headers - Start\n set bereq.http.accept-charset = substr(req.http.accept-charset, 0, 128);\n set bereq.http.accept-language = substr(req.http.accept-language, 0, 256);\n set bereq.http.x-requested-with = substr(req.http.x-requested-with, 0, 128);\n set bereq.http.x-fl-productid = substr(req.http.x-fl-productid, 0, 64);\n set bereq.http.x-flapi-session-id = substr(req.http.x-flapi-session-id, 0, 64);\n set bereq.http.fastly-orig-accept-encoding = substr(req.http.fastly-orig-accept-encoding, 0, 128);\n set bereq.http.cache-control = substr(req.http.cache-control, 0, 128);\n set bereq.http.client-id = substr(req.http.client-id, 0, 128);\n set bereq.http.connection = substr(req.http.connection, 0, 128);\n set bereq.http.pragma = substr(req.http.pragma, 0, 128);\n set bereq.http.accept = substr(req.http.accept, 0, 512);\n set bereq.http.headers-list = substr(req.http.headers-list, 0, 512);\n set bereq.http.host = substr(req.http.host, 0, 512);\n set bereq.http.origin = substr(req.http.origin, 0, 512);\n set bereq.http.server-hostname = substr(req.http.server-hostname, 0, 512);\n set bereq.http.server-name = substr(req.http.server-name, 0, 512);\n if( std.strlen(req.http.x-forwarded-for) \u003e 512 ) {\n # Truncate from the end\n set bereq.http.x-forwarded-for = substr(req.http.x-forwarded-for, -512);\n } else {\n set bereq.http.x-forwarded-for = req.http.x-forwarded-for;\n }\n set bereq.http.user-agent = substr(req.http.user-agent, 0, 768);\n set bereq.http.referer = substr(req.http.referer, 0, 1024);\n set bereq.http.request = substr(req.http.request, 0, 2048);\n set bereq.http.content-type = substr(req.http.content-type, 0, 128);\n set bereq.http.from = substr(req.http.from, 0, 128);\n set bereq.http.true-client-ip = substr(req.http.true-client-ip, 0, 128);\n set bereq.http.via = substr(req.http.via, 0, 256);\n set bereq.http.x-real-ip = substr(req.http.x-real-ip, 0, 128);\n set bereq.http.sec-ch-device-memory = substr(req.http.sec-ch-device-memory, 0, 8);\n set bereq.http.sec-ch-ua = substr(req.http.sec-ch-ua, 0, 128);\n set bereq.http.sec-ch-ua-arch = substr(req.http.sec-ch-ua-arch, 0, 16);\n set bereq.http.sec-ch-ua-full-version-list = substr(req.http.sec-ch-ua-full-version-list, 0, 256);\n set bereq.http.sec-ch-ua-mobile = substr(req.http.sec-ch-ua-mobile, 0, 8);\n set bereq.http.sec-ch-ua-model = substr(req.http.sec-ch-ua-model, 0, 128);\n set bereq.http.sec-ch-ua-platform = substr(req.http.sec-ch-ua-platform, 0, 32);\n set bereq.http.sec-fetch-dest = substr(req.http.sec-fetch-dest, 0, 32);\n set bereq.http.sec-fetch-mode = substr(req.http.sec-fetch-mode, 0, 32);\n set bereq.http.sec-fetch-site = substr(req.http.sec-fetch-site, 0, 64);\n set bereq.http.sec-fetch-user = substr(req.http.sec-fetch-user, 0, 8);\n # Truncating Headers - End\n if (req.http.x-datadome-clientid) {\n set bereq.http.x-datadome-params:clientid = urlencode(substr(req.http.x-datadome-clientid, 0, 128));\n set bereq.http.x-datadome-x-set-cookie = \"true\";\n } else {\n set bereq.http.x-datadome-params:clientid = urlencode(substr(req.http.cookie:datadome, 0, 128));\n }\n set bereq.http.x-datadome-params:cookieslen = std.strlen(req.http.cookie);\n # enforce gzip encoding between Fastly and DataDome\n set bereq.http.accept-encoding = \"gzip\";\n } else {\n # prevent leak of the key\n unset bereq.http.x-datadome-params;\n }\n }\n}\n\nbackend datadome {\n .host = \"api-fastly.datadome.co\";\n .port = \"8443\";\n .connect_timeout = {{datadome_connect_timeout}}ms;\n .first_byte_timeout = {{datadome_between_bytes_timeout}}ms;\n .between_bytes_timeout = {{datadome_between_bytes_timeout}}ms;\n .max_connections = 200;\n .ssl = true;\n .dynamic = true;\n .probe = {\n .request = \"HEAD /.well-known/healthcheck-datadome HTTP/1.1\" \"Host: api-fastly.datadome.co\" \"Connection: close\" \"User-Agent: Varnish/fastly (healthcheck)\";\n .expected_response = 200;\n .initial = 5;\n .interval = 2s;\n .threshold = 1;\n .timeout = 2s;\n .window = 5;\n }\n}", + "template": "sub set_origin_header {\n if (req.backend.is_origin) {\n if (req.backend == datadome) {\n # Remove all unexpected headers\n header.filter_except(bereq, \"x-datadome-params\", \"accept-charset\", \"accept-language\", \"x-requested-with\", \"x-fl-productid\", \"x-flapi-session-id\", \"fastly-orig-accept-encoding\", \"cache-control\", \"client-id\", \"connection\", \"pragma\", \"accept\", \"headers-list\", \"host\", \"origin\", \"server-hostname\", \"server-name\", \"x-forwarded-for\", \"user-agent\", \"referer\", \"request\", \"content-type\", \"from\", \"true-client-ip\", \"via\", \"x-real-ip\", \"sec-ch-device-memory\", \"sec-ch-ua\", \"sec-ch-ua-arch\", \"sec-ch-ua-full-version-list\", \"sec-ch-ua-mobile\", \"sec-ch-ua-model\", \"sec-ch-ua-platform\", \"sec-fetch-dest\", \"sec-fetch-mode\", \"sec-fetch-site\", \"sec-fetch-user\");\n set bereq.http.x-datadome-params:key = \"{{datadome_api_key}}\";\n set bereq.http.x-datadome-params:requestmodulename = \"FastlyMagento\";\n set bereq.http.x-datadome-params:moduleversion = \"2.19.4\";\n set bereq.http.x-datadome-params:timerequest = time.start.usec;\n set bereq.http.x-datadome-params:servername = server.identity;\n set bereq.http.x-datadome-params:serverregion = server.region;\n set bereq.http.x-datadome-params:ip = urlencode(client.ip);\n set bereq.http.x-forwarded-proto = urlencode(req.protocol);\n set bereq.http.x-datadome-params:authorizationlen = std.strlen(req.http.authorization);\n # Truncating Headers - Start\n set bereq.http.accept-charset = substr(req.http.accept-charset, 0, 128);\n set bereq.http.accept-language = substr(req.http.accept-language, 0, 256);\n set bereq.http.x-requested-with = substr(req.http.x-requested-with, 0, 128);\n set bereq.http.x-fl-productid = substr(req.http.x-fl-productid, 0, 64);\n set bereq.http.x-flapi-session-id = substr(req.http.x-flapi-session-id, 0, 64);\n set bereq.http.fastly-orig-accept-encoding = substr(req.http.fastly-orig-accept-encoding, 0, 128);\n set bereq.http.cache-control = substr(req.http.cache-control, 0, 128);\n set bereq.http.client-id = substr(req.http.client-id, 0, 128);\n set bereq.http.connection = substr(req.http.connection, 0, 128);\n set bereq.http.pragma = substr(req.http.pragma, 0, 128);\n set bereq.http.accept = substr(req.http.accept, 0, 512);\n set bereq.http.headers-list = substr(req.http.headers-list, 0, 512);\n set bereq.http.host = substr(req.http.host, 0, 512);\n set bereq.http.origin = substr(req.http.origin, 0, 512);\n set bereq.http.server-hostname = substr(req.http.server-hostname, 0, 512);\n set bereq.http.server-name = substr(req.http.server-name, 0, 512);\n if( std.strlen(req.http.x-forwarded-for) \u003e 512 ) {\n # Truncate from the end\n set bereq.http.x-forwarded-for = substr(req.http.x-forwarded-for, -512);\n } else {\n set bereq.http.x-forwarded-for = req.http.x-forwarded-for;\n }\n set bereq.http.user-agent = substr(req.http.user-agent, 0, 768);\n set bereq.http.referer = substr(req.http.referer, 0, 1024);\n set bereq.http.request = substr(req.http.request, 0, 2048);\n set bereq.http.content-type = substr(req.http.content-type, 0, 64);\n set bereq.http.from = substr(req.http.from, 0, 128);\n set bereq.http.true-client-ip = substr(req.http.true-client-ip, 0, 128);\n set bereq.http.via = substr(req.http.via, 0, 256);\n set bereq.http.x-real-ip = substr(req.http.x-real-ip, 0, 128);\n set bereq.http.sec-ch-device-memory = substr(req.http.sec-ch-device-memory, 0, 8);\n set bereq.http.sec-ch-ua = substr(req.http.sec-ch-ua, 0, 128);\n set bereq.http.sec-ch-ua-arch = substr(req.http.sec-ch-ua-arch, 0, 16);\n set bereq.http.sec-ch-ua-full-version-list = substr(req.http.sec-ch-ua-full-version-list, 0, 256);\n set bereq.http.sec-ch-ua-mobile = substr(req.http.sec-ch-ua-mobile, 0, 8);\n set bereq.http.sec-ch-ua-model = substr(req.http.sec-ch-ua-model, 0, 128);\n set bereq.http.sec-ch-ua-platform = substr(req.http.sec-ch-ua-platform, 0, 32);\n set bereq.http.sec-fetch-dest = substr(req.http.sec-fetch-dest, 0, 32);\n set bereq.http.sec-fetch-mode = substr(req.http.sec-fetch-mode, 0, 32);\n set bereq.http.sec-fetch-site = substr(req.http.sec-fetch-site, 0, 64);\n set bereq.http.sec-fetch-user = substr(req.http.sec-fetch-user, 0, 8);\n # Truncating Headers - End\n if (req.http.x-datadome-clientid) {\n set bereq.http.x-datadome-params:clientid = urlencode(substr(req.http.x-datadome-clientid, 0, 128));\n set bereq.http.x-datadome-x-set-cookie = \"true\";\n } else {\n set bereq.http.x-datadome-params:clientid = urlencode(substr(req.http.cookie:datadome, 0, 128));\n }\n set bereq.http.x-datadome-params:cookieslen = std.strlen(req.http.cookie);\n # enforce gzip encoding between Fastly and DataDome\n set bereq.http.accept-encoding = \"gzip\";\n } else {\n # prevent leak of the key\n unset bereq.http.x-datadome-params;\n }\n }\n}\n\nbackend datadome {\n .host = \"api-fastly.datadome.co\";\n .port = \"8443\";\n .connect_timeout = {{datadome_connect_timeout}}ms;\n .first_byte_timeout = {{datadome_between_bytes_timeout}}ms;\n .between_bytes_timeout = {{datadome_between_bytes_timeout}}ms;\n .max_connections = 200;\n .ssl = true;\n .dynamic = true;\n .probe = {\n .request = \"HEAD /.well-known/healthcheck-datadome HTTP/1.1\" \"Host: api-fastly.datadome.co\" \"Connection: close\" \"User-Agent: Varnish/fastly (healthcheck)\";\n .expected_response = 200;\n .initial = 5;\n .interval = 2s;\n .threshold = 1;\n .timeout = 2s;\n .window = 5;\n }\n}", "type": "init" }, { "priority": 7, - "template": "if (req.backend == datadome) {\n declare local var.status STRING;\n set var.status = beresp.status;\n # check that it is real ApiServer response\n if (var.status != beresp.http.x-datadomeresponse) {\n restart;\n }\n unset beresp.http.x-datadomeresponse;\n # copy datadome headers\n set req.http.x-datadome-headers-pairs:x-datadome-headers = urlencode(beresp.http.x-datadome-headers);\n\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-set-cookie( |$)+\") {\n set req.http.x-datadome-headers-pairs:x-set-cookie = urlencode(beresp.http.x-set-cookie);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-datadome-server( |$)+\") {\n set req.http.x-datadome-headers-pairs:x-datadome-server = urlencode(beresp.http.x-datadome-server);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-datadome( |$)+\") {\n set req.http.x-datadome-headers-pairs:x-datadome = urlencode(beresp.http.x-datadome);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+content-type( |$)+\") {\n set req.http.x-datadome-headers-pairs:content-type = urlencode(beresp.http.content-type);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+charset( |$)+\") {\n set req.http.x-datadome-headers-pairs:charset = urlencode(beresp.http.charset);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+cache-control( |$)+\") {\n set req.http.x-datadome-headers-pairs:cache-control = urlencode(beresp.http.cache-control);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+pragma( |$)+\") {\n set req.http.x-datadome-headers-pairs:pragma = urlencode(beresp.http.pragma);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+access-control-allow-credentials( |$)+\") {\n set req.http.x-datadome-headers-pairs:access-control-allow-credentials = urlencode(beresp.http.access-control-allow-credentials);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+access-control-expose-headers( |$)+\") {\n set req.http.x-datadome-headers-pairs:access-control-expose-headers = urlencode(beresp.http.access-control-expose-headers);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+access-control-allow-origin( |$)+\") {\n set req.http.x-datadome-headers-pairs:access-control-allow-origin = urlencode(beresp.http.access-control-allow-origin);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-datadome-cid( |$)+\") {\n set req.http.x-datadome-headers-pairs:x-datadome-cid = urlencode(beresp.http.x-datadome-cid);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-dd-b( |$)+\") {\n set req.http.x-datadome-headers-pairs:x-dd-b = urlencode(beresp.http.x-dd-b);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-dd-type( |$)+\") {\n set req.http.x-datadome-headers-pairs:x-dd-type = urlencode(beresp.http.x-dd-type);\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-dd-type( |$)+\") {\n set req.http.x-dd-type = beresp.http.x-dd-type;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-botname( |$)+\") {\n set req.http.x-datadome-botname = beresp.http.x-datadome-botname;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-botfamily( |$)+\") {\n set req.http.x-datadome-botfamily = beresp.http.x-datadome-botfamily;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-isbot( |$)+\") {\n set req.http.x-datadome-isbot = beresp.http.x-datadome-isbot;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-captchapassed( |$)+\") {\n set req.http.x-datadome-captchapassed = beresp.http.x-datadome-captchapassed;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-traffic-rule-response( |$)+\") {\n set req.http.x-datadome-traffic-rule-response = beresp.http.x-datadome-traffic-rule-response;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-captchaurl( |$)+\") {\n set req.http.x-datadome-captchaurl = beresp.http.x-datadome-captchaurl;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-requestid( |$)+\") {\n set req.http.x-datadome-requestid = beresp.http.x-datadome-requestid;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-score( |$)+\") {\n set req.http.x-datadome-score = beresp.http.x-datadome-score;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-ruletype( |$)+\") {\n set req.http.x-datadome-ruletype = beresp.http.x-datadome-ruletype;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-matchedmodels( |$)+\") {\n set req.http.x-datadome-matchedmodels = beresp.http.x-datadome-matchedmodels;\n }\n # don\u0027t forget about ApiServer\u0027s cookies\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+set-cookie( |$)+\") {\n set req.http.x-datadome-headers-pairs:set-cookie = urlencode(beresp.http.set-cookie);\n }\n\n # Continue only if ApiServer returns expected blocked status\n if (beresp.status != 403 \u0026\u0026 beresp.status != 401 \u0026\u0026 beresp.status != 301 \u0026\u0026 beresp.status != 302) {\n unset beresp.http.x-datadome-headers;\n unset beresp.http.x-datadome-request-headers;\n set req.http.x-datadome-cookie = beresp.http.x-datadome-cookie; # Allow Session Feature\n restart;\n }\n\n # ok, it is banned request, cleanup it a bit\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-dd-type( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-dd-type( |$)+\") {\n unset beresp.http.x-dd-type;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-botname( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-botname( |$)+\") {\n unset beresp.http.x-datadome-botname;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-botfamily( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-botfamily( |$)+\") {\n unset beresp.http.x-datadome-botfamily;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-isbot( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-isbot( |$)+\") {\n unset beresp.http.x-datadome-isbot;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-captchapassed( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-captchapassed( |$)+\") {\n unset beresp.http.x-datadome-captchapassed;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-traffic-rule-response( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-traffic-rule-response( |$)+\") {\n unset beresp.http.x-datadome-traffic-rule-response;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-captchaurl( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-captchaurl( |$)+\") {\n unset beresp.http.x-datadome-captchaurl;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-requestid( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-requestid( |$)+\") {\n unset beresp.http.x-datadome-requestid;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-score( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-score( |$)+\") {\n unset beresp.http.x-datadome-score;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-ruletype( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-ruletype( |$)+\") {\n unset beresp.http.x-datadome-ruletype;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-matchedmodels( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-matchedmodels( |$)+\") {\n unset beresp.http.x-datadome-matchedmodels;\n }\n }\n unset beresp.http.x-datadome-headers;\n unset beresp.http.x-datadome-request-headers;\n}", + "template": "if (req.backend == datadome) {\n declare local var.status STRING;\n set var.status = beresp.status;\n # check that it is real ApiServer response\n if (var.status != beresp.http.x-datadomeresponse) {\n restart;\n }\n unset beresp.http.x-datadomeresponse;\n # copy datadome headers\n set req.http.x-datadome-headers-pairs:x-datadome-headers = urlencode(beresp.http.x-datadome-headers);\n\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-set-cookie( |$)+\") {\n set req.http.x-datadome-headers-pairs:x-set-cookie = urlencode(beresp.http.x-set-cookie);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-datadome-server( |$)+\") {\n set req.http.x-datadome-headers-pairs:x-datadome-server = urlencode(beresp.http.x-datadome-server);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-datadome( |$)+\") {\n set req.http.x-datadome-headers-pairs:x-datadome = urlencode(beresp.http.x-datadome);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+content-type( |$)+\") {\n set req.http.x-datadome-headers-pairs:content-type = urlencode(beresp.http.content-type);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+charset( |$)+\") {\n set req.http.x-datadome-headers-pairs:charset = urlencode(beresp.http.charset);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+cache-control( |$)+\") {\n set req.http.x-datadome-headers-pairs:cache-control = urlencode(beresp.http.cache-control);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+pragma( |$)+\") {\n set req.http.x-datadome-headers-pairs:pragma = urlencode(beresp.http.pragma);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+access-control-allow-credentials( |$)+\") {\n set req.http.x-datadome-headers-pairs:access-control-allow-credentials = urlencode(beresp.http.access-control-allow-credentials);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+access-control-expose-headers( |$)+\") {\n set req.http.x-datadome-headers-pairs:access-control-expose-headers = urlencode(beresp.http.access-control-expose-headers);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+access-control-allow-origin( |$)+\") {\n set req.http.x-datadome-headers-pairs:access-control-allow-origin = urlencode(beresp.http.access-control-allow-origin);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-datadome-cid( |$)+\") {\n set req.http.x-datadome-headers-pairs:x-datadome-cid = urlencode(beresp.http.x-datadome-cid);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-dd-b( |$)+\") {\n set req.http.x-datadome-headers-pairs:x-dd-b = urlencode(beresp.http.x-dd-b);\n }\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-dd-type( |$)+\") {\n set req.http.x-datadome-headers-pairs:x-dd-type = urlencode(beresp.http.x-dd-type);\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-dd-type( |$)+\") {\n set req.http.x-dd-type = beresp.http.x-dd-type;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-botname( |$)+\") {\n set req.http.x-datadome-botname = beresp.http.x-datadome-botname;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-botfamily( |$)+\") {\n set req.http.x-datadome-botfamily = beresp.http.x-datadome-botfamily;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-isbot( |$)+\") {\n set req.http.x-datadome-isbot = beresp.http.x-datadome-isbot;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-captchapassed( |$)+\") {\n set req.http.x-datadome-captchapassed = beresp.http.x-datadome-captchapassed;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-devicecheckpassed( |$)+\") {\n set req.http.x-datadome-devicecheckpassed = beresp.http.x-datadome-devicecheckpassed;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-traffic-rule-response( |$)+\") {\n set req.http.x-datadome-traffic-rule-response = beresp.http.x-datadome-traffic-rule-response;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-captchaurl( |$)+\") {\n set req.http.x-datadome-captchaurl = beresp.http.x-datadome-captchaurl;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-requestid( |$)+\") {\n set req.http.x-datadome-requestid = beresp.http.x-datadome-requestid;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-score( |$)+\") {\n set req.http.x-datadome-score = beresp.http.x-datadome-score;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-ruletype( |$)+\") {\n set req.http.x-datadome-ruletype = beresp.http.x-datadome-ruletype;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-matchedmodels( |$)+\") {\n set req.http.x-datadome-matchedmodels = beresp.http.x-datadome-matchedmodels;\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-sessionid( |$)+\") {\n set req.http.x-datadome-sessionid = beresp.http.x-datadome-sessionid;\n }\n # don\u0027t forget about ApiServer\u0027s cookies\n if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+set-cookie( |$)+\") {\n set req.http.x-datadome-headers-pairs:set-cookie = urlencode(beresp.http.set-cookie);\n }\n\n # Continue only if ApiServer returns expected blocked status\n if (beresp.status != 403 \u0026\u0026 beresp.status != 401 \u0026\u0026 beresp.status != 301 \u0026\u0026 beresp.status != 302) {\n unset beresp.http.x-datadome-headers;\n unset beresp.http.x-datadome-request-headers;\n set req.http.x-datadome-cookie = beresp.http.x-datadome-cookie; # Allow Session Feature\n restart;\n }\n\n # ok, it is banned request, cleanup it a bit\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-dd-type( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-dd-type( |$)+\") {\n unset beresp.http.x-dd-type;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-botname( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-botname( |$)+\") {\n unset beresp.http.x-datadome-botname;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-botfamily( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-botfamily( |$)+\") {\n unset beresp.http.x-datadome-botfamily;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-isbot( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-isbot( |$)+\") {\n unset beresp.http.x-datadome-isbot;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-captchapassed( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-captchapassed( |$)+\") {\n unset beresp.http.x-datadome-captchapassed;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-devicecheckpassed( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-devicecheckpassed( |$)+\") {\n unset beresp.http.x-datadome-devicecheckpassed;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-traffic-rule-response( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-traffic-rule-response( |$)+\") {\n unset beresp.http.x-datadome-traffic-rule-response;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-captchaurl( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-captchaurl( |$)+\") {\n unset beresp.http.x-datadome-captchaurl;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-requestid( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-requestid( |$)+\") {\n unset beresp.http.x-datadome-requestid;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-score( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-score( |$)+\") {\n unset beresp.http.x-datadome-score;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-ruletype( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-ruletype( |$)+\") {\n unset beresp.http.x-datadome-ruletype;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-matchedmodels( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-matchedmodels( |$)+\") {\n unset beresp.http.x-datadome-matchedmodels;\n }\n }\n if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-sessionid( |$)+\") {\n if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-sessionid( |$)+\") {\n unset beresp.http.x-datadome-sessionid;\n }\n }\n unset beresp.http.x-datadome-headers;\n unset beresp.http.x-datadome-request-headers;\n}", "type": "fetch" }, { @@ -88,5 +88,5 @@ "type": "pass" } ], - "version": "2.19.1" + "version": "2.19.4" } diff --git a/etc/fastly_edge_modules/netacea_integration.json b/etc/fastly_edge_modules/netacea_integration.json index ed11775a..b4d2cc19 100644 --- a/etc/fastly_edge_modules/netacea_integration.json +++ b/etc/fastly_edge_modules/netacea_integration.json @@ -91,12 +91,12 @@ "vcl": [ { "priority": 45, - "template": "set var.fastly_req_do_shield = (req.restarts <= 1);\nset req.http.Fastly-Force-Shield = \"1\";\nif (req.restarts == 0) {\n call cleanup_netacea_variables;\n}\ncall netacea_check_req;\n", + "template": "set var.fastly_req_do_shield = (req.restarts <= 1);\nset req.http.Fastly-Force-Shield = \"1\";\nif (req.restarts == 0) {\n call cleanup_netacea_variables;\n}\ncall netacea_check_req;\n", "type": "recv" }, { "priority": 45, - "template": "if (!is_path_ignored()) {\n declare local var.netacea_use_relative_path_captcha_assets STRING;\n declare local var.integration_mode STRING;\n set var.netacea_use_relative_path_captcha_assets = get_netacea_config_use_relative_path_captcha_assets();\n if (var.netacea_use_relative_path_captcha_assets == \"true\") {\n if (std.prefixof(req.url.path, \"/Mitigations/\") && req.method == \"GET\") {\n if (std.suffixof(req.url.path, \".css\") || std.suffixof(req.url.path, \".js\")) {\n return(deliver);\n }\n }\n }\n if (req.http.netacea_captcha_path == \"1\") {\n call netacea_hide_response_headers;\n call set_netacea_captcha_header;\n return(deliver);\n }\n call netacea_calculate_best_mitigation;\n if (req.http.netacea_processed == \"1\") {\n set var.integration_mode = get_netacea_config_integration_mode();\n set req.http.mit_status = resp.status;\n if (resp.status != 200 && req.http.X-Netacea-Compile-JSON != \"done\") {\n set req.http.netacea_best_mitigation = \"\";\n set req.http.netacea_bctype_string = \"\";\n if(req.url == \"/AtaVerifyCaptcha\") {\n unset resp.http.Set-Cookie;\n set req.http.netacea_set_cookies = \"0\";\n }\n }\n if (var.integration_mode == \"MITIGATE\" && req.http.X-Netacea-Compile-JSON != \"done\" && netacea_should_return_json()) { \n if (req.url != \"/AtaVerifyCaptcha\" && resp.http.X-Netacea-Mitigate == \"1\") { \n if (resp.http.X-Netacea-Captcha == \"1\" || resp.http.X-Netacea-Captcha == \"5\") { \n set req.http.X-Netacea-Event-ID = resp.http.X-Netacea-Event-ID;\n set req.http.X-Netacea-Compile-JSON = \"requested\";\n }\n }\n }\n if (var.integration_mode == \"INJECT\" || req.http.X-Netacea-Compile-JSON == \"requested\") {\n set req.http.X-Netacea-Match = \"\" resp.http.X-Netacea-Match;\n set req.http.X-Netacea-Mitigate = \"\" resp.http.X-Netacea-Mitigate;\n set req.http.X-Netacea-Captcha = \"\" resp.http.X-Netacea-Captcha;\n }\n set req.http.netacea_mitata_captcha_cookie_value = resp.http.x-netacea-mitatacaptcha-value;\n set req.http.netacea_mitata_captcha_cookie_expiry = resp.http.x-netacea-mitatacaptcha-expiry;\n call set_netacea_cookies;\n call netacea_hide_response_headers;\n if(req.url == \"/AtaVerifyCaptcha\") {\n return(deliver);\n }\n set req.http.host = req.http.netacea_origin_host;\n set req.url = req.http.netacea_origin_url;\n set req.method = req.http.netacea_origin_method;\n unset req.http.netacea_origin_url;\n unset req.http.netacea_origin_host;\n unset req.http.netacea_origin_method;\n unset req.http.X-Netacea-Api-Key;\n if (\n req.http.netacea_best_mitigation != \"captcha\"\n || var.integration_mode == \"INJECT\"\n || req.http.X-Netacea-Compile-JSON == \"requested\"\n ) {\n unset req.http.x-netacea:netacea_check_req_called;\n restart;\n }\n set resp.status = 403;\n set resp.response = \"Forbidden\";\n unset req.http.X-Netacea-Compile-JSON;\n call set_netacea_captcha_header;\n return(deliver);\n }\n call set_netacea_cookies;\n}\n", + "template": "if (!is_path_ignored() && !req.is_purge) {\n declare local var.netacea_use_relative_path_captcha_assets STRING;\n declare local var.integration_mode STRING;\n declare local var.mit_svc_latency INTEGER;\n if (req.http.x-netacea:mit_svc_start_time) {\n set var.mit_svc_latency = std.strtol(time.elapsed.msec, 10);\n set var.mit_svc_latency -= std.strtol(req.http.x-netacea:mit_svc_start_time, 10);\n set req.http.x-netacea:mit_svc_latency = var.mit_svc_latency;\n }\n set var.netacea_use_relative_path_captcha_assets = get_netacea_config_use_relative_path_captcha_assets();\n if (var.netacea_use_relative_path_captcha_assets == \"true\") {\n if (std.prefixof(req.url.path, \"/Mitigations/\") && req.method == \"GET\") {\n if (std.suffixof(req.url.path, \".css\") || std.suffixof(req.url.path, \".js\")) {\n return(deliver);\n }\n }\n }\n if (req.http.netacea_captcha_path == \"1\") {\n call netacea_hide_response_headers;\n call set_netacea_captcha_header;\n return(deliver);\n }\n call netacea_calculate_best_mitigation;\n if (req.http.netacea_processed == \"1\") {\n set var.integration_mode = get_netacea_config_integration_mode();\n set req.http.x-netacea:mit_status = resp.status;\n if (resp.status != 200 && req.http.X-Netacea-Compile-JSON != \"done\") {\n set req.http.netacea_best_mitigation = \"\";\n set req.http.netacea_bctype_string = \"\";\n if(req.url == \"/AtaVerifyCaptcha\") {\n unset resp.http.Set-Cookie;\n set req.http.netacea_set_cookies = \"0\";\n }\n }\n if (var.integration_mode == \"MITIGATE\" && req.http.X-Netacea-Compile-JSON != \"done\" && netacea_should_return_json()) { \n if (req.url != \"/AtaVerifyCaptcha\" && resp.http.X-Netacea-Mitigate == \"1\") { \n if (resp.http.X-Netacea-Captcha == \"1\" || resp.http.X-Netacea-Captcha == \"5\") { \n set req.http.X-Netacea-Event-ID = resp.http.X-Netacea-Event-ID;\n set req.http.X-Netacea-Compile-JSON = \"requested\";\n }\n }\n }\n if (var.integration_mode == \"INJECT\" || req.http.X-Netacea-Compile-JSON == \"requested\") {\n set req.http.X-Netacea-Match = \"\" resp.http.X-Netacea-Match;\n set req.http.X-Netacea-Mitigate = \"\" resp.http.X-Netacea-Mitigate;\n set req.http.X-Netacea-Captcha = \"\" resp.http.X-Netacea-Captcha;\n }\n set req.http.netacea_mitata_captcha_cookie_value = resp.http.x-netacea-mitatacaptcha-value;\n set req.http.netacea_mitata_captcha_cookie_expiry = resp.http.x-netacea-mitatacaptcha-expiry;\n call set_netacea_cookies;\n call netacea_hide_response_headers;\n if(req.url == \"/AtaVerifyCaptcha\") {\n return(deliver);\n }\n set req.http.host = req.http.netacea_origin_host;\n set req.url = req.http.netacea_origin_url;\n set req.method = req.http.netacea_origin_method;\n unset req.http.netacea_origin_url;\n unset req.http.netacea_origin_host;\n unset req.http.netacea_origin_method;\n unset req.http.X-Netacea-Api-Key;\n if (\n req.http.netacea_best_mitigation != \"captcha\"\n || var.integration_mode == \"INJECT\"\n || req.http.X-Netacea-Compile-JSON == \"requested\"\n ) {\n unset req.http.x-netacea:netacea_check_req_called;\n restart;\n }\n set resp.status = 403;\n set resp.response = \"Forbidden\";\n unset req.http.X-Netacea-Compile-JSON;\n call set_netacea_captcha_header;\n return(deliver);\n }\n if (fastly.ff.visits_this_service == 0) {\n call set_netacea_cookies;\n }\n}\n", "type": "deliver" }, { @@ -106,9 +106,9 @@ }, { "priority": 45, - "template": "backend F_MitSvc {\n .between_bytes_timeout = 100ms;\n .connect_timeout = 500ms;\n .dynamic = true;\n .first_byte_timeout = 500ms;\n .host = \"geo-mitigations.netacea.net\";\n .max_connections = 200;\n .port = \"443\";\n .share_key = \"NetaceaGeoMitigations\";\n .host_header = \"geo-mitigations.netacea.net\";\n .always_use_host_header = true;\n .ssl = true;\n .ssl_cert_hostname = \"geo-mitigations.netacea.net\";\n .ssl_check_cert = always;\n .ssl_sni_hostname = \"geo-mitigations.netacea.net\";\n .probe = {\n .dummy = false;\n .initial = 5;\n .request = \"GET /_health HTTP/1.1\" \"Host: geo-mitigations.netacea.net\" \"Connection: close\" \"User-Agent: Varnish/fastly (healthcheck)\";\n .threshold = 1;\n .timeout = 2s;\n .window = 5;\n .expected_response = 200;\n }\n}\nbackend F_CaptchaAssets {\n .between_bytes_timeout = 10s;\n .connect_timeout = 1s;\n .dynamic = true;\n .first_byte_timeout = 15s;\n .host = \"assets.ntcacdn.net\";\n .max_connections = 200;\n .port = \"443\";\n .share_key = \"4nxXnE6VkrJiVuGz4G1VbJ\";\n .host_header = \"assets.ntcacdn.net\";\n .always_use_host_header = true;\n .ssl = true;\n .ssl_cert_hostname = \"assets.ntcacdn.net\";\n .ssl_check_cert = always;\n .ssl_sni_hostname = \"assets.ntcacdn.net\";\n .probe = {\n .dummy = true;\n .initial = 5;\n .request = \"HEAD / HTTP/1.1\" \"Host: assets.ntcacdn.net\" \"Connection: close\";\n .threshold = 1;\n .timeout = 2s;\n .window = 5;\n }\n}\ntable Netacea_Config {\n \"integration_type\": \"fastly/magento\",\n \"integration_version\": \"5.7.0\",\n \"integration_mode\": \"{{netacea_integration_mode}}\",\n \"api_key\": \"{{netacea_api_key}}\",\n \"secret_key\": \"{{netacea_secret}}\",\n \"encryption_key\": \"{{netacea_encryption_key}}\",\n \"cookie_name\": \"{{netacea_cookie_name}}\",\n \"captcha_cookie_name\": \"{{netacea_captcha_cookie_name}}\",\n \"ignore_list\": \"{{netacea_ignore_list}}\",\n \"use_relative_path_captcha_assets\": \"{{netacea_use_relative_path_captcha_assets}}\",\n \"real_ip_header_name\": \"{{netacea_real_ip_header_name}}\",\n \"captcha_path\": \"{{netacea_captcha_path}}\",\n \"captcha_header\": \"{{netacea_captcha_header}}\",\n \"enable_captcha_content_negotiation\": \"{{netacea_enable_ccn}}\"\n}\nsub get_netacea_config_integration_type STRING {\n return table.lookup(Netacea_Config, \"integration_type\", \"\");\n}\nsub get_netacea_config_integration_version STRING {\n return table.lookup(Netacea_Config, \"integration_version\", \"\");\n}\nsub get_netacea_config_api_key STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"api_key\");\n }\n return table.lookup(Netacea_Config, \"api_key\", \"\");\n}\nsub get_netacea_config_secret_key STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"secret_key\");\n }\n return table.lookup(Netacea_Config, \"secret_key\", \"\");\n}\nsub get_netacea_config_encryption_key STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"encryption_key\");\n }\n return table.lookup(Netacea_Config, \"encryption_key\", \"\");\n}\nsub get_netacea_config_integration_mode STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"integration_mode\");\n }\n return table.lookup(Netacea_Config, \"integration_mode\", \"\");\n}\nsub get_netacea_config_ignore_list STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"ignore_list\");\n }\n return table.lookup(Netacea_Config, \"ignore_list\", \"\");\n}\nsub get_netacea_config_cookie_name STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"cookie_name\");\n }\n return table.lookup(Netacea_Config, \"cookie_name\", \"\");\n}\nsub get_netacea_config_captcha_cookie_name STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"captcha_cookie_name\");\n }\n return table.lookup(Netacea_Config, \"captcha_cookie_name\", \"\");\n}\nsub get_netacea_config_use_relative_path_captcha_assets STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"use_relative_path_captcha_assets\");\n }\n return table.lookup(Netacea_Config, \"use_relative_path_captcha_assets\", \"\");\n}\nsub get_netacea_config_real_ip_header_name STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"real_ip_header_name\");\n }\n return table.lookup(Netacea_Config, \"real_ip_header_name\", \"\");\n}\nsub get_netacea_config_captcha_path STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"captcha_path\");\n }\n return table.lookup(Netacea_Config, \"captcha_path\", \"\");\n}\nsub get_netacea_config_captcha_header STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"captcha_header\");\n }\n return table.lookup(Netacea_Config, \"captcha_header\", \"\");\n}\nsub get_netacea_config_enable_captcha_content_negotiation STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"enable_captcha_content_negotiation\");\n }\n return table.lookup(Netacea_Config, \"enable_captcha_content_negotiation\", \"\");\n}\nsub get_sanitised_netacea_config_cookie_name STRING {\n declare local var.name STRING;\n set var.name = get_netacea_config_cookie_name();\n if (var.name ~ \"^\\s*(.*?)\\s*$\") {\n if (re.group.1 != \"\") {\n return re.group.1;\n }\n }\n return \"_mitata\";\n}\nsub get_sanitised_netacea_config_captcha_cookie_name STRING {\n declare local var.name STRING;\n set var.name = get_netacea_config_captcha_cookie_name();\n if (var.name ~ \"^\\s*(.*?)\\s*$\") {\n if (re.group.1 != \"\") {\n return re.group.1;\n }\n }\n return \"_mitatacaptcha\";\n}\ntable Netacea_Match_Dict {\n \"0\": \"\",\n \"1\": \"ua\",\n \"2\": \"ip\",\n \"3\": \"visitor\",\n \"4\": \"datacenter\",\n \"5\": \"customer_session\",\n \"6\": \"organisation\",\n \"7\": \"asn\",\n \"8\": \"country\",\n \"9\": \"combination\"\n}\ntable Netacea_Mitigate_Dict {\n \"0\": \"\",\n \"1\": \"blocked\",\n \"2\": \"allow\",\n \"3\": \"hardblocked\"\n}\ntable Netacea_Best_Mitigations_Dict {\n \"0\": \"\",\n \"1\": \"block\",\n \"2\": \"allow\",\n \"3\": \"block\"\n}\ntable Netacea_Best_Mitigations_Captcha_Dict {\n \"1\": \"captcha\",\n \"2\": \"\",\n \"3\": \"captcha\",\n \"4\": \"\",\n \"5\": \"captcha\"\n}\ntable Netacea_Captcha_Dict {\n \"0\": \"\",\n \"1\": \"captcha_serve\",\n \"2\": \"captcha_pass\",\n \"3\": \"captcha_fail\",\n \"4\": \"captcha_cookiepass\",\n \"5\": \"captcha_cookiefail\",\n}\nsub get_netacea_captcha_path STRING {\n declare local var.path STRING;\n set var.path = get_netacea_config_captcha_path();\n set var.path = regsub(var.path, \"^\\s*/*\", \"/\");\n set var.path = regsub(var.path, \"\\s*$\", \"\");\n return urldecode(var.path);\n}\nsub get_sanitised_netacea_config_captcha_header STRING {\n declare local var.value STRING;\n set var.value = get_netacea_config_captcha_header();\n set var.value = urldecode(regsuball(var.value, \"&#x(.{2});\", \"%25\\1\"));\n set var.value = std.replaceall(var.value, \""\", \"%22\");\n set var.value = std.replaceall(var.value, \"<\", \"<\");\n set var.value = std.replaceall(var.value, \">\", \">\");\n set var.value = std.replaceall(var.value, \"&\", \"&\");\n return var.value;\n}\nsub get_netacea_captcha_header_name STRING {\n declare local var.config STRING;\n set var.config = get_sanitised_netacea_config_captcha_header();\n if (var.config ~ \"(?i)(?:^|&)\\s*name\\s*=\\s*(.*?)\\s*(?:&|$)\") {\n return re.group.1;\n }\n return \"\";\n}\nsub get_netacea_captcha_header_value STRING {\n declare local var.config STRING;\n set var.config = get_sanitised_netacea_config_captcha_header();\n if (var.config ~ \"(?i)(?:^|&)\\s*value\\s*=\\s*(.*?)\\s*(?:&|$)\") {\n return re.group.1;\n }\n return \"\";\n}\nsub is_path_ignored BOOL {\n declare local var.netacea_ignore_list STRING;\n declare local var.req_path STRING;\n set var.netacea_ignore_list = get_netacea_config_ignore_list();\n set var.req_path = urldecode(req.url.path);\n set var.netacea_ignore_list = regsuball(var.netacea_ignore_list, \"\\s*(,\\s*)+\", \",\");\n set var.netacea_ignore_list = regsuball(var.netacea_ignore_list, \"(^|,)\\s*/*\", \"\\1/\");\n set var.netacea_ignore_list = regsuball(var.netacea_ignore_list, \"/*\\s*(,|$)\", \"\\1\");\n if (var.netacea_ignore_list ~ \"^([^,]+),*([^,]+)?,*([^,]+)?,*([^,]+)?,*([^,]+)?\") {\n if (re.group.1 && (var.req_path == urldecode(re.group.1) || std.prefixof(var.req_path, urldecode(re.group.1) + \"/\"))) {\n return true;\n }\n if (re.group.2 && (var.req_path == urldecode(re.group.2) || std.prefixof(var.req_path, urldecode(re.group.2) + \"/\"))) {\n return true;\n }\n if (re.group.3 && (var.req_path == urldecode(re.group.3) || std.prefixof(var.req_path, urldecode(re.group.3) + \"/\"))) {\n return true;\n }\n if (re.group.4 && (var.req_path == urldecode(re.group.4) || std.prefixof(var.req_path, urldecode(re.group.4) + \"/\"))) {\n return true;\n }\n if (re.group.5 && (var.req_path == urldecode(re.group.5) || std.prefixof(var.req_path, urldecode(re.group.5) + \"/\"))) {\n return true;\n }\n }\n return false;\n}\nsub netacea_should_return_json BOOL {\n declare local var.enable_captcha_content_negotiation STRING;\n set var.enable_captcha_content_negotiation = get_netacea_config_enable_captcha_content_negotiation();\n if (var.enable_captcha_content_negotiation != \"true\") {\n return false;\n }\n declare local var.html_weight FLOAT;\n declare local var.json_weight FLOAT;\n set var.html_weight = 0.0;\n set var.json_weight = 0.0;\n if (req.http.Accept ~ \"(?i)(^|,)\\s*application/json\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.json_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n } elseif (req.http.Accept ~ \"(?i)(^|,)\\s*application/\\*\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.json_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n }\n if (req.http.Accept ~ \"(?i)(^|,)\\s*text/html\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.html_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n } elseif (req.http.Accept ~ \"(^|,)\\s*text/\\*\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.html_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n }\n return var.json_weight > var.html_weight;\n}\nsub netacea_hide_response_headers {\n unset resp.http.X-Netacea-Captcha;\n unset resp.http.X-Netacea-Event-ID;\n unset resp.http.X-Netacea-Match;\n unset resp.http.X-Netacea-MitATA-Expiry;\n unset resp.http.X-Netacea-MitATA-Value;\n unset resp.http.X-Netacea-Mitigate;\n}\nsub set_netacea_captcha_header {\n declare local var.captcha_header_name STRING;\n declare local var.captcha_header_value STRING;\n set var.captcha_header_name = get_netacea_captcha_header_name();\n set var.captcha_header_value = get_netacea_captcha_header_value();\n if (var.captcha_header_name != \"\") {\n header.set(resp, var.captcha_header_name, var.captcha_header_value);\n }\n}\nsub set_netacea_ip_header {\n declare local var.ip_header_name STRING;\n set var.ip_header_name = get_netacea_config_real_ip_header_name();\n declare local var.ip_header_value STRING;\n set var.ip_header_value = if (std.strlen(var.ip_header_name) > 0, header.get(req, var.ip_header_name), \"\");\n set req.http.X-Netacea-Client-IP = if (std.strlen(var.ip_header_value) > 0, var.ip_header_value, client.ip);\n}\nsub set_netacea_cookies {\n if (req.http.netacea_set_cookies == \"1\") {\n declare local var.ignored BOOL;\n declare local var.netacea_mitSvc_secret STRING;\n declare local var.netacea_encryption_key STRING;\n set var.ignored = setcookie.delete_by_name(resp, \"_mitata\");\n set var.ignored = setcookie.delete_by_name(resp, \"_mitatacaptcha\");\n declare local var.netacea_captcha_cookie_name STRING;\n set var.netacea_captcha_cookie_name = get_sanitised_netacea_config_captcha_cookie_name();\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n set var.netacea_encryption_key = get_netacea_config_encryption_key();\n call set_mitata_cookie;\n if (req.http.netacea_mitata_captcha_cookie_value && req.http.netacea_mitata_captcha_cookie_expiry) {\n if (var.netacea_encryption_key ~ \".\") {\n declare local var.netacea_iv STRING;\n declare local var.netacea_iv_trimmed STRING;\n declare local var.netacea_sig STRING;\n declare local var.netacea_mitata_captcha_cookie_value_base64 STRING;\n declare local var.netacea_mitata_captcha_cookie_value_hex STRING;\n declare local var.netacea_mitata_captcha_cookie_value_encrypted STRING;\n declare local var.netacea_mitata_captcha_cookie_final_value STRING;\n set var.netacea_mitata_captcha_cookie_value_base64 = digest.base64(req.http.netacea_mitata_captcha_cookie_value);\n set var.netacea_mitata_captcha_cookie_value_hex = bin.base64_to_hex(var.netacea_mitata_captcha_cookie_value_base64);\n set var.netacea_iv = uuid.version4();\n set var.netacea_iv_trimmed = std.replaceall(var.netacea_iv, \"-\", \"\");\n set var.netacea_mitata_captcha_cookie_value_encrypted = crypto.encrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv_trimmed, var.netacea_mitata_captcha_cookie_value_hex);\n set var.netacea_sig = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_captcha_cookie_value_encrypted);\n set var.netacea_mitata_captcha_cookie_final_value = var.netacea_iv_trimmed + \".\" + var.netacea_mitata_captcha_cookie_value_encrypted + \".\" + var.netacea_sig;\n add resp.http.Set-Cookie = var.netacea_captcha_cookie_name + \"=\" + var.netacea_mitata_captcha_cookie_final_value + \"; Max-Age=\" + req.http.netacea_mitata_captcha_cookie_expiry + \"; Path=/;\";\n }\n if (var.netacea_encryption_key !~ \".\") {\n add resp.http.Set-Cookie = var.netacea_captcha_cookie_name + \"=\" + req.http.netacea_mitata_captcha_cookie_value + \"; Max-Age=\" + req.http.netacea_mitata_captcha_cookie_expiry + \"; Path=/;\";\n }\n }\n }\n}\nsub netacea_calculate_best_mitigation {\n if (!req.http.netacea_bctype_string) {\n declare local var.netacea_match STRING;\n declare local var.netacea_mitigate STRING;\n declare local var.netacea_captcha STRING;\n declare local var.netacea_match_string STRING;\n declare local var.netacea_mitigate_string STRING;\n declare local var.netacea_captcha_string STRING;\n declare local var.netacea_captcha_mitigate_string STRING;\n declare local var.netacea_best_mitigation STRING;\n declare local var.netacea_bctype_string STRING;\n if (resp.http.x-netacea-match) { \n set var.netacea_match = resp.http.x-netacea-match;\n } elseif (req.http.netacea_match) { \n set var.netacea_match = req.http.netacea_match;\n } else {\n set var.netacea_match = \"0\";\n }\n if (resp.http.x-netacea-mitigate) { \n set var.netacea_mitigate = resp.http.x-netacea-mitigate;\n } elseif (req.http.netacea_mitigate) { \n set var.netacea_mitigate = req.http.netacea_mitigate;\n } else {\n set var.netacea_mitigate = \"0\";\n }\n if (resp.http.x-netacea-captcha) { \n set var.netacea_captcha = resp.http.x-netacea-captcha;\n } elseif (req.http.netacea_captcha) { \n set var.netacea_captcha = req.http.netacea_captcha;\n } else {\n set var.netacea_captcha = \"0\";\n }\n if (var.netacea_match) {\n set var.netacea_match_string = table.lookup(Netacea_Match_Dict, var.netacea_match, \"unknown\");\n if (var.netacea_match_string != \"\") {\n set var.netacea_bctype_string = var.netacea_match_string + \"_\";\n }\n }\n if (var.netacea_mitigate) {\n set var.netacea_mitigate_string = table.lookup(Netacea_Mitigate_Dict, var.netacea_mitigate, \"unknown\");\n if (var.netacea_mitigate_string != \"\") {\n set var.netacea_bctype_string = var.netacea_bctype_string + var.netacea_mitigate_string;\n }\n set var.netacea_best_mitigation = table.lookup(Netacea_Best_Mitigations_Dict, var.netacea_mitigate, \"no-best-mitigation\");\n if (var.netacea_best_mitigation == \"no-best-mitigation\") {\n set var.netacea_best_mitigation = \"\";\n }\n }\n if (var.netacea_captcha) {\n if (req.url != \"/AtaVerifyCaptcha\") {\n if (var.netacea_captcha == \"2\") {\n set var.netacea_captcha = \"4\";\n } elseif (var.netacea_captcha == \"3\") {\n set var.netacea_captcha = \"5\";\n }\n }\n set var.netacea_captcha_string = table.lookup(Netacea_Captcha_Dict, var.netacea_captcha, \"unknown\");\n if (var.netacea_captcha_string != \"\") {\n set var.netacea_bctype_string = var.netacea_bctype_string + \",\" + var.netacea_captcha_string;\n }\n set var.netacea_captcha_mitigate_string = table.lookup(Netacea_Best_Mitigations_Captcha_Dict, var.netacea_captcha, \"no-best-captcha-mitigation\");\n if (var.netacea_captcha_mitigate_string != \"no-best-captcha-mitigation\") {\n set var.netacea_best_mitigation = var.netacea_captcha_mitigate_string;\n }\n }\n set req.http.netacea_bctype_string = var.netacea_bctype_string;\n set req.http.netacea_best_mitigation = var.netacea_best_mitigation;\n set req.http.netacea_best_mitigation_code = var.netacea_match + var.netacea_mitigate + var.netacea_captcha;\n if (var.netacea_mitigate == \"3\") {\n set req.http.netacea_require_revalidation = \"1\";\n }\n if (var.netacea_mitigate == \"1\" && var.netacea_captcha != \"2\" && var.netacea_captcha != \"4\") {\n set req.http.netacea_require_revalidation = \"1\";\n }\n }\n}\nsub set_mitata_cookie {\n declare local var.netacea_mitSvc_secret STRING;\n declare local var.netacea_encryption_key STRING;\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n set var.netacea_encryption_key = get_netacea_config_encryption_key();\n if (!req.http.X-Netacea-UserId) {\n set req.http.X-Netacea-UserId = \"c\" + randomstr(15, \"1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\");\n }\n declare local var.netacea_iv STRING;\n declare local var.netacea_iv_trimmed STRING;\n declare local var.netacea_sig STRING;\n declare local var.netacea_mitata_cookie_full_value_base64 STRING;\n declare local var.netacea_mitata_cookie_full_value_hex STRING;\n declare local var.netacea_mitata_cookie_full_value_encrypted STRING;\n declare local var.netacea_mitata_cookie_final_value STRING;\n declare local var.netacea_mitata_cookie_full_value STRING;\n declare local var.netacea_ataCookie_stringValue STRING;\n declare local var.netacea_ataCookie_HMAC STRING;\n declare local var.netacea_mitSvc_exp STRING;\n declare local var.netacea_mitSvc_sig STRING;\n declare local var.netacea_mitSvc_userId STRING;\n declare local var.netacea_mitigation_code STRING;\n declare local var.netacea_client_ip_time STRING;\n declare local var.netacea_client_ip_time_hash STRING;\n declare local var.netacea_cookie_name STRING;\n set var.netacea_mitigation_code = req.http.netacea_best_mitigation_code;\n set var.netacea_mitSvc_userId = req.http.X-Netacea-UserId;\n set var.netacea_cookie_name = get_sanitised_netacea_config_cookie_name();\n if (req.http.netacea_require_revalidation == \"1\") {\n set var.netacea_mitSvc_exp = time.units(\"s\", time.sub(now, 1m));\n } else {\n set var.netacea_mitSvc_exp = time.units(\"s\", time.add(now, 1m));\n }\n set var.netacea_client_ip_time = req.http.X-Netacea-Client-IP + var.netacea_mitSvc_exp;\n set var.netacea_client_ip_time_hash = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_client_ip_time);\n if (var.netacea_client_ip_time_hash ~ \"0x(.*)\") {\n set var.netacea_client_ip_time_hash = re.group.1;\n }\n set var.netacea_ataCookie_stringValue = var.netacea_mitSvc_exp + \"_/@#/\" + var.netacea_mitSvc_userId + \"_/@#/\" + digest.base64(var.netacea_client_ip_time_hash) + \"_/@#/\" + var.netacea_mitigation_code;\n set var.netacea_ataCookie_HMAC = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_ataCookie_stringValue);\n if (var.netacea_ataCookie_HMAC ~ \"0x(.*)\") {\n set var.netacea_ataCookie_HMAC = re.group.1;\n }\n set var.netacea_mitSvc_sig = digest.base64(var.netacea_ataCookie_HMAC);\n set var.netacea_mitata_cookie_full_value = var.netacea_mitSvc_sig + \"_/@#/\" + var.netacea_ataCookie_stringValue;\n if (var.netacea_encryption_key ~ \".\") {\n set var.netacea_mitata_cookie_full_value_base64 = digest.base64(var.netacea_mitata_cookie_full_value);\n set var.netacea_mitata_cookie_full_value_hex = bin.base64_to_hex(var.netacea_mitata_cookie_full_value_base64);\n set var.netacea_iv = uuid.version4();\n set var.netacea_iv_trimmed = std.replaceall(var.netacea_iv, \"-\", \"\");\n set var.netacea_mitata_cookie_full_value_encrypted = crypto.encrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv_trimmed, var.netacea_mitata_cookie_full_value_hex);\n set var.netacea_sig = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_cookie_full_value_encrypted);\n set var.netacea_mitata_cookie_final_value = var.netacea_iv_trimmed + \".\" + var.netacea_mitata_cookie_full_value_encrypted + \".\" + var.netacea_sig;\n add resp.http.Set-Cookie = var.netacea_cookie_name + \"=\" + var.netacea_mitata_cookie_final_value + \"; Max-Age=\" + time.units(\"s\", 1d) + \"; Path=/;\";\n }\n if (var.netacea_encryption_key !~ \".\") {\n add resp.http.Set-Cookie = var.netacea_cookie_name + \"=\" + var.netacea_mitata_cookie_full_value+ \"; Max-Age=\" + time.units(\"s\", 1d) + \"; Path=/;\";\n }\n set req.http.mitigation_user_id = var.netacea_mitSvc_userId;\n}\nsub process_netacea_mitata_cookie {\n declare local var.netacea_mitSvc_secret STRING;\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n declare local var.netacea_cookie_sig STRING;\n declare local var.netacea_cookie_payload STRING;\n declare local var.netacea_cookie_expiry STRING;\n declare local var.netacea_client_ip_time_hash STRING;\n declare local var.netacea_real_client_ip_time STRING;\n declare local var.netacea_real_client_ip_time_hash STRING;\n declare local var.netacea_cookie_HMAC STRING;\n declare local var.netacea_cookie_real_value STRING;\n if (req.http.Cookie:_mitata) {\n if (req.http.Cookie:_mitata ~ \"^(.*)_\\/@#\\/((\\d+)_\\/@#\\/(.+)_\\/@#\\/(.+)_\\/@#\\/((\\d)(\\d)(\\d)))$\") {\n set var.netacea_cookie_sig = re.group.1;\n set var.netacea_cookie_payload = re.group.2;\n set var.netacea_cookie_expiry = re.group.3;\n set req.http.X-Netacea-UserId = re.group.4;\n set var.netacea_client_ip_time_hash = re.group.5;\n set req.http.netacea_match = re.group.7;\n set req.http.netacea_mitigate = re.group.8;\n set req.http.netacea_captcha = re.group.9;\n set var.netacea_cookie_real_value = var.netacea_cookie_expiry + \"_/@#/\" + req.http.X-Netacea-UserId + \"_/@#/\" + var.netacea_client_ip_time_hash + \"_/@#/\" + req.http.netacea_match + req.http.netacea_mitigate + req.http.netacea_captcha;\n set var.netacea_cookie_HMAC = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_cookie_real_value);\n if (var.netacea_cookie_HMAC ~ \"0x(.*)\") {\n set var.netacea_cookie_HMAC = re.group.1;\n }\n set var.netacea_real_client_ip_time = req.http.X-Netacea-Client-IP + var.netacea_cookie_expiry;\n set var.netacea_real_client_ip_time_hash = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_real_client_ip_time);\n if (var.netacea_real_client_ip_time_hash ~ \"0x(.*)\") {\n set var.netacea_real_client_ip_time_hash = re.group.1;\n }\n if (var.netacea_cookie_sig != digest.base64(var.netacea_cookie_HMAC)) {\n unset req.http.Cookie:_mitata;\n unset req.http.X-Netacea-UserId;\n unset req.http.netacea_match;\n unset req.http.netacea_mitigate;\n unset req.http.netacea_captcha;\n } else {\n if (time.is_after(now, std.time(var.netacea_cookie_expiry, now)) || digest.base64(var.netacea_real_client_ip_time_hash) != var.netacea_client_ip_time_hash ) {\n set req.http.netacea_mitata_must_reauthenticate = \"1\";\n }\n }\n } else {\n unset req.http.Cookie:_mitata;\n }\n }\n if (!req.http.Cookie:_mitata) {\n unset req.http.Cookie:_mitatacaptcha;\n }\n}\nsub normalise_netacea_cookie_names {\n declare local var.netacea_custom_cookie_name STRING;\n declare local var.netacea_custom_captcha_cookie_name STRING;\n set var.netacea_custom_cookie_name = get_sanitised_netacea_config_cookie_name();\n set var.netacea_custom_captcha_cookie_name = get_sanitised_netacea_config_captcha_cookie_name();\n set req.http.Cookie = regsuball(req.http.Cookie, \";\\s*+\", \"; \");\n if (var.netacea_custom_cookie_name !~ \"^_mitata$\") {\n unset req.http.Cookie:_mitata;\n set req.http.Cookie = std.replace_prefix(req.http.Cookie, var.netacea_custom_cookie_name + \"=\", \"_mitata=\");\n set req.http.Cookie = std.replace(req.http.Cookie, \"; \" + var.netacea_custom_cookie_name + \"=\", \"; _mitata=\");\n }\n if (var.netacea_custom_captcha_cookie_name !~ \"^_mitatacaptcha$\") {\n unset req.http.Cookie:_mitatacaptcha;\n set req.http.Cookie = std.replace_prefix(req.http.Cookie, var.netacea_custom_captcha_cookie_name + \"=\", \"_mitatacaptcha=\");\n set req.http.Cookie = std.replace(req.http.Cookie, \"; \" + var.netacea_custom_captcha_cookie_name + \"=\", \"; _mitatacaptcha=\");\n }\n}\nsub decrypt_netacea_cookies_values {\n declare local var.netacea_mitSvc_secret STRING;\n declare local var.netacea_mitata_cookie_encrypted STRING;\n declare local var.netacea_encryption_key STRING;\n declare local var.netacea_iv STRING;\n declare local var.netacea_mitata_cookie_base64 STRING;\n declare local var.netacea_mitata_cookie_hex STRING;\n declare local var.netacea_mitata_cookie_value STRING;\n declare local var.netacea_mitata_cookie_sig STRING;\n declare local var.netacea_mitata_captcha_cookie_encrypted STRING;\n declare local var.netacea_captcha_iv STRING;\n declare local var.netacea_mitata_captcha_cookie_base64 STRING;\n declare local var.netacea_mitata_captcha_cookie_hex STRING;\n declare local var.netacea_mitata_captcha_cookie_value STRING;\n declare local var.netacea_mitata_captcha_cookie_sig STRING;\n set var.netacea_encryption_key = get_netacea_config_encryption_key();\n if (var.netacea_encryption_key ~ \".\") {\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n if (req.http.Cookie:_mitata ~ \".\") {\n if (req.http.Cookie:_mitata ~ \"^(.*?)\\.\") {\n set var.netacea_iv = re.group.1;\n }\n if (req.http.Cookie:_mitata ~ \"\\.(.*?)\\.\") {\n set var.netacea_mitata_cookie_encrypted = re.group.1;\n }\n if (req.http.Cookie:_mitata ~ \"([^\\.]+$)\") {\n set var.netacea_mitata_cookie_sig = re.group.1;\n }\n set var.netacea_mitata_cookie_hex = crypto.decrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv, var.netacea_mitata_cookie_encrypted);\n set var.netacea_mitata_cookie_base64 = bin.hex_to_base64(var.netacea_mitata_cookie_hex);\n set var.netacea_mitata_cookie_value = digest.base64_decode(var.netacea_mitata_cookie_base64);\n set req.http.Cookie:_mitata = var.netacea_mitata_cookie_value;\n if(var.netacea_mitata_cookie_sig != digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_cookie_encrypted)) {\n unset req.http.Cookie:_mitata;\n }\n }\n if (req.http.Cookie:_mitatacaptcha ~ \"^(.*?)\\.\") {\n if (req.http.Cookie:_mitatacaptcha ~ \"^(.*?)\\.\") {\n set var.netacea_captcha_iv = re.group.1;\n }\n if (req.http.Cookie:_mitatacaptcha ~ \"\\.(.*?)\\.\") {\n set var.netacea_mitata_captcha_cookie_encrypted = re.group.1;\n }\n if (req.http.Cookie:_mitatacaptcha ~ \"([^\\.]+$)\") {\n set var.netacea_mitata_captcha_cookie_sig = re.group.1;\n }\n set var.netacea_mitata_captcha_cookie_hex = crypto.decrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_captcha_iv, var.netacea_mitata_captcha_cookie_encrypted);\n set var.netacea_mitata_captcha_cookie_base64 = bin.hex_to_base64(var.netacea_mitata_captcha_cookie_hex);\n set var.netacea_mitata_captcha_cookie_value = digest.base64_decode(var.netacea_mitata_captcha_cookie_base64);\n set req.http.Cookie:_mitatacaptcha = var.netacea_mitata_captcha_cookie_value;\n if(var.netacea_mitata_captcha_cookie_sig != digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_captcha_cookie_encrypted)) {\n unset req.http.Cookie:_mitatacaptcha;\n }\n }\n }\n}\nsub cleanup_netacea_variables {\n set req.http.netacea_best_mitigation_code = \"000\";\n set req.http.netacea_match = \"0\";\n set req.http.netacea_mitigate = \"0\";\n set req.http.netacea_captcha = \"0\";\n unset req.http.mit_status;\n unset req.http.netacea_bctype_string;\n unset req.http.netacea_best_mitigation;\n unset req.http.netacea_cookies;\n unset req.http.netacea_mitata_captcha_cookie_expiry;\n unset req.http.netacea_mitata_captcha_cookie_value;\n unset req.http.netacea_mitata_must_reauthenticate;\n unset req.http.netacea_require_revalidation;\n unset req.http.netacea_set_cookies;\n unset req.http.X-Netacea-Match;\n unset req.http.X-Netacea-Mitigate;\n unset req.http.X-Netacea-Captcha;\n unset req.http.X-Netacea-Event-ID;\n unset req.http.X-Netacea-Api-Key;\n unset req.http.X-Netacea-Captcha-Status;\n unset req.http.X-Netacea-UserId;\n unset req.http.X-Netacea-Compile-JSON;\n unset req.http.x-netacea;\n}\nsub netacea_check_req {\n declare local var.netacea_mitSvc_authenticate BOOL;\n declare local var.netacea_mitSvc_apiKey STRING;\n declare local var.netacea_integration_mode STRING;\n declare local var.netacea_use_relative_path_captcha_assets STRING;\n declare local var.captcha_path STRING;\n if (req.http.x-netacea:netacea_check_req_called) {\n return;\n }\n set var.netacea_integration_mode = get_netacea_config_integration_mode();\n if (std.strlen(var.netacea_integration_mode) == 0) {\n return;\n }\n set req.http.x-netacea:netacea_check_req_called = \"true\";\n unset req.http.netacea_processed;\n if (is_path_ignored()) {\n return;\n }\n set var.netacea_mitSvc_apiKey = get_netacea_config_api_key();\n set var.netacea_use_relative_path_captcha_assets = get_netacea_config_use_relative_path_captcha_assets();\n set var.captcha_path = get_netacea_captcha_path();\n if (var.netacea_use_relative_path_captcha_assets == \"true\") {\n if (std.prefixof(req.url.path, \"/Mitigations/\") && req.method == \"GET\") {\n if (std.suffixof(req.url.path, \".css\") || std.suffixof(req.url.path, \".js\")) {\n set req.backend = F_CaptchaAssets;\n return(lookup);\n }\n }\n }\n if (var.captcha_path != \"\" && urldecode(req.url.path) == var.captcha_path) {\n set req.backend = F_MitSvc;\n if (req.backend.healthy) {\n set req.http.netacea_origin_method = \"GET\";\n set req.http.netacea_processed = \"1\";\n set req.http.netacea_captcha_path = \"1\";\n set req.http.netacea_origin_host = req.http.host;\n set req.http.netacea_origin_url = req.url;\n set req.url = \"/captcha?\" + req.url.qs;\n set req.http.X-Netacea-Api-Key = var.netacea_mitSvc_apiKey;\n return(lookup);\n }\n }\n if (req.restarts == 0 && fastly.ff.visits_this_service == 0) {\n call set_netacea_ip_header;\n if (var.netacea_integration_mode != \"BYPASS\") {\n set var.netacea_mitSvc_authenticate = true;\n call normalise_netacea_cookie_names;\n call decrypt_netacea_cookies_values;\n call process_netacea_mitata_cookie;\n }\n } else {\n if (req.http.X-Netacea-Compile-JSON == \"requested\") {\n set req.http.netacea_processed = \"1\";\n set req.http.X-Netacea-Compile-JSON = \"processing\";\n error 601;\n }\n if (var.netacea_integration_mode == \"MITIGATE\" && req.http.netacea_best_mitigation == \"block\") {\n error 403;\n }\n }\n if (req.http.Cookie:_mitata && !req.http.netacea_mitata_must_reauthenticate) {\n set var.netacea_mitSvc_authenticate = false;\n }\n set req.http.mitigation_user_id = req.http.X-Netacea-UserId;\n set req.http.integration_type = get_netacea_config_integration_type();\n set req.http.integration_version = get_netacea_config_integration_version();\n if (var.netacea_mitSvc_authenticate) {\n set req.http.netacea_set_cookies = \"1\";\n } else {\n if (var.netacea_integration_mode == \"INJECT\" && req.restarts == 0 && fastly.ff.visits_this_service == 0) {\n set req.http.X-Netacea-Match = req.http.netacea_match;\n set req.http.X-Netacea-Mitigate = req.http.netacea_mitigate;\n set req.http.X-Netacea-Captcha = req.http.netacea_captcha;\n }\n }\n if (var.netacea_integration_mode ~ \"(MITIGATE|INJECT)\" && var.netacea_mitSvc_authenticate) {\n set req.backend = F_MitSvc;\n if (req.backend.healthy) {\n unset req.http.netacea_match;\n unset req.http.netacea_mitigate;\n unset req.http.netacea_captcha;\n unset req.http.Cookie:_mitata;\n set req.http.netacea_origin_method = req.method;\n set req.http.netacea_processed = \"1\";\n set req.http.netacea_origin_host = req.http.host;\n set req.http.netacea_origin_url = req.url;\n if (req.url != \"/AtaVerifyCaptcha\") {\n set req.method = \"GET\";\n set req.url = \"/\";\n }\n set req.http.X-Netacea-Api-Key = var.netacea_mitSvc_apiKey;\n return(pass);\n }\n }\n}\n", + "template": "backend F_MitSvc {\n .between_bytes_timeout = 100ms;\n .connect_timeout = 500ms;\n .dynamic = true;\n .first_byte_timeout = 500ms;\n .host = \"geo-mitigations.netacea.net\";\n .max_connections = 200;\n .port = \"443\";\n .share_key = \"NetaceaGeoMitigations\";\n .host_header = \"geo-mitigations.netacea.net\";\n .always_use_host_header = true;\n .ssl = true;\n .ssl_cert_hostname = \"geo-mitigations.netacea.net\";\n .ssl_check_cert = always;\n .ssl_sni_hostname = \"geo-mitigations.netacea.net\";\n .probe = {\n .dummy = false;\n .initial = 5;\n .request = \"GET /_health HTTP/1.1\" \"Host: geo-mitigations.netacea.net\" \"Connection: close\" \"User-Agent: Varnish/fastly (healthcheck)\";\n .threshold = 1;\n .timeout = 2s;\n .window = 5;\n .expected_response = 200;\n }\n}\nbackend F_CaptchaAssets {\n .between_bytes_timeout = 10s;\n .connect_timeout = 1s;\n .dynamic = true;\n .first_byte_timeout = 15s;\n .host = \"assets.ntcacdn.net\";\n .max_connections = 200;\n .port = \"443\";\n .share_key = \"4nxXnE6VkrJiVuGz4G1VbJ\";\n .host_header = \"assets.ntcacdn.net\";\n .always_use_host_header = true;\n .ssl = true;\n .ssl_cert_hostname = \"assets.ntcacdn.net\";\n .ssl_check_cert = always;\n .ssl_sni_hostname = \"assets.ntcacdn.net\";\n .probe = {\n .dummy = true;\n .initial = 5;\n .request = \"HEAD / HTTP/1.1\" \"Host: assets.ntcacdn.net\" \"Connection: close\";\n .threshold = 1;\n .timeout = 2s;\n .window = 5;\n }\n}\ntable Netacea_Config {\n \"integration_type\": \"fastly/magento\",\n \"integration_version\": \"5.10.1\",\n \"integration_mode\": \"{{netacea_integration_mode}}\",\n \"api_key\": \"{{netacea_api_key}}\",\n \"secret_key\": \"{{netacea_secret}}\",\n \"encryption_key\": \"{{netacea_encryption_key}}\",\n \"cookie_name\": \"{{netacea_cookie_name}}\",\n \"captcha_cookie_name\": \"{{netacea_captcha_cookie_name}}\",\n \"ignore_list\": \"{{netacea_ignore_list}}\",\n \"use_relative_path_captcha_assets\": \"{{netacea_use_relative_path_captcha_assets}}\",\n \"real_ip_header_name\": \"{{netacea_real_ip_header_name}}\",\n \"captcha_path\": \"{{netacea_captcha_path}}\",\n \"captcha_header\": \"{{netacea_captcha_header}}\",\n \"enable_captcha_content_negotiation\": \"{{netacea_enable_ccn}}\"\n}\nsub get_netacea_config_integration_type STRING {\n return table.lookup(Netacea_Config, \"integration_type\", \"\");\n}\nsub get_netacea_config_integration_version STRING {\n return table.lookup(Netacea_Config, \"integration_version\", \"\");\n}\nsub get_netacea_config_api_key STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"api_key\");\n }\n return table.lookup(Netacea_Config, \"api_key\", \"\");\n}\nsub get_netacea_config_secret_key STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"secret_key\");\n }\n return table.lookup(Netacea_Config, \"secret_key\", \"\");\n}\nsub get_netacea_config_encryption_key STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"encryption_key\");\n }\n return table.lookup(Netacea_Config, \"encryption_key\", \"\");\n}\nsub get_netacea_config_integration_mode STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"integration_mode\");\n }\n return table.lookup(Netacea_Config, \"integration_mode\", \"\");\n}\nsub get_netacea_config_ignore_list STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"ignore_list\");\n }\n return table.lookup(Netacea_Config, \"ignore_list\", \"\");\n}\nsub get_netacea_config_cookie_name STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"cookie_name\");\n }\n return table.lookup(Netacea_Config, \"cookie_name\", \"\");\n}\nsub get_netacea_config_captcha_cookie_name STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"captcha_cookie_name\");\n }\n return table.lookup(Netacea_Config, \"captcha_cookie_name\", \"\");\n}\nsub get_netacea_config_use_relative_path_captcha_assets STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"use_relative_path_captcha_assets\");\n }\n return table.lookup(Netacea_Config, \"use_relative_path_captcha_assets\", \"\");\n}\nsub get_netacea_config_real_ip_header_name STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"real_ip_header_name\");\n }\n return table.lookup(Netacea_Config, \"real_ip_header_name\", \"\");\n}\nsub get_netacea_config_captcha_path STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"captcha_path\");\n }\n return table.lookup(Netacea_Config, \"captcha_path\", \"\");\n}\nsub get_netacea_config_captcha_header STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"captcha_header\");\n }\n return table.lookup(Netacea_Config, \"captcha_header\", \"\");\n}\nsub get_netacea_config_enable_captcha_content_negotiation STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"enable_captcha_content_negotiation\");\n }\n return table.lookup(Netacea_Config, \"enable_captcha_content_negotiation\", \"\");\n}\nsub get_sanitised_netacea_config_cookie_name STRING {\n declare local var.name STRING;\n set var.name = get_netacea_config_cookie_name();\n if (var.name ~ \"^\\s*(.*?)\\s*$\") {\n if (re.group.1 != \"\") {\n return re.group.1;\n }\n }\n return \"_mitata\";\n}\nsub get_sanitised_netacea_config_captcha_cookie_name STRING {\n declare local var.name STRING;\n set var.name = get_netacea_config_captcha_cookie_name();\n if (var.name ~ \"^\\s*(.*?)\\s*$\") {\n if (re.group.1 != \"\") {\n return re.group.1;\n }\n }\n return \"_mitatacaptcha\";\n}\ntable Netacea_Match_Dict {\n \"0\": \"\",\n \"1\": \"ua\",\n \"2\": \"ip\",\n \"3\": \"visitor\",\n \"4\": \"datacenter\",\n \"5\": \"customer_session\",\n \"6\": \"organisation\",\n \"7\": \"asn\",\n \"8\": \"country\",\n \"9\": \"combination\"\n}\ntable Netacea_Mitigate_Dict {\n \"0\": \"\",\n \"1\": \"blocked\",\n \"2\": \"allow\",\n \"3\": \"hardblocked\"\n}\ntable Netacea_Best_Mitigations_Dict {\n \"0\": \"\",\n \"1\": \"block\",\n \"2\": \"allow\",\n \"3\": \"block\"\n}\ntable Netacea_Best_Mitigations_Captcha_Dict {\n \"1\": \"captcha\",\n \"2\": \"\",\n \"3\": \"captcha\",\n \"4\": \"\",\n \"5\": \"captcha\"\n}\ntable Netacea_Captcha_Dict {\n \"0\": \"\",\n \"1\": \"captcha_serve\",\n \"2\": \"captcha_pass\",\n \"3\": \"captcha_fail\",\n \"4\": \"captcha_cookiepass\",\n \"5\": \"captcha_cookiefail\",\n}\nsub get_netacea_captcha_path STRING {\n declare local var.path STRING;\n set var.path = get_netacea_config_captcha_path();\n set var.path = regsub(var.path, \"^\\s*/*\", \"/\");\n set var.path = regsub(var.path, \"\\s*$\", \"\");\n return urldecode(var.path);\n}\nsub get_sanitised_netacea_config_captcha_header STRING {\n declare local var.value STRING;\n set var.value = get_netacea_config_captcha_header();\n set var.value = urldecode(regsuball(var.value, \"&#x(.{2});\", \"%25\\1\"));\n set var.value = std.replaceall(var.value, \""\", \"%22\");\n set var.value = std.replaceall(var.value, \"<\", \"<\");\n set var.value = std.replaceall(var.value, \">\", \">\");\n set var.value = std.replaceall(var.value, \"&\", \"&\");\n return var.value;\n}\nsub get_netacea_captcha_header_name STRING {\n declare local var.config STRING;\n set var.config = get_sanitised_netacea_config_captcha_header();\n if (var.config ~ \"(?i)(?:^|&)\\s*name\\s*=\\s*(.*?)\\s*(?:&|$)\") {\n return re.group.1;\n }\n return \"\";\n}\nsub get_netacea_captcha_header_value STRING {\n declare local var.config STRING;\n set var.config = get_sanitised_netacea_config_captcha_header();\n if (var.config ~ \"(?i)(?:^|&)\\s*value\\s*=\\s*(.*?)\\s*(?:&|$)\") {\n return re.group.1;\n }\n return \"\";\n}\nsub is_path_ignored BOOL {\n declare local var.netacea_ignore_list STRING;\n declare local var.req_path STRING;\n set var.netacea_ignore_list = get_netacea_config_ignore_list();\n set var.req_path = urldecode(req.url.path);\n set var.netacea_ignore_list = regsuball(var.netacea_ignore_list, \"\\s*(,\\s*)+\", \",\");\n set var.netacea_ignore_list = regsuball(var.netacea_ignore_list, \"(^|,)\\s*/*\", \"\\1/\");\n set var.netacea_ignore_list = regsuball(var.netacea_ignore_list, \"/*\\s*(,|$)\", \"\\1\");\n if (var.netacea_ignore_list ~ \"^([^,]+),*([^,]+)?,*([^,]+)?,*([^,]+)?,*([^,]+)?\") {\n if (re.group.1 && (var.req_path == urldecode(re.group.1) || std.prefixof(var.req_path, urldecode(re.group.1) + \"/\"))) {\n return true;\n }\n if (re.group.2 && (var.req_path == urldecode(re.group.2) || std.prefixof(var.req_path, urldecode(re.group.2) + \"/\"))) {\n return true;\n }\n if (re.group.3 && (var.req_path == urldecode(re.group.3) || std.prefixof(var.req_path, urldecode(re.group.3) + \"/\"))) {\n return true;\n }\n if (re.group.4 && (var.req_path == urldecode(re.group.4) || std.prefixof(var.req_path, urldecode(re.group.4) + \"/\"))) {\n return true;\n }\n if (re.group.5 && (var.req_path == urldecode(re.group.5) || std.prefixof(var.req_path, urldecode(re.group.5) + \"/\"))) {\n return true;\n }\n }\n return false;\n}\nsub netacea_should_return_json BOOL {\n declare local var.enable_captcha_content_negotiation STRING;\n set var.enable_captcha_content_negotiation = get_netacea_config_enable_captcha_content_negotiation();\n if (var.enable_captcha_content_negotiation != \"true\") {\n return false;\n }\n declare local var.html_weight FLOAT;\n declare local var.json_weight FLOAT;\n set var.html_weight = 0.0;\n set var.json_weight = 0.0;\n if (req.http.Accept ~ \"(?i)(^|,)\\s*application/json\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.json_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n } elseif (req.http.Accept ~ \"(?i)(^|,)\\s*application/\\*\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.json_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n }\n if (req.http.Accept ~ \"(?i)(^|,)\\s*text/html\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.html_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n } elseif (req.http.Accept ~ \"(^|,)\\s*text/\\*\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.html_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n }\n return var.json_weight > var.html_weight;\n}\nsub netacea_hide_response_headers {\n unset resp.http.X-Netacea-Captcha;\n unset resp.http.X-Netacea-Event-ID;\n unset resp.http.X-Netacea-Match;\n unset resp.http.X-Netacea-MitATA-Expiry;\n unset resp.http.X-Netacea-MitATA-Value;\n unset resp.http.X-Netacea-Mitigate;\n}\nsub set_netacea_captcha_header {\n declare local var.captcha_header_name STRING;\n declare local var.captcha_header_value STRING;\n set var.captcha_header_name = get_netacea_captcha_header_name();\n set var.captcha_header_value = get_netacea_captcha_header_value();\n if (var.captcha_header_name != \"\") {\n header.set(resp, var.captcha_header_name, var.captcha_header_value);\n }\n}\nsub set_netacea_ip_header {\n declare local var.ip_header_name STRING;\n set var.ip_header_name = get_netacea_config_real_ip_header_name();\n declare local var.ip_header_value STRING;\n set var.ip_header_value = if (std.strlen(var.ip_header_name) > 0, header.get(req, var.ip_header_name), \"\");\n set req.http.X-Netacea-Client-IP = if (std.strlen(var.ip_header_value) > 0, var.ip_header_value, client.ip);\n}\nsub set_netacea_cookies {\n if (req.http.netacea_set_cookies == \"1\") {\n declare local var.ignored BOOL;\n declare local var.netacea_mitSvc_secret STRING;\n declare local var.netacea_encryption_key STRING;\n set var.ignored = setcookie.delete_by_name(resp, \"_mitata\");\n set var.ignored = setcookie.delete_by_name(resp, \"_mitatacaptcha\");\n declare local var.netacea_captcha_cookie_name STRING;\n set var.netacea_captcha_cookie_name = get_sanitised_netacea_config_captcha_cookie_name();\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n set var.netacea_encryption_key = get_netacea_config_encryption_key();\n call set_mitata_cookie;\n if (req.http.netacea_mitata_captcha_cookie_value && req.http.netacea_mitata_captcha_cookie_expiry) {\n if (var.netacea_encryption_key ~ \".\") {\n declare local var.netacea_iv STRING;\n declare local var.netacea_iv_trimmed STRING;\n declare local var.netacea_sig STRING;\n declare local var.netacea_mitata_captcha_cookie_value_base64 STRING;\n declare local var.netacea_mitata_captcha_cookie_value_hex STRING;\n declare local var.netacea_mitata_captcha_cookie_value_encrypted STRING;\n declare local var.netacea_mitata_captcha_cookie_final_value STRING;\n set var.netacea_mitata_captcha_cookie_value_base64 = digest.base64(req.http.netacea_mitata_captcha_cookie_value);\n set var.netacea_mitata_captcha_cookie_value_hex = bin.base64_to_hex(var.netacea_mitata_captcha_cookie_value_base64);\n set var.netacea_iv = uuid.version4();\n set var.netacea_iv_trimmed = std.replaceall(var.netacea_iv, \"-\", \"\");\n set var.netacea_mitata_captcha_cookie_value_encrypted = crypto.encrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv_trimmed, var.netacea_mitata_captcha_cookie_value_hex);\n set var.netacea_sig = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_captcha_cookie_value_encrypted);\n set var.netacea_mitata_captcha_cookie_final_value = var.netacea_iv_trimmed + \".\" + var.netacea_mitata_captcha_cookie_value_encrypted + \".\" + var.netacea_sig;\n add resp.http.Set-Cookie = var.netacea_captcha_cookie_name + \"=\" + var.netacea_mitata_captcha_cookie_final_value + \"; Max-Age=\" + req.http.netacea_mitata_captcha_cookie_expiry + \"; Path=/;\";\n }\n if (var.netacea_encryption_key !~ \".\") {\n add resp.http.Set-Cookie = var.netacea_captcha_cookie_name + \"=\" + req.http.netacea_mitata_captcha_cookie_value + \"; Max-Age=\" + req.http.netacea_mitata_captcha_cookie_expiry + \"; Path=/;\";\n }\n }\n }\n}\nsub netacea_calculate_best_mitigation {\n if (!req.http.netacea_bctype_string) {\n declare local var.netacea_match STRING;\n declare local var.netacea_mitigate STRING;\n declare local var.netacea_captcha STRING;\n declare local var.netacea_match_string STRING;\n declare local var.netacea_mitigate_string STRING;\n declare local var.netacea_captcha_string STRING;\n declare local var.netacea_captcha_mitigate_string STRING;\n declare local var.netacea_best_mitigation STRING;\n declare local var.netacea_bctype_string STRING;\n if (resp.http.x-netacea-match) { \n set var.netacea_match = resp.http.x-netacea-match;\n } elseif (req.http.netacea_match) { \n set var.netacea_match = req.http.netacea_match;\n } else {\n set var.netacea_match = \"0\";\n }\n if (resp.http.x-netacea-mitigate) { \n set var.netacea_mitigate = resp.http.x-netacea-mitigate;\n } elseif (req.http.netacea_mitigate) { \n set var.netacea_mitigate = req.http.netacea_mitigate;\n } else {\n set var.netacea_mitigate = \"0\";\n }\n if (resp.http.x-netacea-captcha) { \n set var.netacea_captcha = resp.http.x-netacea-captcha;\n } elseif (req.http.netacea_captcha) { \n set var.netacea_captcha = req.http.netacea_captcha;\n } else {\n set var.netacea_captcha = \"0\";\n }\n if (var.netacea_match) {\n set var.netacea_match_string = table.lookup(Netacea_Match_Dict, var.netacea_match, \"unknown\");\n if (var.netacea_match_string != \"\") {\n set var.netacea_bctype_string = var.netacea_match_string + \"_\";\n }\n }\n if (var.netacea_mitigate) {\n set var.netacea_mitigate_string = table.lookup(Netacea_Mitigate_Dict, var.netacea_mitigate, \"unknown\");\n if (var.netacea_mitigate_string != \"\") {\n set var.netacea_bctype_string = var.netacea_bctype_string + var.netacea_mitigate_string;\n }\n set var.netacea_best_mitigation = table.lookup(Netacea_Best_Mitigations_Dict, var.netacea_mitigate, \"no-best-mitigation\");\n if (var.netacea_best_mitigation == \"no-best-mitigation\") {\n set var.netacea_best_mitigation = \"\";\n }\n }\n if (var.netacea_captcha) {\n if (req.url != \"/AtaVerifyCaptcha\") {\n if (var.netacea_captcha == \"2\") {\n set var.netacea_captcha = \"4\";\n } elseif (var.netacea_captcha == \"3\") {\n set var.netacea_captcha = \"5\";\n }\n }\n set var.netacea_captcha_string = table.lookup(Netacea_Captcha_Dict, var.netacea_captcha, \"unknown\");\n if (var.netacea_captcha_string != \"\") {\n set var.netacea_bctype_string = var.netacea_bctype_string + \",\" + var.netacea_captcha_string;\n }\n set var.netacea_captcha_mitigate_string = table.lookup(Netacea_Best_Mitigations_Captcha_Dict, var.netacea_captcha, \"no-best-captcha-mitigation\");\n if (var.netacea_captcha_mitigate_string != \"no-best-captcha-mitigation\") {\n set var.netacea_best_mitigation = var.netacea_captcha_mitigate_string;\n }\n }\n set req.http.netacea_bctype_string = var.netacea_bctype_string;\n set req.http.netacea_best_mitigation = var.netacea_best_mitigation;\n set req.http.netacea_best_mitigation_code = var.netacea_match + var.netacea_mitigate + var.netacea_captcha;\n if (var.netacea_mitigate == \"3\") {\n set req.http.netacea_require_revalidation = \"1\";\n }\n if (var.netacea_mitigate == \"1\" && var.netacea_captcha != \"2\" && var.netacea_captcha != \"4\") {\n set req.http.netacea_require_revalidation = \"1\";\n }\n }\n}\nsub set_mitata_cookie {\n declare local var.netacea_mitSvc_secret STRING;\n declare local var.netacea_encryption_key STRING;\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n set var.netacea_encryption_key = get_netacea_config_encryption_key();\n if (!req.http.X-Netacea-UserId) {\n set req.http.X-Netacea-UserId = \"c\" + randomstr(15, \"1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\");\n set req.http.x-netacea:cookie_session_status = \"1\";\n }\n declare local var.netacea_iv STRING;\n declare local var.netacea_iv_trimmed STRING;\n declare local var.netacea_sig STRING;\n declare local var.netacea_mitata_cookie_full_value_base64 STRING;\n declare local var.netacea_mitata_cookie_full_value_hex STRING;\n declare local var.netacea_mitata_cookie_full_value_encrypted STRING;\n declare local var.netacea_mitata_cookie_final_value STRING;\n declare local var.netacea_mitata_cookie_full_value STRING;\n declare local var.netacea_ataCookie_stringValue STRING;\n declare local var.netacea_ataCookie_HMAC STRING;\n declare local var.netacea_mitSvc_exp STRING;\n declare local var.netacea_mitSvc_sig STRING;\n declare local var.netacea_mitSvc_userId STRING;\n declare local var.netacea_mitigation_code STRING;\n declare local var.netacea_client_ip_time_ua STRING;\n declare local var.netacea_client_ip_time_ua_hash STRING;\n declare local var.netacea_cookie_name STRING;\n set var.netacea_mitigation_code = req.http.netacea_best_mitigation_code;\n set var.netacea_mitSvc_userId = req.http.X-Netacea-UserId;\n set var.netacea_cookie_name = get_sanitised_netacea_config_cookie_name();\n if (req.http.netacea_require_revalidation == \"1\") {\n set var.netacea_mitSvc_exp = time.units(\"s\", time.sub(now, 1m));\n } else {\n set var.netacea_mitSvc_exp = time.units(\"s\", time.add(now, 1m));\n }\n set var.netacea_client_ip_time_ua = req.http.X-Netacea-Client-IP + \"|\" + var.netacea_mitSvc_exp + \"|\" + req.http.user-agent;\n set var.netacea_client_ip_time_ua_hash = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_client_ip_time_ua);\n if (var.netacea_client_ip_time_ua_hash ~ \"0x(.*)\") {\n set var.netacea_client_ip_time_ua_hash = re.group.1;\n }\n set var.netacea_ataCookie_stringValue = var.netacea_mitSvc_exp + \"_/@#/\" + var.netacea_mitSvc_userId + \"_/@#/\" + digest.base64(var.netacea_client_ip_time_ua_hash) + \"_/@#/\" + var.netacea_mitigation_code;\n set var.netacea_ataCookie_HMAC = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_ataCookie_stringValue);\n if (var.netacea_ataCookie_HMAC ~ \"0x(.*)\") {\n set var.netacea_ataCookie_HMAC = re.group.1;\n }\n set var.netacea_mitSvc_sig = digest.base64(var.netacea_ataCookie_HMAC);\n set var.netacea_mitata_cookie_full_value = var.netacea_mitSvc_sig + \"_/@#/\" + var.netacea_ataCookie_stringValue;\n if (var.netacea_encryption_key ~ \".\") {\n set var.netacea_mitata_cookie_full_value_base64 = digest.base64(var.netacea_mitata_cookie_full_value);\n set var.netacea_mitata_cookie_full_value_hex = bin.base64_to_hex(var.netacea_mitata_cookie_full_value_base64);\n set var.netacea_iv = uuid.version4();\n set var.netacea_iv_trimmed = std.replaceall(var.netacea_iv, \"-\", \"\");\n set var.netacea_mitata_cookie_full_value_encrypted = crypto.encrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv_trimmed, var.netacea_mitata_cookie_full_value_hex);\n set var.netacea_sig = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_cookie_full_value_encrypted);\n set var.netacea_mitata_cookie_final_value = var.netacea_iv_trimmed + \".\" + var.netacea_mitata_cookie_full_value_encrypted + \".\" + var.netacea_sig;\n add resp.http.Set-Cookie = var.netacea_cookie_name + \"=\" + var.netacea_mitata_cookie_final_value + \"; Max-Age=\" + time.units(\"s\", 1d) + \"; Path=/;\";\n }\n if (var.netacea_encryption_key !~ \".\") {\n add resp.http.Set-Cookie = var.netacea_cookie_name + \"=\" + var.netacea_mitata_cookie_full_value+ \"; Max-Age=\" + time.units(\"s\", 1d) + \"; Path=/;\";\n }\n set req.http.mitigation_user_id = var.netacea_mitSvc_userId;\n}\nsub process_netacea_mitata_cookie {\n declare local var.netacea_mitSvc_secret STRING;\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n declare local var.netacea_cookie_sig STRING;\n declare local var.netacea_cookie_payload STRING;\n declare local var.netacea_cookie_expiry STRING;\n declare local var.netacea_client_ip_time_ua_hash STRING;\n declare local var.netacea_real_client_ip_time_ua STRING;\n declare local var.netacea_real_client_ip_time_ua_hash STRING;\n declare local var.netacea_cookie_HMAC STRING;\n declare local var.netacea_cookie_real_value STRING;\n if (req.http.Cookie:_mitata) {\n if (req.http.Cookie:_mitata ~ \"^(.*)_\\/@#\\/((\\d+)_\\/@#\\/(.+)_\\/@#\\/(.+)_\\/@#\\/((\\d)(\\d)(\\d)))$\") {\n set var.netacea_cookie_sig = re.group.1;\n set var.netacea_cookie_payload = re.group.2;\n set var.netacea_cookie_expiry = re.group.3;\n set req.http.X-Netacea-UserId = re.group.4;\n set var.netacea_client_ip_time_ua_hash = re.group.5;\n set req.http.netacea_match = re.group.7;\n set req.http.netacea_mitigate = re.group.8;\n set req.http.netacea_captcha = re.group.9;\n set var.netacea_cookie_real_value = var.netacea_cookie_expiry + \"_/@#/\" + req.http.X-Netacea-UserId + \"_/@#/\" + var.netacea_client_ip_time_ua_hash + \"_/@#/\" + req.http.netacea_match + req.http.netacea_mitigate + req.http.netacea_captcha;\n set var.netacea_cookie_HMAC = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_cookie_real_value);\n if (var.netacea_cookie_HMAC ~ \"0x(.*)\") {\n set var.netacea_cookie_HMAC = re.group.1;\n }\n set var.netacea_real_client_ip_time_ua = req.http.X-Netacea-Client-IP + \"|\" + var.netacea_cookie_expiry + \"|\" + req.http.user-agent;\n set var.netacea_real_client_ip_time_ua_hash = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_real_client_ip_time_ua);\n if (var.netacea_real_client_ip_time_ua_hash ~ \"0x(.*)\") {\n set var.netacea_real_client_ip_time_ua_hash = re.group.1;\n }\n if (var.netacea_cookie_sig != digest.base64(var.netacea_cookie_HMAC)) {\n unset req.http.Cookie:_mitata;\n unset req.http.X-Netacea-UserId;\n unset req.http.netacea_match;\n unset req.http.netacea_mitigate;\n unset req.http.netacea_captcha;\n } else {\n if (time.is_after(now, std.time(var.netacea_cookie_expiry, now)) || digest.base64(var.netacea_real_client_ip_time_ua_hash) != var.netacea_client_ip_time_ua_hash ) {\n set req.http.netacea_mitata_must_reauthenticate = \"1\";\n set req.http.x-netacea:cookie_session_status = \"3\";\n } else {\n set req.http.x-netacea:cookie_session_status = \"2\";\n }\n }\n } else {\n unset req.http.Cookie:_mitata;\n }\n }\n if (!req.http.Cookie:_mitata) {\n unset req.http.Cookie:_mitatacaptcha;\n }\n}\nsub normalise_netacea_cookie_names {\n declare local var.netacea_custom_cookie_name STRING;\n declare local var.netacea_custom_captcha_cookie_name STRING;\n set var.netacea_custom_cookie_name = get_sanitised_netacea_config_cookie_name();\n set var.netacea_custom_captcha_cookie_name = get_sanitised_netacea_config_captcha_cookie_name();\n set req.http.Cookie = regsuball(req.http.Cookie, \";\\s*+\", \"; \");\n if (var.netacea_custom_cookie_name !~ \"^_mitata$\") {\n unset req.http.Cookie:_mitata;\n set req.http.Cookie = std.replace_prefix(req.http.Cookie, var.netacea_custom_cookie_name + \"=\", \"_mitata=\");\n set req.http.Cookie = std.replace(req.http.Cookie, \"; \" + var.netacea_custom_cookie_name + \"=\", \"; _mitata=\");\n }\n if (var.netacea_custom_captcha_cookie_name !~ \"^_mitatacaptcha$\") {\n unset req.http.Cookie:_mitatacaptcha;\n set req.http.Cookie = std.replace_prefix(req.http.Cookie, var.netacea_custom_captcha_cookie_name + \"=\", \"_mitatacaptcha=\");\n set req.http.Cookie = std.replace(req.http.Cookie, \"; \" + var.netacea_custom_captcha_cookie_name + \"=\", \"; _mitatacaptcha=\");\n }\n}\nsub decrypt_netacea_cookies_values {\n declare local var.netacea_mitSvc_secret STRING;\n declare local var.netacea_mitata_cookie_encrypted STRING;\n declare local var.netacea_encryption_key STRING;\n declare local var.netacea_iv STRING;\n declare local var.netacea_mitata_cookie_base64 STRING;\n declare local var.netacea_mitata_cookie_hex STRING;\n declare local var.netacea_mitata_cookie_value STRING;\n declare local var.netacea_mitata_cookie_sig STRING;\n declare local var.netacea_mitata_captcha_cookie_encrypted STRING;\n declare local var.netacea_captcha_iv STRING;\n declare local var.netacea_mitata_captcha_cookie_base64 STRING;\n declare local var.netacea_mitata_captcha_cookie_hex STRING;\n declare local var.netacea_mitata_captcha_cookie_value STRING;\n declare local var.netacea_mitata_captcha_cookie_sig STRING;\n set var.netacea_encryption_key = get_netacea_config_encryption_key();\n if (var.netacea_encryption_key ~ \".\") {\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n if (req.http.Cookie:_mitata ~ \".\") {\n if (req.http.Cookie:_mitata ~ \"^(.*?)\\.\") {\n set var.netacea_iv = re.group.1;\n }\n if (req.http.Cookie:_mitata ~ \"\\.(.*?)\\.\") {\n set var.netacea_mitata_cookie_encrypted = re.group.1;\n }\n if (req.http.Cookie:_mitata ~ \"([^\\.]+$)\") {\n set var.netacea_mitata_cookie_sig = re.group.1;\n }\n set var.netacea_mitata_cookie_hex = crypto.decrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv, var.netacea_mitata_cookie_encrypted);\n set var.netacea_mitata_cookie_base64 = bin.hex_to_base64(var.netacea_mitata_cookie_hex);\n set var.netacea_mitata_cookie_value = digest.base64_decode(var.netacea_mitata_cookie_base64);\n set req.http.Cookie:_mitata = var.netacea_mitata_cookie_value;\n if(var.netacea_mitata_cookie_sig != digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_cookie_encrypted)) {\n unset req.http.Cookie:_mitata;\n }\n }\n if (req.http.Cookie:_mitatacaptcha ~ \"^(.*?)\\.\") {\n if (req.http.Cookie:_mitatacaptcha ~ \"^(.*?)\\.\") {\n set var.netacea_captcha_iv = re.group.1;\n }\n if (req.http.Cookie:_mitatacaptcha ~ \"\\.(.*?)\\.\") {\n set var.netacea_mitata_captcha_cookie_encrypted = re.group.1;\n }\n if (req.http.Cookie:_mitatacaptcha ~ \"([^\\.]+$)\") {\n set var.netacea_mitata_captcha_cookie_sig = re.group.1;\n }\n set var.netacea_mitata_captcha_cookie_hex = crypto.decrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_captcha_iv, var.netacea_mitata_captcha_cookie_encrypted);\n set var.netacea_mitata_captcha_cookie_base64 = bin.hex_to_base64(var.netacea_mitata_captcha_cookie_hex);\n set var.netacea_mitata_captcha_cookie_value = digest.base64_decode(var.netacea_mitata_captcha_cookie_base64);\n set req.http.Cookie:_mitatacaptcha = var.netacea_mitata_captcha_cookie_value;\n if(var.netacea_mitata_captcha_cookie_sig != digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_captcha_cookie_encrypted)) {\n unset req.http.Cookie:_mitatacaptcha;\n }\n }\n }\n}\nsub cleanup_netacea_variables {\n if (fastly.ff.visits_this_service > 0) {\n return;\n }\n set req.http.netacea_best_mitigation_code = \"000\";\n set req.http.netacea_match = \"0\";\n set req.http.netacea_mitigate = \"0\";\n set req.http.netacea_captcha = \"0\";\n unset req.http.mit_status;\n unset req.http.netacea_bctype_string;\n unset req.http.netacea_best_mitigation;\n unset req.http.netacea_cookies;\n unset req.http.netacea_mitata_captcha_cookie_expiry;\n unset req.http.netacea_mitata_captcha_cookie_value;\n unset req.http.netacea_mitata_must_reauthenticate;\n unset req.http.netacea_require_revalidation;\n unset req.http.netacea_set_cookies;\n unset req.http.X-Netacea-Match;\n unset req.http.X-Netacea-Mitigate;\n unset req.http.X-Netacea-Captcha;\n unset req.http.X-Netacea-Event-ID;\n unset req.http.X-Netacea-Api-Key;\n unset req.http.X-Netacea-Captcha-Status;\n unset req.http.X-Netacea-UserId;\n unset req.http.X-Netacea-Compile-JSON;\n unset req.http.x-netacea;\n}\nsub netacea_check_req {\n if (req.is_purge) {\n return;\n }\n declare local var.netacea_mitSvc_authenticate BOOL;\n declare local var.netacea_mitSvc_apiKey STRING;\n declare local var.netacea_integration_mode STRING;\n declare local var.netacea_use_relative_path_captcha_assets STRING;\n declare local var.captcha_path STRING;\n set req.http.x-netacea:integration_mode = get_netacea_config_integration_mode();\n if (req.http.x-netacea:netacea_check_req_called || fastly.ff.visits_this_service > 0) {\n return;\n }\n set var.netacea_integration_mode = get_netacea_config_integration_mode();\n if (std.strlen(var.netacea_integration_mode) == 0) {\n return;\n }\n set req.http.x-netacea:netacea_check_req_called = \"true\";\n unset req.http.netacea_processed;\n if (is_path_ignored()) {\n return;\n }\n set var.netacea_mitSvc_apiKey = get_netacea_config_api_key();\n set var.netacea_use_relative_path_captcha_assets = get_netacea_config_use_relative_path_captcha_assets();\n set var.captcha_path = get_netacea_captcha_path();\n if (var.netacea_use_relative_path_captcha_assets == \"true\") {\n if (std.prefixof(req.url.path, \"/Mitigations/\") && req.method == \"GET\") {\n if (std.suffixof(req.url.path, \".css\") || std.suffixof(req.url.path, \".js\")) {\n set req.backend = F_CaptchaAssets;\n return(lookup);\n }\n }\n }\n if (var.captcha_path != \"\" && urldecode(req.url.path) == var.captcha_path) {\n set req.backend = F_MitSvc;\n set req.http.x-netacea:mit_svc_start_time = time.elapsed.msec;\n if (req.backend.healthy) {\n set req.http.netacea_origin_method = \"GET\";\n set req.http.netacea_processed = \"1\";\n set req.http.netacea_captcha_path = \"1\";\n set req.http.netacea_origin_host = req.http.host;\n set req.http.netacea_origin_url = req.url;\n set req.url = \"/captcha?\" + req.url.qs;\n set req.http.X-Netacea-Api-Key = var.netacea_mitSvc_apiKey;\n return(lookup);\n }\n }\n if (req.restarts == 0) {\n call set_netacea_ip_header;\n if (var.netacea_integration_mode != \"BYPASS\") {\n set var.netacea_mitSvc_authenticate = true;\n call normalise_netacea_cookie_names;\n call decrypt_netacea_cookies_values;\n call process_netacea_mitata_cookie;\n }\n } else {\n if (req.http.X-Netacea-Compile-JSON == \"requested\") {\n set req.http.netacea_processed = \"1\";\n set req.http.X-Netacea-Compile-JSON = \"processing\";\n error 601;\n }\n if (var.netacea_integration_mode == \"MITIGATE\" && req.http.netacea_best_mitigation == \"block\") {\n error 403;\n }\n }\n if (req.http.Cookie:_mitata && !req.http.netacea_mitata_must_reauthenticate) {\n set var.netacea_mitSvc_authenticate = false;\n set req.http.x-netacea:cookie_session_status = \"2\";\n }\n set req.http.mitigation_user_id = req.http.X-Netacea-UserId;\n set req.http.integration_type = get_netacea_config_integration_type();\n set req.http.integration_version = get_netacea_config_integration_version();\n if (var.netacea_mitSvc_authenticate) {\n set req.http.netacea_set_cookies = \"1\";\n } else {\n if (var.netacea_integration_mode == \"INJECT\" && req.restarts == 0) {\n set req.http.X-Netacea-Match = req.http.netacea_match;\n set req.http.X-Netacea-Mitigate = req.http.netacea_mitigate;\n set req.http.X-Netacea-Captcha = req.http.netacea_captcha;\n }\n }\n if (var.netacea_integration_mode ~ \"(MITIGATE|INJECT)\" && var.netacea_mitSvc_authenticate) {\n set req.backend = F_MitSvc;\n set req.http.x-netacea:mit_svc_start_time = time.elapsed.msec;\n if (req.backend.healthy) {\n unset req.http.netacea_match;\n unset req.http.netacea_mitigate;\n unset req.http.netacea_captcha;\n unset req.http.Cookie:_mitata;\n set req.http.netacea_origin_method = req.method;\n set req.http.netacea_processed = \"1\";\n set req.http.netacea_origin_host = req.http.host;\n set req.http.netacea_origin_url = req.url;\n if (req.url != \"/AtaVerifyCaptcha\") {\n set req.method = \"GET\";\n set req.url = \"/\";\n }\n set req.http.X-Netacea-Api-Key = var.netacea_mitSvc_apiKey;\n return(pass);\n }\n }\n}\n", "type": "init" } ], - "version": "5.7.0" + "version": "5.10.1" } diff --git a/etc/vcl_snippets/deliver.vcl b/etc/vcl_snippets/deliver.vcl index 1d99281f..7c72e58a 100644 --- a/etc/vcl_snippets/deliver.vcl +++ b/etc/vcl_snippets/deliver.vcl @@ -39,7 +39,7 @@ # Add an easy way to see whether custom Fastly VCL has been uploaded if ( req.http.Fastly-Debug ) { - set resp.http.Fastly-Magento-VCL-Uploaded = "1.2.211"; + set resp.http.Fastly-Magento-VCL-Uploaded = "1.2.217"; if (table.lookup(magentomodule_config, "allow_super_users_during_maint", "0") == "1") { set resp.http.Fastly-Magento-Maintenance-Mode = "on"; } diff --git a/etc/vcl_snippets/fetch.vcl b/etc/vcl_snippets/fetch.vcl index 49ef9e5f..0e697261 100644 --- a/etc/vcl_snippets/fetch.vcl +++ b/etc/vcl_snippets/fetch.vcl @@ -52,7 +52,9 @@ if (!beresp.http.Vary ~ "Accept-Encoding") { set beresp.http.Vary:Accept-Encoding = ""; } - if (req.http.Accept-Encoding == "gzip") { + if (req.http.Accept-Encoding == "br") { + set beresp.brotli = true; + } else if (req.http.Accept-Encoding == "gzip") { set beresp.gzip = true; } } diff --git a/etc/vcl_snippets/miss.vcl b/etc/vcl_snippets/miss.vcl index bbc41756..b35a8438 100644 --- a/etc/vcl_snippets/miss.vcl +++ b/etc/vcl_snippets/miss.vcl @@ -3,4 +3,4 @@ unset bereq.http.Accept-Encoding; # Send VCL version uploaded to the backend - set bereq.http.Fastly-Magento-VCL-Uploaded = "1.2.211"; + set bereq.http.Fastly-Magento-VCL-Uploaded = "1.2.217"; diff --git a/etc/vcl_snippets/pass.vcl b/etc/vcl_snippets/pass.vcl index dc5fc5eb..7a82a872 100644 --- a/etc/vcl_snippets/pass.vcl +++ b/etc/vcl_snippets/pass.vcl @@ -12,4 +12,4 @@ } # Send VCL version uploaded to the backend - set bereq.http.Fastly-Magento-VCL-Uploaded = "1.2.211"; + set bereq.http.Fastly-Magento-VCL-Uploaded = "1.2.217"; diff --git a/etc/vcl_snippets/recv.vcl b/etc/vcl_snippets/recv.vcl index dad826df..56f3c38e 100644 --- a/etc/vcl_snippets/recv.vcl +++ b/etc/vcl_snippets/recv.vcl @@ -106,6 +106,13 @@ set req.http.Https = "on"; } + # Add support for Brotli static compression + if (req.http.Fastly-Orig-Accept-Encoding) { + if (req.http.Fastly-Orig-Accept-Encoding ~ "\bbr\b") { + set req.http.Accept-Encoding = "br"; + } + } + if (fastly.ff.visits_this_service > 0) { # disable ESI processing on Origin Shield set req.esi = false; diff --git a/view/adminhtml/web/js/log-endpoints.js b/view/adminhtml/web/js/log-endpoints.js index 5914c247..34d4e4cb 100644 --- a/view/adminhtml/web/js/log-endpoints.js +++ b/view/adminhtml/web/js/log-endpoints.js @@ -96,14 +96,20 @@ define([ $('#condition_priority').val(''); return getResponseConditions(active_version, loaderVisibility) .done(function (response) { - let html = ''; $('#attach_span').hide(); if (response !== false) { + let conditionElement = document.getElementById('conditions'); conditions = response.conditions; - html += ''; + let option = document.createElement("option"); + option.text = 'no condition'; + option.value = ''; + conditionElement.add(option); $.each(conditions, function (index, condition) { - if (condition.type === "REQUEST") { - html += ''; + if (condition.type === "RESPONSE") { + let option = document.createElement("option"); + option.text = _.escape(condition.name) +' ('+condition.type+') ' + _.escape(condition.statement); + option.value = _.escape(condition.name); + conditionElement.add(option); } }); } @@ -112,7 +118,6 @@ define([ $('#detach').show(); $('#create-response-condition').show(); $('#sep').show(); - $('#conditions').html(html); }) }