# ![image](https://storage.googleapis.com/perimeterx-logos/primary_logo_red_cropped.png)
# [PerimeterX](http://www.perimeterx.com) Fastly Compute@Edge Rust Enforcer
[![Crates.io][crates-badge]][crates-url]
[![License Badge]](./LICENSE)
[crates-badge]: https://img.shields.io/crates/v/perimeterx-fastly-enforcer.svg?style=for-the-badge&logo=rust
[crates-url]: https://crates.io/crates/perimeterx-fastly-enforcer
[License Badge]: https://img.shields.io/crates/l/perimeterx-fastly-enforcer?style=for-the-badge
## Table of Contents
- [Project layout](#projectlayout)
- [Prerequisites](#prerequisites)
- [Configuration](#configuration)
- [PX Backend](#backend)
- [Module installation](#installation)
- [Module integration](#integration)
- [Enforcer API](#api)
- [Logging](#logging)
- [Sample code](#sample)
## Project layout
- `src` folder contains Fastly Compute@Edge Rust Module
- `example` folder contains a sample Fastly Compute@Edge Rust application
- `contrib/pxconfig.sh` script to create Fastly Config store and populate with default values
- `contrib/pxbackend.sh` script to create and configure PX Backend host
## Prerequisites
In order to compile and deploy Fastly Compute@Edge Package, Fastly CLI must be installed and configured: Compute@Edge services
## Configuration
Module configuration is done using Compute@Edge Config store.
Please refer PerimeterX documentation for individual configuration option description.
This is the list of Config store (PXConfig) items and datatypes:
| configuration name | type | | default |
|--------------------|------|--|---------|
| px_app_id | string | required | - |
| px_cookie_secret | string | required | - |
| px_auth_token | string | required | - |
| px_module_enabled | bool | optional | false |
| px_module_mode | "active_blocking", "monitor" | optional | "monitor" |
| px_debug | bool | optional | false |
| px_blocking_score | number | optional | 100 |
| px_sensitive_headers | list | optional | [] |
| px_sensitive_routes | list | optional | [] |
| px_filter_by_route | list | optional | [] |
| px_filter_by_user_agent | list | optional | [] |
| px_filter_by_ip | list | optional | [] |
| px_filter_by_http_method | list | optional | [] |
| px_custom_cookie_header | string | optional | "" |
| px_enforced_routes | list | optional | [] |
| px_monitored_routes | list | optional | [] |
| px_bypass_monitor_header | string | optional | "" |
| px_first_party_enabled | bool | optional | true |
| px_custom_logo | string | optional | "" |
| px_js_ref | string | optional | "" |
| px_css_ref | string | optional | "" |
| px_ip_headers | list | optional | [] |
| log_endpoint | string | optional | "" |
| px_graphql_enabled | bool | optional | false |
| px_graphql_routes | list | optional | ["^/graphql$"] |
| px_sensitive_graphql_operation_names | list | optional | [] |
| px_sensitive_graphql_operation_types | list | optional | [] |
`pxconfig.sh` script could be used to populate Config store with the required values. Usage:
```bash
Required options:
-s, --service-id=SERVICE_ID specify a service to deploy the Config store
-v, --version=VER specify a service version
-a, --appid=APPID specify an appid
-c, --cookie_secret=SECRET specify a cookie_secret
-t, --auth_token=TOKEN specify an auth_token
```
## 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):
- Name: `PX_BACKEND_${APP_ID}`
- Hostname: `sapi-${APP_ID}.perimeterx.net`
- Override host: (empty value)
- Use SSL/TLS: Yes
## Installation
Include `perimeterx-fastly-enforcer` dependency to `Cargo.toml`:
```bash
cargo add perimeterx-fastly-enforcer
```
## 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):
```rust
let mut px: PXEnforcer = PXEnforcer::new(perimeterx_fastly_enforcer::DEFAULT_CONFIGSTORE_NAME);
let px_result = px.enforce(&mut req)?;
if let Some(r) = px_result {
return Ok(r);
};
//... communicate with Origin server / process request and response
px.post_enforce(&response);
```
## Enforcer API
Initialize PXEnforcer structure, it takes a name of Fastly "ConfigStore" (it's possible to use the default name: `perimeterx_fastly_enforcer::DEFAULT_CONFIGSTORE_NAME`)
```rust
pub fn new(config_store_name: &str) -> Self
```
This function takes Request and returns a Result which optionally contains "Response" (for "blocked" or "first party" requests):
```rust
pub fn enforce(&mut self, req: &mut Request) -> Result