← Cloudflare Ruleset Engine / ruleset-engine / rules-language
Функции
Cloudflare Rules language предоставляет функции для обработки и проверки значений в выражении:
- Функции преобразования обрабатывают значения, извлечённые из HTTP-запроса.
- Функция проверки HMAC проверяет действительность токена HMAC. Используйте эту функцию, чтобы писать выражения, которые определяют запросы по наличию действительного токена HMAC.
Функции преобразования
Rules language поддерживает несколько функций для преобразования значений, извлечённых из HTTP-запросов. Типичным примером использования функций преобразования является приведение строки символов к верхнему или нижнему регистру, поскольку по умолчанию сравнение строк выполняется с учётом регистра.
Например, lower() функция преобразует все символы верхнего регистра в строке в нижний регистр.
В приведённом ниже выражении lower() функция преобразует http.host значения в нижний регистр, чтобы они соответствовали целевому значению "www.cloudflare.com":
lower(http.host) == "www.cloudflare.com"Для функций преобразования, которые не принимают массивы в качестве типа аргумента, требуется [*] индексную запись. См. Массивы, где это описано подробнее.
Rules language поддерживает следующие функции преобразования:
any
any(: Array<Boolean>)Boolean
Возвращает true когда оператор сравнения в аргументе возвращает true для any значений в массиве аргументов. Возвращает false в противном случае.
Пример:
any(url_decode(http.request.body.form.values[*])[*] contains "an xss attack")all
all(: Array<Boolean>)Boolean
Возвращает true когда оператор сравнения в аргументе возвращает true для all значений в массиве аргументов. Возвращает false в противном случае.
Пример:
all(http.request.headers["content-type"][*] == "application/json")encode_base64
encode_base64(input : String | Bytes [, flags String])String
Кодирует input строку или массив байтов в формат Base64.
flags параметр необязателен. Можно указать один или несколько флагов в виде одной строки. Доступны следующие флаги:
u: Использует URL-safe кодирование Base64 (использует-и_вместо+и/).p: Добавляет дополнение (добавляет=символов, чтобы длина результата была кратна 4, как того требуют некоторые системы).
По умолчанию результат кодируется в стандартном формате Base64 без дополнения (padding).
Примеры:
encode_base64("hello world") will return "aGVsbG8gd29ybGQ"
encode_base64("hello world", "p") will return "aGVsbG8gd29ybGQ="
encode_base64("hello world", "u") will return "aGVsbG8gd29ybGQ"
encode_base64("hello world", "up") will return "aGVsbG8gd29ybGQ="Вы можете объединять encode_base64() с другими функциями, чтобы создавать подписанные заголовки запроса:
encode_base64(sha256(concat(to_string(ip.src), http.host, "my-secret")))cidr
cidr(address : IP address, ipv4_network_bits Integer, ipv6_network_bits Integer)IP address
Возвращает адрес сети, соответствующий IP-адресу (IPv4 или IPv6), с учётом указанных битов сети для IPv4 и IPv6 (которые определяют соответствующие маски подсети).
address параметр должен быть полем, то есть не может быть литералом String.
ipv4_network_bits значение должно быть от 1 до 32, а ipv6_network_bits значение должно быть от 1 до 128.
Примеры:
- Если
ip.srcэто113.10.0.2,cidr(ip.src, 24, 24)вернёт113.10.0.0. - Если
ip.srcэто2001:0000:130F:0000:0000:09C0:876A:130B,cidr(ip.src, 24, 24)вернёт2001:0000:0000:0000:0000:0000:0000:0000.
cidr6
cidr6(address : IP address, ipv6_network_bits Integer)IP address
Возвращает адрес сети IPv6, соответствующий адресу IPv6, с учётом указанных битов сети (которые определяют маску подсети). Если в первом параметре вы укажете адрес IPv4, он будет возвращён без изменений.
address параметр должен быть полем, то есть не может быть литералом String.
ipv6_network_bits значение должно быть от 1 до 128.
Эта функция эквивалентна: cidr(<address>, 32, <ipv6_network_bits>).
Примеры:
- Если
ip.srcэто2001:0000:130F:0000:0000:09C0:876A:130B,cidr6(ip.src, 24)вернёт2001:0000:0000:0000:0000:0000:0000:0000. - Если
ip.srcэто113.10.0.2,cidr6(ip.src, 24)вернёт113.10.0.2(без изменений).
concat
concat(: String | Bytes | Array)String | Array
Принимает список значений, разделённых запятыми. Объединяет значения аргументов в один String или массив.
Тип возвращаемого значения зависит от типа входных аргументов. Например, при объединении массивов функция вернёт массив.
Например, concat("String1", " ", "String", "2") вернёт "String1 String2".
decode_base64
decode_base64(source : String)String
Декодирует строку в кодировке Base64, указанную в source.
source должен быть полем, то есть не может быть литералом String.
Например, при следующем заголовке HTTP-запроса: client_id: MTIzYWJj, (any(decode_base64(http.request.headers["client_id"][*])[*] eq "123abc")) вернёт true.
ends_with
ends_with(source : String, substring String)Boolean
Возвращает true когда источник заканчивается заданной подстрокой. Возвращает false в противном случае. Источником не может быть литеральное значение (например, "foo").
Например, если http.request.uri.path это "/welcome.html", затем ends_with(http.request.uri.path, ".html") вернёт true.
join
join(items : Array<String>, separator String)String
Возвращает строку, полученную объединением строк в items на separator между элементами.
Если хотя бы один из аргументов равен nil, возвращаемое значение также будет nil.
Если items массив пуст, возвращаемое значение будет пустой строкой.
Если items массив содержит только один элемент, то объединение не производится и этот (единственный) элемент возвращается без изменений.
Эта функция выполняет действие, противоположное split() функцию.
Пример:
# Joins all HTTP request header names into a single string, with names separated by commas
join(http.request.headers.names, ",")has_key
has_key(map: : Map<T>, key: String)Boolean
Возвращает true, если key указанная во втором аргументе (это может быть литерал или динамическая строка), является существующим ключом в map указанному в первом аргументе; в противном случае возвращает false.
Тип данных значений в map (обозначается T) может быть любого типа.
Если хотя бы один из аргументов равен nil, возвращаемое значение также будет nil.
Примеры:
# Check if an HTTP request header exists:
has_key(http.request.headers, "x-my-header")
# Check if a request header exists based on the name of the first query argument:
has_key(http.request.headers, lower(http.request.uri.args.names[0]))has_value
has_value(collection: : Map<T> | Array<T>, value: T)Boolean
Возвращает true, если value указанное во втором аргументе (это может быть литерал или динамическое значение), найдено в collection указанному в первом аргументе; в противном случае возвращает false.
Тип данных значений в collection (обозначается T) должен соответствовать типу данных переданного value. Кроме того, T должен быть примитивным типом данных, то есть одним из следующих: Boolean, Integer, String, Bytes, или IP address.
Если хотя бы один из аргументов равен nil, возвращаемое значение также будет nil.
Примеры:
# Check if there is an HTTP request header with the exact name 'X-My-Header'
has_value(http.request.headers.names, "X-My-Header")
# Check if there is a request header with the exact name provided as the first query argument:
has_value(http.request.headers.names, http.request.uri.args.names[0])is_jwt_present
is_jwt_present(token_configuration_id: : String)Boolean
Возвращает true, если у запроса есть токен, настроенный в конфигурации токена с ID token_configuration_id.
token_configuration_id должен быть идентификатором существующего конфигурация токена.
Пример:
is_jwt_present("51231d16-01f1-48e3-93f8-91c99e81288e")is_jwt_valid
is_jwt_valid(token_configuration_id: : String)Boolean
Возвращает true, если у запроса есть действительный токен согласно конфигурации токена с ID token_configuration_id.
token_configuration_id должен быть идентификатором существующего конфигурация токена. Функция возвращает false, если токен отсутствует в запросе.
is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e")len
len(: String | Bytes | Array)Integer
Возвращает длину в байтах значения типа String или Bytes либо количество элементов в массиве.
Например, если значение http.host это "example.com", затем len(http.host) вернёт 11.
lookup_json_integer
lookup_json_integer(field : String, key String | Integer, key String | Integer optional, ...)Integer
Возвращает целочисленное значение, связанное с указанным key в field.
field должен быть строковым представлением корректного JSON-документа.
key может быть именем атрибута, номером позиции (начиная с нуля) в массиве JSON или комбинацией этих двух вариантов (в виде дополнительных параметров функции), при этом путь строится по иерархии документа JSON, чтобы получить конкретное целочисленное значение.
Примечание: эта функция работает только с обычными целыми числами. Например, она не будет работать с числами с плавающей точкой, у которых дробная часть равна нулю, такими как 42.0.
Примеры:
-
При следующем объекте JSON, содержащемся в
http.request.body.rawполе:
{ "record_id": "aed53a", "version": 2 }
Тогдаlookup_json_integer(http.request.body.raw, "version")вернёт2. -
При следующем вложенном объекте:
{ "product": { "id": 356 } }
Тогдаlookup_json_integer(http.request.body.raw, "product", "id")вернёт356. -
При следующем массиве JSON на верхнем уровне:
["first_item", -234]
Тогдаlookup_json_integer(http.request.body.raw, 1)вернёт-234. -
При следующем массиве в атрибуте объекта JSON:
{ "network_ids": [123, 456] }
Тогдаlookup_json_integer(http.request.body.raw, "network_ids", 0)вернёт123. -
При следующем массиве объектов JSON верхнего уровня:
[{ "product_id": 123 }, { "product_id": 456 }]
Тогдаlookup_json_integer(http.request.body.raw, 1, "product_id")вернёт456.
lookup_json_string
lookup_json_string(field : String, key String | Integer, key String | Integer optional, ...)String
Возвращает строковое значение, связанное с указанным key в field.
field должен быть строковым представлением корректного JSON-документа.
key может быть именем атрибута, номером позиции (начиная с нуля) в массиве JSON или комбинацией этих двух вариантов (в виде дополнительных параметров функции), при этом путь строится по иерархии документа JSON, чтобы получить конкретное значение.
Примеры:
-
При следующем объекте JSON, содержащемся в
http.request.body.rawполе:
{ "company": "cloudflare", "product": "rulesets" }
Тогдаlookup_json_string(http.request.body.raw, "company") == "cloudflare"вернётtrue. -
При следующем вложенном объекте:
{ "network": { "name": "cloudflare" } }
Тогдаlookup_json_string(http.request.body.raw, "network", "name") == "cloudflare"вернётtrue. -
При следующем массиве JSON на верхнем уровне:
["other_company", "cloudflare"]
Тогдаlookup_json_string(http.request.body.raw, 1) == "cloudflare"вернётtrue. -
При следующем массиве в атрибуте объекта JSON:
{ "networks": ["other_company", "cloudflare"] }
Тогдаlookup_json_string(http.request.body.raw, "networks", 1) == "cloudflare"вернётtrue. -
При следующем массиве объектов JSON верхнего уровня:
[{ "network": "other_company" }, { "network": "cloudflare" }]
Тогдаlookup_json_string(http.request.body.raw, 1, "network") == "cloudflare"вернётtrue.
lower
lower(: String)String
Преобразует строковое поле в нижний регистр. Преобразуются только прописные байты ASCII. Остальные байты остаются без изменений.
Например, если http.host это "WWW.cloudflare.com", затем lower(http.host) == "www.cloudflare.com" вернёт true.
regex_replace
regex_replace(source : String, regular_expression String, replacement String)String
Заменяет часть исходной строки, соответствующую регулярному выражению, строкой замены и возвращает результат. Строка замены может содержать ссылки на группы захвата регулярного выражения (например, ${1} и ${2}), до восьми ссылок на замену.
Примеры:
-
Замена по точному совпадению:
regex_replace("/foo/bar", "/bar$", "/baz") == "/foo/baz" -
Если совпадений нет, входная строка остаётся без изменений:
regex_replace("/x", "^/y$", "/mumble") == "/x" -
По умолчанию сопоставление учитывает регистр:
regex_replace("/foo", "^/FOO$", "/x") == "/foo" -
Если совпадений несколько, выполняется только одна замена (первая):
regex_replace("/a/a", "/a", "/b") == "/b/a" -
Экранирование
$в строке замены, поставив перед ним ещё один$:
regex_replace("/b", "^/b$", "/b$$") == "/b$" -
Замена с использованием групп захвата:
regex_replace("/foo/a/path", "^/foo/([^/]*)/(.*)$", "/bar/${2}/${1}") == "/bar/path/a/"
Создавайте группы захвата, заключая часть регулярного выражения в круглые скобки. Затем ссылайтесь на группу захвата с помощью ${<NUMBER>} в строке замены, где <NUMBER> это номер группы захвата.
Использовать можно только regex_replace() функцию только один раз в выражении, и её нельзя вкладывать в wildcard_replace() функцию.
remove_bytes
remove_bytes(: Bytes)Bytes
Возвращает новый массив байтов, из которого удалены все вхождения заданных байтов.
Например, если http.host это "www.cloudflare.com", затем remove_bytes(http.host, "\x2e\x77") вернёт "cloudflarecom".
remove_query_args
remove_query_args(field : String, query_param1 String, query_param2 String, ...)String
Удаляет один или несколько параметров строки запроса URI. Возвращает строку без указанных параметров.
field должен быть одним из следующих:
http.request.uri.queryraw.http.request.uri.query
field не может быть литеральным значением, например "search=foo&order=asc".
remove_query_args() функция удалит все указанные параметры (в виде query_param1, query_param2, и т.д.) , включая повторяющиеся вхождения одного и того же параметра.
Порядок незатронутых параметров запроса сохраняется.
Примеры:
// If http.request.uri.query is "order=asc&country=GB":
remove_query_args(http.request.uri.query, "country") will return "order=asc"
remove_query_args(http.request.uri.query, "order") will return "country=GB"
remove_query_args(http.request.uri.query, "search") will return "order=asc&country=GB" (unchanged)
// If http.request.uri.query is "category=Foo&order=desc&category=Bar":
remove_query_args(http.request.uri.query, "order") will return "category=Foo&category=Bar"
remove_query_args(http.request.uri.query, "category") will return "order=desc"sha256
sha256(input : String | Bytes)Bytes
Вычисляет криптографический хэш SHA-256 для input строку или массив байтов. Возвращает хеш-значение длиной 32 байта.
Используйте эту функцию, чтобы формировать подписанные заголовки запроса, проверять целостность запроса или создавать защищенные токены прямо в выражениях правил.
Примеры:
sha256("my-token")Приведённый выше пример возвращает 32-байтовый хеш, который ваш исходный сервер может проверить для аутентификации запросов.
Вы можете объединять sha256() с encode_base64() чтобы создавать подписи, закодированные в Base64:
encode_base64(sha256("my-token"))Чтобы создать подписанное значение заголовка на основе атрибутов запроса:
encode_base64(sha256(concat(to_string(ip.src), to_string(http.request.timestamp.sec), "my-secret-key")))split
split(input : String, separator String, limit Integer)Array<String>
Разбивает input строку на массив строк, разбивая исходную строку в каждом месте, где встречается separator строку. Возвращаемый массив будет содержать не более limit количество элементов.
Если вы указываете limit значение меньше фактического количества подстрок в разбиваемой строке, последний элемент возвращаемого массива будет содержать остаток строки.
separator должен быть непустым строковым литералом.
limit является обязательным и должно быть целочисленным литералом от 1 до 128.
Если input равно nil, возвращаемое значение также будет nil.
Эта функция выполняет действие, противоположное join() функцию.
Примеры:
# Split a comma-separated list of categories obtained from an HTTP request header.
# A) Consider the following HTTP request header:
x-categories: groceries,electronics,diy,auto
split(http.request.headers["x-categories"][0], ",", 64) will return ["groceries", "electronics", "diy", "auto"]
split(http.request.headers["x-categories"][0], ",", 3) will return ["groceries", "electronics", "diy,auto"]
# B) Consider the following HTTP request header:
x-categories: groceries,,electronics
split(http.request.headers["x-categories"][0], ",", 64) will return ["groceries", "", "electronics"]starts_with
starts_with(source : String, substring String)Boolean
Возвращает true когда источник начинается с заданной подстроки. Возвращает false в противном случае. Источником не может быть литеральное значение (например, "foo").
Например, если http.request.uri.path это "/blog/first-post", затем starts_with(http.request.uri.path, "/blog") вернёт true.
substring
substring(field : String | Bytes, start Integer, end Integer optional)String
Возвращает часть field значение (значение типа String или Bytes поле) из start индекса байта до (но не включая) end индекса байта. Первый байт в field имеет индекс 0. Если не указать необязательный end индекс, функция возвращает часть строки начиная с start индекса и до конца строки.
start и end индексы могут быть отрицательными целыми числами, что позволяет обращаться к символам с конца строки, а не с начала.
Примеры:
// If http.request.body.raw is "asdfghjk":
substring(http.request.body.raw, 2, 5) will return "dfg"
substring(http.request.body.raw, 2) will return "dfghjk"
substring(http.request.body.raw, -2) will return "jk"
substring(http.request.body.raw, 0, -2) will return "asdfgh"to_string
to_string(: Integer | Boolean | IP address)String
Возвращает строковое представление значения типа Integer, Boolean или IP-адрес.
Примеры:
// If cf.bot_management.score is 5:
to_string(cf.bot_management.score) will return "5"
// If ssl is true:
to_string(ssl) will return "true"upper
upper(: String)String
Преобразует строковое поле в верхний регистр. Преобразуются только строчные байты ASCII. Остальные байты остаются без изменений.
Например, если http.host является"www.cloudflare.com", затем upper(http.host) вернёт "WWW.CLOUDFLARE.COM".
url_decode
url_decode(source : String, options String optional)String
Декодирует строку в формате URL, заданную в source, как показано ниже:
-
%20и+декодируются в символ пробела (). -
%E4%BDдекодируется вä½.
source должен быть полем, то есть не может быть строковым литералом.
options параметр необязателен. Все параметры нужно указывать в виде одной строки в кавычках, например "r" или "ur". Доступны следующие варианты:
r: Применяет рекурсивное декодирование. Например,%2520будет декодирован дважды (рекурсивно) в символ пробела ().u: Включает процентное декодирование Unicode. Результат будет закодирован в UTF-8. Например,"%u2601"будет декодирована в эмодзи облака (☁️) в кодировке UTF-8 ("\xe2\x98\x81", размером 3 байта).
Примеры:
url_decode("John%20Doe") will return "John Doe"
url_decode("John+Doe") will return "John Doe"
url_decode("%2520") will return "%20"
url_decode("%2520", "r") will return " "
// Using url_decode() with the any() function:
any(url_decode(http.request.body.form.values[*])[*] contains "an xss attack")
// Using the u option to match a specific alphabet
url_decode(http.request.uri.path) matches "(?u)\p{Hangul}+"uuidv4
uuidv4(source : Bytes)String
Генерирует случайный UUIDv4 (Universally Unique Identifier, версия 4) на основе переданного аргумента (источника случайности). Чтобы получить массив случайных байтов, используйте cf.random_seed поле.
Например, uuidv4(cf.random_seed) вернёт UUIDv4, похожий на 49887398-6bcf-485f-8899-f15dbef4d1d5.
wildcard_replace
wildcard_replace(source : Bytes, wildcard_pattern Bytes, replacement Bytes, flags Bytes optional)String
Заменяет source строку, соответствующую литералу с нулём или более * подстановочные метасимволы на строку замены и возвращает результат. Строка замены может содержать ссылки на группы захвата подстановочных знаков (например, ${1} и ${2}), до восьми ссылок на замену.
Если совпадений нет, функция вернёт source без изменений.
source параметр должен быть полем (он не может быть литеральной строкой). Кроме того, весь source значение должно соответствовать wildcard_pattern параметр (он не может совпадать только с частью значения поля).
Чтобы ввести литерал * символ в wildcard_pattern параметр, его нужно экранировать с помощью \*. Кроме того, необходимо также экранировать \ с помощью \\. Два неэкранированных * символов подряд (**) в этом параметре считаются недопустимыми и не могут использоваться. Если необходимо экранирование символов, рекомендуется использовать синтаксис необработанных строк для wildcard_pattern параметр.
Чтобы ввести литерал $ символ в replacement параметр, его нужно экранировать с помощью $$.
Чтобы выполнить сопоставление с подстановочными знаками с учетом регистра, задайте flags параметр в "s".
Эта функция использует ленивое сопоставление, то есть пытается сопоставить каждый * метасимвол с максимально короткой строкой.
Использовать можно только wildcard_replace() функцию только один раз в выражении, и её нельзя вкладывать в regex_replace() функцию.
Примеры:
-
Если полный URI равен
https://apps.example.com/calendar/admin?expand=true,
wildcard_replace(http.request.full_uri, "https://*.example.com/*/*", "https://example.com/${1}/${2}/${3}")вернётhttps://example.com/apps/calendar/admin?expand=true -
Если полный URI равен
https://example.com/applications/app1,
wildcard_replace(http.request.full_uri, "/applications/*", "/apps/${1}")вернётhttps://example.com/applications/app1(значение не изменится, так как нет совпадения по полному значению URI; в этом случае следует использоватьhttp.request.uri.pathполе для сопоставления пути URI). -
Если путь URI равен
/calendar,
wildcard_replace(http.request.uri.path, "/*", "/apps/${1}")вернёт/apps/calendar. -
Если путь URI равен
/Apps/calendar,
wildcard_replace(http.request.uri.path, "/apps/*", "/${1}")вернёт/calendar(по умолчанию без учета регистра). -
Если путь URI равен
/Apps/calendar,
wildcard_replace(http.request.uri.path, "/apps/*", "/${1}", "s")вернёт/Apps/calendar(значение не изменится), так как нет точного совпадения с учетом регистра. -
Если путь URI равен
/apps/calendar/login,
wildcard_replace(http.request.uri.path, "/apps/*/login", "/${1}/login")вернёт/calendar/login.
Дополнительные примеры сопоставления с подстановочными знаками см. в Сопоставление с подстановочными знаками.
Cloudflare Network Firewall Functions
bit_slice
bit_slice(protocol : String, offset_start Number, offset_end Number)Number
Эта функция ищет совпадения в заданном срезе битов.
Смещение отсчитывается от указанного заголовка протокола. Например, чтобы проверить первый бит полезной нагрузки пакета UDP, нужно задать offset_start к 64.
Это в первую очередь предназначено для использования с ip, udp, а также tcp.
Срез (offset_end, offset_start) не может превышать 32 бита, но несколько вызовов можно объединить с помощью логических выражений.
bit_slice смещение не может превышать 2,040 бит.
Проверка HMAC
Обзор
Вы можете проверять токены с кодом аутентификации сообщений на основе хеш-функции (HMAC) в выражении правила с помощью is_timed_hmac_valid_v0() функция, сигнатура которой выглядит так:
is_timed_hmac_valid_v0(
<String literal as Key>,
<String field as MessageMAC>,
<Integer literal as ttl>,
<Integer as currentTimeStamp>,
<Optional Integer literal as lengthOfSeparator, default: 0>,
<Optional String literal as flags>
) -> <Bool as result> is_timed_hmac_valid_v0() функция имеет следующие определения параметров:
-
KeyString literal- Задаёт секретный криптографический ключ для проверки HMAC.
-
MessageMACString- Содержит конкатенацию следующих элементов HMAC:
message,separator,timestamp,mac. Определение и пример см. в MessageMAC.
- Содержит конкатенацию следующих элементов HMAC:
-
ttlInteger literal- Определяет время жизни токена HMAC в секундах. Указывает, как долго токен остаётся действительным с момента выдачи.
-
currentTimeStampInteger- Представляет метку времени UNIX (в секундах), когда Cloudflare получил запрос. Передайте
http.request.timestamp.secполе в качестве приблизительного значения для этого аргумента.
- Представляет метку времени UNIX (в секундах), когда Cloudflare получил запрос. Передайте
-
lengthOfSeparatorInteger literalнеобязательно- Задаёт длину
separatorмеждуtimestampиmessageвMessageMAC. Выражается в байтах, со значением по умолчанию0.
- Задаёт длину
-
flagsString literalнеобязательно-
Если вы задаете этому необязательному аргументу значение
's', функция ожидает значение закодированного в Base64macвMessageMACаргумент для использования набора символов, безопасного для URL, без дополнения. -
Когда вы делаете не задают значение
flagsк's', необходимо выполнить URL-кодирование значения Base64 дляmacвMessageMACаргумент.
-
Использование
is_timed_hmac_valid_v0() функция использует переданный Ключ чтобы сгенерировать код аутентификации сообщения (MAC) на основе message и timestamp областей MessageMAC. Если сгенерированный MAC совпадает с mac области MessageMAC и срок действия токена не истёк, HMAC считается действительным, и функция возвращает true.
Например, следующее выражение соответствует запросам к downloads.example.com которые не содержат действительных токенов HMAC:
http.host == "downloads.example.com"
and not is_timed_hmac_valid_v0("mysecretkey", http.request.uri, 100000, http.request.timestamp.sec, 8)Примеры правил с проверкой HMAC см. в Настройка аутентификации по токену в документации WAF.
MessageMAC
Корректный MessageMAC соответствует следующему регулярному выражению:
(.+)(.*)(\d{10})-(.{43,})и состоит из следующих выражений, разделённых скобками:
| Выражение | Описание | Пример |
|---|---|---|
(.+) |
message для проверки. |
/download/cat.jpg |
(.*) |
separator между сообщением и меткой времени, обычно это имя параметра. |
&verify= |
(\d{10}) |
10-значный UNIX timestamp когда был выпущен MAC, в секундах. |
1484063137 |
(.{43,}) |
Версия в кодировке Base64 mac. Если не задать значение urlSafe аргумент в функции проверки HMAC на 's', необходимо выполнить URL-кодирование значения Base64 для mac. Если кодирование MAC в Base64 является URL-safe, mac значение содержит 43 байта. В противном случае значение будет состоять из 44 и более байт из-за URL-кодирования. |
IaLGSmELTvlhfd0ItdN6PhhHTFhzx73EX8uy%2FcSDiIU%3D |
Сведения о генерации MessageMAC см. в Генерация HMAC-токена.
Примеры проверки HMAC
MessageMAC в одном поле
Рассмотрим случай, когда MessageMAC полностью содержится в одном поле, как в этом примере пути URI:
/download/cat.jpg?verify=1484063787-IaLGSmELTvlhfd0ItdN6PhhHTFhzx73EX8uy%2FcSDiIU%3DОбратите внимание, как URI соотносится с элементами MessageMAC:
| Элемент | Значение |
|---|---|
message |
/download/cat.jpg |
separator |
?verify= (длиной 8) |
timestamp |
1484063787 |
mac |
IaLGSmELTvlhfd0ItdN6PhhHTFhzx73EX8uy%2FcSDiIU%3D |
Если MessageMAC полностью содержится в одном поле, например http.request.uri, передайте имя поля в MessageMAC аргумент функции проверки HMAC:
is_timed_hmac_valid_v0(
"mysecretkey",
http.request.uri,
100000,
http.request.timestamp.sec,
8
)Аргумент MessageMAC в виде конкатенации
Чтобы составить MessageMAC из нескольких полей, используйте concat() функцию.
В этом примере формируется значение MessageMAC аргумент путем объединения URI запроса и двух полей заголовков:
is_timed_hmac_valid_v0(
"mysecretkey",
concat(
http.request.uri,
http.request.headers["timestamp"][0],
"-",
http.request.headers["mac"][0]),
100000,
http.request.timestamp.sec,
0
)