PerimeterX Fastly Compute Rust Enforcer
Table of Contents
- Project layout
- Prerequisites
- Configuration
- PX Backend
- Module installation
- Module integration
- Enforcer API
- Logging
- Sample code
- Documentation
- Additional tools
Project layout
srcfolder contains Fastly Compute Rust Moduleexamplefolder contains a sample Fastly Compute@ Rust applicationcontrib/pxconfig.shscript to create Fastly Config store and populate with default valuescontrib/pxbackend.shscript to create and configure PX Backend host
Prerequisites
In order to compile and deploy Fastly Compute Package, Fastly CLI must be installed and configured: Compute@ services
Configuration
PXConfig holds the full enforcer configuration. HUMAN product docs describe each option’s behavior; the following matches src/pxconfig.rs in this repository.
Loading and updates
- ConfigStore (default):
PXConfig::new(config_store_name, secret_store_name)opens the Fastly ConfigStore and reads each presentPXConfigKeystring. Keys that are missing keep the RustDefaultforPXConfig. - Secret Store: when
secret_store_nameis non-empty, the enforcer opens the Fastly Secret Store and overlays these keys (samepx_*names):px_app_id,px_cookie_secret,px_auth_token,px_logger_auth_token. Secret Store values override ConfigStore/KVStore for those fields. Missing secrets are non-fatal and leave the ConfigStore/KVStore value (or default) in place. Ifsecret_store_nameis an empty string (""), Secret Store is ignored and no secrets are loaded. - KVStore (
kv_storeCargo feature): the same keys are read from (and optional updates persisted to) a Fastly KVStore.
Secret store keys
| secret name | type | notes |
|---|---|---|
| px_app_id | string | HUMAN application ID; overrides ConfigStore/KVStore when present |
| px_cookie_secret | string | Secret used to validate risk cookies; overrides ConfigStore/KVStore when present |
| px_auth_token | string | Bearer token for Risk API, activities, telemetry; overrides ConfigStore/KVStore when present |
| px_logger_auth_token | string | Secret for header-based enforcer log collection; overrides ConfigStore/KVStore when present |
Default Secret Store name: perimeterx_fastly_enforcer::DEFAULT_SECRETSTORE_NAME ("PXSecrets").
Config store keys (aligned with PXConfigKey)
| configuration key | type | default if absent from store | notes |
|---|---|---|---|
| px_app_id | string | "" |
Required, HUMAN application ID; may also be set in Secret Store |
| px_cookie_secret | string | "" |
Required, secret used to validate risk cookies; may also be set in Secret Store |
| px_auth_token | string | "" |
Required, Bearer token for Risk API, activities, telemetry; may also be set in Secret Store |
| px_debug | bool | false |
Enables verbose px_debug! logging |
| px_blocking_score | number (u8) | 100 |
Cookie v3 / Risk score blocking threshold |
| px_module_enabled | bool | false |
Master switch |
| px_module_mode | string | "monitor" |
e.g. monitor, active_blocking (PXModuleMode) |
| px_sensitive_headers | list | ["Cookie","Cookies"] |
Header names stripped from outbound risk/activity payloads |
| px_sensitive_routes | list | [] |
Path prefixes; always Risk API after valid low-risk cookie |
| px_sensitive_routes_regex | list (regex strings) | [] |
Same semantics; invalid patterns dropped at load |
| px_filter_by_route | list | [] |
Path prefixes skipped before verification |
| px_filter_by_extension | list | pxconstants::WHITELIST_EXT |
File extensions skipped before verification |
| px_filter_by_user_agent | list | [] |
User-agent values (exact match) skipped before verification |
| px_filter_by_ip | list | [] |
IPv4s (exact) or CIDR blocks (/0, /8, /16, /24, /32) skipped before verification |
| px_filter_by_http_method | list | [] |
Methods skipped before verification |
| px_custom_cookie_header | string | "x-px-cookies" |
Alternate cookie header; empty uses Cookie only |
| px_enforced_routes | list | [] |
Blocking on these paths even in monitor mode |
| px_monitored_routes | list | [] |
Monitor on these paths even in active blocking |
| px_bypass_monitor_header | string | "x-px-block" |
Header name; value 1 forces real block in monitor mode |
| px_first_party_enabled | bool | true |
First-party sensor / captcha / XHR proxy |
| px_custom_logo | string | "" |
Block page logo URL |
| px_js_ref | string | "" |
Extra block-page script URL |
| px_css_ref | string | "" |
Extra block-page stylesheet URL |
| px_ip_headers | list | [] |
Trusted client-IP headers, first match wins |
| px_log_endpoint | string | "" |
Fastly logging endpoint for activity delivery |
| px_data_enrichment_header_name | string | "" |
Request header for verified PXDE JSON; empty disables |
| px_extracted_cookies | list | [] |
Cookie names on Risk API extras (_pxac handled in code) |
| px_cors_support_enabled | bool | false |
CORS preflight / block response handling |
| px_cors_preflight_request_filter_enabled | bool | false |
Pass OPTIONS preflight without full verification when CORS enabled |
| px_graphql_enabled | bool | false |
POST GraphQL extraction on matching routes |
| px_graphql_routes | list (regex strings) | one pattern ^/graphql$ |
Invalid patterns dropped at load |
| px_sensitive_graphql_operation_names | list | [] |
Forces sensitive GraphQL handling |
| px_sensitive_graphql_operation_types | list | [] |
Operation types forcing sensitive handling |
| px_graphql_body_max_length | number (usize) | 1048576 |
Max bytes of body read for GraphQL JSON |
| px_s2s_timeout | number (u32) | 2000 |
Risk API timeout in ms (fail-open) |
| px_token_version | string | "3" |
Expected risk / mobile token version (TokenVersion) |
| px_custom_first_party_captcha_endpoint | string | "" |
Optional first-party captcha path override |
| px_custom_first_party_sensor_endpoint | string | "" |
Optional first-party sensor path override |
| px_custom_first_party_xhr_endpoint | string | "" |
Optional first-party XHR path override |
| px_user_agent_max_length | number (usize) | 8528 |
UA length cap for cookie validation |
| px_jwt_cookie_name | string | "" |
Cookie name that carries the customer JWT |
| px_jwt_cookie_user_id_field_name | string | "" |
Dot path in the JWT payload for the app user ID |
| px_jwt_cookie_additional_field_names | list | [] |
Extra JWT payload dot paths extracted from the cookie JWT |
| px_jwt_header_name | string | "" |
Header name that carries the customer JWT |
| px_jwt_header_user_id_field_name | string | "" |
Dot path in the JWT payload for the app user ID |
| px_jwt_header_additional_field_names | list | [] |
Extra JWT payload dot paths extracted from the header JWT |
| px_risk_cookie_max_length | number (usize) | 2048 |
Max raw risk cookie length |
| px_risk_cookie_min_iterations | number (usize) | 500 |
Cookie v3 PBKDF2 iteration lower bound |
| px_risk_cookie_max_iterations | number (usize) | 5000 |
Cookie v3 PBKDF2 iteration upper bound |
| px_logger_auth_token | string | "" |
Secret for header-based enforcer log collection; may also be set in Secret Store |
pxconfig.sh script could be used to populate Config store with the required values. Usage:
PerimeterX Backend
In order for PerimeterX Enforcer to communicate with PerimeterX Collector server, a special "backend" server must be added and configured in Fastly UI (or using contrib/pxbackend.sh script).
Backend parameters (replace ${APP_ID} with your PerimeterX Application ID):
human_sapi:sapi-${APP_ID}.perimeterx.nethuman_collector:collector-${APP_ID}.perimeterx.nethuman_client:client.perimeterx.nethuman_captcha:captcha.px-cdn.net
All HUMAN backends should use SSL/TLS. The SAPI and collector backend hosts can be overridden with the matching px_human_*_host and px_human_*_backend config keys.
It's recommended to set "First byte (ms)" and "Between bytes (ms)" to 1000 ms.
Installation
Include perimeterx-fastly-enforcer dependency to Cargo.toml:
Module integration
To integrate PerimeterX Rust module into existing Rust code, the following base snippet could be used (for a more advanced example see the project in "example" folder):
let mut px: PXEnforcer = new;
let px_result = px.enforce?;
if let Some = px_result ;
//... communicate with Origin server / process request and response
px.post_enforce;
Enforcer API
Initialize PXEnforcer structure. It takes the Fastly ConfigStore name and Secret Store name (defaults: perimeterx_fastly_enforcer::DEFAULT_CONFIGSTORE_NAME and perimeterx_fastly_enforcer::DEFAULT_SECRETSTORE_NAME). secret_store_name can be an empty string (""); in that case, Secret Store is ignored and no secrets are loaded.
This function takes Request and returns a Result which optionally contains "Response" (for "blocked" or "first party" requests):
At the end of request processing, the following function must be called to finalize PerimeterX enforcer code:
It is possible to access PXContext structure with various Enforcer variables via px.ctx():
// send "score" value to the Origin
req.set_header;
To set "custom_parameters" variables, the following callback function could be used
pub type PXEnrichCustomParamsFn = fn ;
where:
req: fastly::Requestconf: PXConfigparams: modifiable structure with custom_param1 .. custom_param10 fields
To set custom parameters callback function, use the following setter:
To set "sensitive request" identification function, the following callback function could be used
pub type PXIsSensitiveRequestFn = fn ;
where:
req: fastly::Requestconf: PXConfig
To set sensitive request identification function, use the following setter:
To set "additional activity" handler function, the following callback function could be used
pub type PXAdditionalActivityHandlerFn = fn ;
where:
req: fastly::Requestconf: PXConfigctx: PXContext
To set additional activity handler function, use the following setter:
To set a CORS preflight handler, the following callback function could be used
pub type PXCorsCustomPreflightHandlerFn = fn ;
where:
req: fastly::Requestconf: PXConfig
To set a custom preflight handler, use the following setter:
To set custom CORS headers for block responses, the following callback function could be used
pub type PXCorsCustomBlockResponseHeadersFn =
fn ;
where:
req: fastly::Requestconf: PXConfig
To set custom block-response CORS headers, use the following setter:
Logging
PerimeterX Rust Enforcer logs the most messages (both "info" and "debug") using Level::Info level.
In order to enable Enforcer to produce "debug" messages, set px_debug configuration value to true.
Sample code
This is the simplest example how to use PerimeterX Rust module:
use ;
use PXEnforcer;
const ORIGIN_BACKEND: &str = "origin_backend";
// send a request to the Origin server
For a complete example: example folder contains a sample project.
Documentation
To see the crate documentation, run:
Additional Tools
Testing
