INTEGRITY Dokumentace

Funkce

Cloudflare Rules language nabízí funkce pro úpravu a ověřování hodnot ve výrazu:

Transformační funkce

Rules language podporuje několik funkcí, které transformují hodnoty získané z HTTP požadavků. Typickým případem použití transformačních funkcí je převod řetězce znaků na velká nebo malá písmena, protože vyhodnocování řetězců standardně rozlišuje velká a malá písmena.

Například lower() převádí všechny velké znaky v řetězci na malá písmena.

V následujícím výrazu lower() funkce transformuje http.host hodnoty na malá písmena, aby odpovídaly cílové hodnotě "www.cloudflare.com":

lower(http.host) == "www.cloudflare.com"

Transformační funkce, které nepřijímají pole jako typ argumentu, vyžadují [*] indexovou notaci. Viz Pole s dalšími informacemi.

Rules language podporuje tyto transformační funkce:

any

any(Array<Boolean>): Boolean

Vrátí true pokud porovnávací operátor v argumentu vrátí true pro any hodnot v poli argumentů. Vrací false v opačném případě.

Příklad:

any(url_decode(http.request.body.form.values[*])[*] contains "an xss attack")

all

all(Array<Boolean>): Boolean

Vrátí true pokud porovnávací operátor v argumentu vrátí true pro all hodnoty v poli argumentů. Vrací false v opačném případě.

Příklad:

all(http.request.headers["content-type"][*] == "application/json")

encode_base64

encode_base64(input String | Bytes [, flags String]): String

Zakóduje input řetězec nebo pole bajtů do formátu Base64.

flags parametr je volitelný. Můžete zadat jeden nebo více příznaků jako jeden řetězec. K dispozici jsou tyto příznaky:

Výstup ve výchozím nastavení používá standardní kódování Base64 bez paddingu.

Příklady:

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="

Můžete kombinovat encode_base64() s dalšími funkcemi k vytvoření podepsaných hlaviček požadavku:

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

Vrátí síťovou adresu odpovídající adrese IP (IPv4 nebo IPv6) na základě zadaného počtu síťových bitů pro IPv4 a IPv6 (které určují příslušné masky sítě).

address parametr musí být pole, tedy nemůže jít o literální řetězec.

ipv4_network_bits hodnota musí být mezi 1 a 32 a ipv6_network_bits hodnota musí být mezi 1 a 128.

Příklady:

cidr6

cidr6(address IP address, ipv6_network_bits Integer): IP address

Vrátí síťovou adresu IPv6 odpovídající adrese IPv6 na základě zadaného počtu síťových bitů (které určují masku sítě). Pokud v prvním parametru zadáte adresu IPv4, vrátí se beze změny.

address parametr musí být pole, tedy nemůže jít o literální řetězec.

ipv6_network_bits hodnota musí být mezi 1 a 128.

Tato funkce je ekvivalentní: cidr(<address>, 32, <ipv6_network_bits>).

Příklady:

concat

concat(String | Bytes | Array): String | Array

Přijímá seznam hodnot oddělených čárkou. Zřetězí hodnoty argumentů do jediné hodnoty typu String nebo pole.

Návratový typ závisí na typu vstupních argumentů. Pokud například spojujete pole, funkce vrátí pole.

Například concat("String1", " ", "String", "2") vrátí "String1 String2".

decode_base64

decode_base64(source String): String

Dekóduje řetězec zakódovaný pomocí Base64 zadaný v source.

source musí být pole, tedy nemůže jít o doslovný řetězec String.

Například s následující hlavičkou HTTP požadavku: client_id: MTIzYWJj, (any(decode_base64(http.request.headers["client_id"][*])[*] eq "123abc")) by vrátilo true.

ends_with

ends_with(source String, substring String): Boolean

Vrátí true pokud zdroj končí daným podřetězcem. Vrací false v opačném případě. Zdroj nemůže být literální hodnota (například "foo").

Například pokud http.request.uri.path je "/welcome.html", poté ends_with(http.request.uri.path, ".html") vrátí true.

join

join(items Array<String>, separator String): String

Vrátí řetězec, který je spojením řetězců v items hodnotou separator mezi jednotlivými položkami.

Pokud je kterýkoli z argumentů nil, vrácená hodnota bude také nil.
Pokud items pole je prázdné, vrácenou hodnotou bude prázdný řetězec.
Pokud items pole obsahuje jedinou položku, ke zřetězení nedojde a tato (jediná) položka bude vrácena beze změny.

Tato funkce je opakem split() .

Příklad:

# 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

Vrátí true, pokud key zadaný v druhém argumentu, kterým může být literál nebo dynamický řetězec, existuje jako klíč v map zadaný jako první argument, jinak vrátí false.

Datový typ hodnot v map (označeno T) může být libovolného typu.

Pokud je kterýkoli z argumentů nil, vrácená hodnota bude také nil.

Příklady:

# 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

Vrátí true, pokud value zadaná v druhém argumentu, kterou může být literál nebo dynamická hodnota, se nachází v collection zadaný jako první argument, jinak vrátí false.

Datový typ hodnot v collection (označeno T) musí odpovídat datovému typu poskytnutého value. Kromě toho T musí být primitivní datový typ, tedy musí jít o jeden z těchto typů: Boolean, Integer, String, Bytes, nebo IP address.

Pokud je kterýkoli z argumentů nil, vrácená hodnota bude také nil.

Příklady:

# 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

Vrátí true, pokud má požadavek token nakonfigurovaný v konfiguraci tokenu s ID token_configuration_id.

token_configuration_id musí být ID existujícího konfigurace tokenu.

Příklad:

is_jwt_present("51231d16-01f1-48e3-93f8-91c99e81288e")

is_jwt_valid

is_jwt_valid(token_configuration_id: String): Boolean

Vrátí true, pokud má požadavek platný token podle konfigurace tokenu s ID token_configuration_id.

token_configuration_id musí být ID existujícího konfigurace tokenu. Pokud v požadavku chybí token, funkce vrátí false.

is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e")

len

len(String | Bytes | Array): Integer

Vrátí délku hodnoty typu String nebo Bytes v bajtech, případně počet prvků v poli.

Pokud je například hodnota http.host je "example.com", poté len(http.host) vrátí 11.

lookup_json_integer

lookup_json_integer(field String, key String | Integer, key String | Integer optional, ...): Integer

Vrátí celočíselnou hodnotu přiřazenou k zadanému key v field.

field musí být řetězcová reprezentace platného dokumentu JSON.

key může být název atributu, číslo pozice v poli JSON počítané od nuly, nebo kombinace obou možností (jako další parametry funkce), přičemž se postupuje podle hierarchie dokumentu JSON až k požadované celočíselné hodnotě.

Poznámka: Tato funkce funguje pouze pro celá čísla. Nebude fungovat například u desetinných čísel s nulovou desetinnou částí, jako je 42.0.

Příklady:

lookup_json_string

lookup_json_string(field String, key String | Integer, key String | Integer optional, ...): String

Vrátí řetězcovou hodnotu přiřazenou k zadanému key v field.

field musí být řetězcová reprezentace platného dokumentu JSON.

key může být název atributu, číslo pozice v poli JSON počítané od nuly, nebo kombinace obou možností (jako další parametry funkce), přičemž se postupuje podle hierarchie dokumentu JSON až k požadované hodnotě.

Příklady:

lower

lower(String): String

Převede textové pole na malá písmena. Převádějí se pouze velká písmena ASCII, ostatní bajty zůstávají beze změny.

Například pokud http.host je "WWW.cloudflare.com", poté lower(http.host) == "www.cloudflare.com" vrátí true.

regex_replace

regex_replace(source String, regular_expression String, replacement String): String

Nahradí část zdrojového řetězce odpovídající regulárnímu výrazu náhradním řetězcem a vrátí výsledek. Náhradní řetězec může obsahovat odkazy na zachytávací skupiny regulárního výrazu (například ${1} a ${2}), až osm náhradních odkazů.

Příklady:

Zachytávací skupiny vytvoříte tak, že část regulárního výrazu umístíte do závorek. Na zachytávací skupinu se pak odkážete pomocí ${<NUMBER>} v náhradním řetězci, kde <NUMBER> je číslo zachytávací skupiny.

Použít můžete pouze regex_replace() funkci ve výrazu pouze jednou a nelze ji vnořit do wildcard_replace() .

remove_bytes

remove_bytes(Bytes): Bytes

Vrátí nové pole bajtů, ze kterého jsou odstraněny všechny výskyty zadaných bajtů.

Například pokud http.host je "www.cloudflare.com", poté remove_bytes(http.host, "\x2e\x77") vrátí "cloudflarecom".

remove_query_args

remove_query_args(field String, query_param1 String, query_param2 String, ...): String

Odebere jeden nebo více parametrů z řetězce dotazu (query string) v URI. Vrátí řetězec bez zadaných parametrů.

field musí být jedno z následujících:

field nemůže být literál, například "search=foo&order=asc".

remove_query_args() funkce odstraní všechny zadané parametry (jako query_param1, query_param2, atd.) , včetně opakovaného výskytu stejného parametru.

Pořadí nedotčených parametrů dotazu zůstane zachováno.

Příklady:

// 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

Vypočítá kryptografický hash SHA-256 pro input řetězec nebo pole bajtů. Vrací 32bajtovou hodnotu hash.

Tuto funkci použijte k generování podepsaných hlaviček požadavku, ověření integrity požadavku nebo k vytváření zabezpečených tokenů přímo ve výrazech pravidel.

Příklady:

sha256("my-token")

Výše uvedený příklad vrací 32bajtový hash, který může váš origin server ověřit pro autentizaci požadavků.

Můžete kombinovat sha256() hodnotou encode_base64() k vytvoření podpisů kódovaných ve formátu Base64:

encode_base64(sha256("my-token"))

Chcete-li vytvořit podepsanou hodnotu hlavičky z atributů požadavku:

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>

Rozdělí input řetězec na pole řetězců rozdělením původního řetězce v každém výskytu separator řetězec. Vrácené pole bude obsahovat nejvýše limit počet prvků.

Pokud zadáte limit hodnotu nižší, než je skutečný počet podřetězců v rozděleném řetězci, poslední prvek vráceného pole bude obsahovat zbytek řetězce.

separator musí být neprázdný doslovný řetězec.

limit je povinné a musí jít o celé číslo v rozmezí 1 až 128 zapsané doslovně.

Pokud input je nil, vrácená hodnota bude také nil.

Tato funkce je opakem join() .

Příklady:

# 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

Vrátí true pokud zdroj začíná daným podřetězcem. Vrací false v opačném případě. Zdroj nemůže být literální hodnota (například "foo").

Například pokud http.request.uri.path je "/blog/first-post", poté starts_with(http.request.uri.path, "/blog") vrátí true.

substring

substring(field String | Bytes, start Integer, end Integer optional): String

Vrátí část field hodnota (hodnota typu String nebo Bytes pole) z start bajtový index až po (ale nikoli včetně) end bajtový index. První bajt v field má index 0. Pokud neuvedete volitelný end index vrátí funkce část řetězce od start index do konce řetězce.

start a end indexy mohou být záporná celá čísla, což umožňuje přistupovat ke znakům od konce řetězce místo od začátku.

Příklady:

// 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

Vrátí řetězcovou reprezentaci hodnoty typu Integer, Boolean nebo IP address.

Příklady:

// 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

Převede textové pole na velká písmena. Převádějí se pouze malá písmena ASCII, ostatní bajty zůstávají beze změny.

Například pokud http.host je"www.cloudflare.com", poté upper(http.host) vrátí "WWW.CLOUDFLARE.COM".

url_decode

url_decode(source String, options String optional): String

Dekóduje řetězec ve formátu URL definovaný v source, jak je uvedeno níže:

source musí být pole, tedy nemůže jít o doslovný řetězec.

options parametr je volitelný. Veškeré možnosti musíte zadat jako jeden řetězec v uvozovkách, například "r" nebo "ur". Dostupné možnosti jsou následující:

Příklady:

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

Vygeneruje náhodné UUIDv4 (Universally Unique Identifier, verze 4) na základě zadaného argumentu (zdroje náhodnosti). Chcete-li získat pole náhodných bajtů, použijte cf.random_seed .

Například uuidv4(cf.random_seed) vrátí UUIDv4 podobné 49887398-6bcf-485f-8899-f15dbef4d1d5.

wildcard_replace

wildcard_replace(source Bytes, wildcard_pattern Bytes, replacement Bytes, flags Bytes optional): String

Nahradí source řetězec, který odpovídá literálu s nulou nebo více * zástupné metaznaky náhradním řetězcem a vrátí výsledek. Náhradní řetězec může obsahovat odkazy na zachytávací skupiny zástupných znaků (například ${1} a ${2}), až osm náhradních odkazů.

Pokud nedojde ke shodě, funkce vrátí source beze změny.

source parametr musí být pole (nemůže jít o literální řetězec). Navíc celý source hodnota musí odpovídat wildcard_pattern parametr (nemůže odpovídat pouze části hodnoty pole).

Chcete-li zadat literál * znak v wildcard_pattern parametru ho musíte escapovat pomocí \*. Kromě toho musíte také escapovat \ pomocí \\. Dva neescapované * znaků po sobě (**) v tomto parametru jsou považovány za neplatné a nelze je použít. Pokud potřebujete provést escapování znaků, doporučujeme použít syntaxe surových řetězců pro wildcard_pattern .

Chcete-li zadat literál $ znak v replacement parametru ho musíte escapovat pomocí $$.

Chcete-li provést porovnávání zástupných znaků s rozlišením velkých a malých písmen, nastavte flags parametr na "s".

Tato funkce používá líné porovnávání (lazy matching), to znamená, že se snaží porovnat každý * metaznak co nejkratším možným řetězcem.

Použít můžete pouze wildcard_replace() funkci ve výrazu pouze jednou a nelze ji vnořit do regex_replace() .

Příklady:

Další příklady porovnávání se zástupnými znaky najdete v Porovnávání se zástupnými znaky.

Cloudflare Network Firewall Functions

bit_slice

bit_slice(protocol String, offset_start Number, offset_end Number): Number

Tato funkce hledá shody v zadaném slice bitů.

Posun začíná na zadané hlavičce protokolu. Pokud chcete například porovnávat první bit datové části paketu UDP, musíte nastavit offset_start na 64.

Toto je určeno především pro použití s ip, udp, a tcp.

Slice (offset_end, offset_start) nesmí být delší než 32 bitů, ale více volání lze spojit pomocí logických výrazů.

bit_slice posun nesmí překročit 2,040 bitů.

Ověřování HMAC

Přehled

Tokeny HMAC (hash-based message authentication code) můžete ve výrazu pravidla ověřit pomocí is_timed_hmac_valid_v0() funkce, která má tuto signaturu:

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() má tyto definice parametrů:

Použití

is_timed_hmac_valid_v0() funkce používá zadaný Key ke generování kódu pro autentizaci zprávy (MAC) z message a timestamp oblastí MessageMAC. Pokud vygenerovaný MAC odpovídá mac oblasti MessageMAC a platnost tokenu ještě nevypršela, je HMAC platný a funkce vrátí true.

Následující výraz například odpovídá požadavkům na downloads.example.com , které neobsahují platné tokeny HMAC:

http.host == "downloads.example.com"
and not is_timed_hmac_valid_v0("mysecretkey", http.request.uri, 100000, http.request.timestamp.sec, 8)

Příklady pravidel využívajících ověření HMAC najdete v Konfigurace ověřování pomocí tokenu v dokumentaci WAF.

MessageMAC

Platný MessageMAC odpovídá tomuto regulárnímu výrazu:

(.+)(.*)(\d{10})-(.{43,})

a skládá se z těchto výrazů oddělených závorkami:

Výraz Popis Příklad
(.+) message k ověření. /download/cat.jpg
(.*) separator mezi zprávou a časovým razítkem, obvykle název parametru. &verify=
(\d{10}) 10místné časové razítko UNIX timestamp kdy byl MAC vydán, vyjádřený v sekundách. 1484063137
(.{43,}) Verze kódovaná v Base64 pro mac. Pokud nenastavíte hodnotu urlSafe argument ve funkci pro ověřování HMAC na 's', musíte URL kódovat hodnotu Base64 pro mac. Pokud je kódování Base64 MAC bezpečné pro URL, mac hodnota obsahuje 43 bajtů. V opačném případě bude mít hodnota 44 bajtů nebo více, a to kvůli kódování URL. IaLGSmELTvlhfd0ItdN6PhhHTFhzx73EX8uy%2FcSDiIU%3D

Podrobnosti o generování MessageMAC najdete v Generování tokenu HMAC.

Příklady ověření HMAC

MessageMAC v jednom poli

Uvažujme případ, kdy je MessageMAC celý obsažen v jediném poli, jako v této ukázkové cestě URI:

/download/cat.jpg?verify=1484063787-IaLGSmELTvlhfd0ItdN6PhhHTFhzx73EX8uy%2FcSDiIU%3D

Všimněte si, jak se URI mapuje na jednotlivé prvky MessageMAC:

Element Hodnota
message /download/cat.jpg
separator ?verify= (s délkou 8)
timestamp 1484063787
mac IaLGSmELTvlhfd0ItdN6PhhHTFhzx73EX8uy%2FcSDiIU%3D

Pokud je MessageMAC celý obsažen v jediném poli, jako je například http.request.uri, předejte název pole do MessageMAC argument funkce pro ověřování HMAC:

is_timed_hmac_valid_v0(
  "mysecretkey",
  http.request.uri,
  100000,
  http.request.timestamp.sec,
  8
)

Zřetězený argument MessageMAC

Chcete-li sestavit MessageMAC z více než jednoho pole, použijte concat() .

Tento příklad sestavuje hodnotu MessageMAC argument zřetězením URI požadavku a dvou polí hlaviček:

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
)