Skip to main content

Introduction

PATH
Authorization & Rate Limiting

Grove logo

Table of Contents ​

Quickstart​

Shannon Quickstart​

See the PATH Quickstart Cheat Sheet for instructions on how to get started with a local PATH instance on Shannon.

  1. Install all prerequisites:

  2. Run make init_envoy to create all the required config files

    • .allowed-services.lua is created with the service IDs allowed by the PATH instance.
    • .envoy.yaml is created with your auth provider's domain and audience.
    • .ratelimit.yaml is created with the rate limiting configuration for the PATH instance.
    • .gateway-endpoints.yaml is created from the example file in the PADS Repository.
  3. Run make path_up to start the services with all auth and rate limiting dependencies.

MAKE SURE TO UPDATE THESE FILES

ℹī¸ After copying config files by running make init_envoy, please update local/path/envoy/.allowed-services.lua with the service IDs allowed by your PATH instance and local/path/envoy/.gateway-endpoints.yaml with your own data.

Overview​

This folder contains everything necessary for managing authorization and rate limiting in the PATH service. Specifically, this is split into two logical parts:

  1. The Envoy Proxy configuration
  2. The External Auth Server

Components​

tip

A Tiltfile is provided to run all of these services locally.

  • PATH Service: The service that handles requests after they have been authorized.
  • Envoy Proxy: A proxy server that handles incoming requests, performs auth checks, and routes authorized requests to the PATH service.
  • External Auth Server: A Go/gRPC server that evaluates whether incoming requests are authorized to access the PATH service.
  • Rate Limiter: A service that coordinates all rate limiting.
  • Redis: A key-value store used by the rate limiter to share state and coordinate rate limiting across any number of PATH instances behind the same Envoy Proxy.
  • Remote gRPC Server: A server that provides the external authorization server with data on which endpoints are authorized to use the PATH service.
    • PADS (PATH Auth Data Server) is provided as a functional implementation of the remote gRPC server that loads data from a YAML file or simple Postgres database.
    • See PATH Auth Data Server for more information.

Architecture Diagram​

Envoy Proxy​

PATH uses Envoy Proxy to handle authorization and rate limiting.

The /envoy directory houses the configuration files and settings for Envoy Proxy.

Envoy acts as a gateway, handling incoming requests, determining allowed services, performing auth checks, and routing authorized requests to the PATH service.

Envoy Configuration​

See the Envoy Config docs for a simplified explanation of the Envoy Proxy configuration files and how they work together.

Envoy HTTP Filters​

The PATH Auth Server uses the following Envoy HTTP filters to handle authorization:

  • lua: Extracts the Service ID from the subdomain of the request's host field and attaches it to the request as the target-service-id header.
  • header_mutation: Ensures the request does not have the jwt-user-id header set before it is forwarded upstream.
    • header_mutation is used only if the PATH instance has JWT auth enabled.
  • jwt_authn: Performs JWT verification and sets the jwt-user-id header.
    • jwt_authn is used only if the PATH instance has JWT auth enabled.
  • ext_authz: Performs authorization checks using the PATH Auth Server external authorization server.
  • ratelimit: Performs rate limiting checks using the Rate Limiter service.

Request Lifecycle​

Service ID Specification​

The target-service-id header is used to specify the Service ID in the request.

There are two methods for specifying this header in the request:

  1. Target Service ID Header (e.g. -H "target-service-id: anvil")
  2. URL Subdomain (e.g. http://anvil.localhost:3001/v1)

Allowed Services File​

The file local/path/envoy/.allowed-services.lua defines the mapping of service IDs to the service IDs used by the PATH service.

All service IDs (and optional service aliases) used by the PATH service must be defined in this file.

.allowed-services.lua format
return {
-- 1. Shannon Service IDs
["anvil"] = "anvil", -- Anvil (Authoritative ID)

-- 2. Morse Service IDs
["F000"] = "F000", -- Pocket (Authoritative ID)
["pocket"] = "F000", -- Pocket (Alias)
}

Target Service ID Header​

The service ID (or a configured alias) may be specified in the target-service-id header.

Example request:
curl http://localhost:3001/v1 \
-X POST \
-H "Content-Type: application/json" \
-H "target-service-id: anvil" \
-H "endpoint-id: endpoint_3_no_auth" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "eth_blockNumber" }'

URL Subdomain​

The service ID (or a configured alias) may be specified in the URL subdomain.

eg. host = "anvil.path.grove.city" -> Header: "target-service-id: anvil"

Example request:
curl http://anvil.localhost:3001/v1 \
-X POST \
-H "Content-Type: application/json" \
-H "endpoint-id: endpoint_3_no_auth" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "eth_blockNumber" }'

Specifying the Gateway Endpoint ID​

The Auth Server may extract the Gateway Endpoint ID from the request in one of two ways:

  1. URL Path Endpoint ID Extractor
  2. Header Endpoint ID Extractor

This is determined by the ENDPOINT_ID_EXTRACTOR environment variable in the auth_server/.env file. One of:

  • url_path (default)
  • header
warning

Requests are rejected if either of the following are true:

  • The <GATEWAY_ENDPOINT_ID> is missing
  • ID is not present in the External Auth Server's Gateway Endpoint Store
info

Regardless of which extractor is used, the Gateway Endpoint ID will always be set in the endpoint-id header if the request is forwarded to the PATH Service.

URL Path Endpoint ID Extractor​

When using the url_path extractor, the Gateway Endpoint ID must be specified in the URL path.

https://<SERVICE_NAME>.<PATH_DOMAIN>/v1/<GATEWAY_ENDPOINT_ID>

For example, if the SERVICE_NAME is eth and the GATEWAY_ENDPOINT_ID is a1b2c3d4:

curl http://anvil.localhost:3001/v1/endpoint_3_no_auth \
-X POST \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "eth_blockNumber" }'

Header Endpoint ID Extractor​

When using the header extractor, the Gateway Endpoint ID must be specified in the endpoint-id header.

-H "endpoint-id: <GATEWAY_ENDPOINT_ID>"

For example, if the endpoint-id header is set to a1b2c3d4:

curl http://anvil.localhost:3001/v1 \
-X POST \
-H "Content-Type: application/json" \
-H "endpoint-id: endpoint_3_no_auth" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "eth_blockNumber" }'
Example curl requests

A variety of example cURL requests to the PATH service can be found in the test_requests.mk file.

info

endpoint_3_no_auth is the endpoint from the example .gateway-endpoints.yaml file that requires no authorization.

See the Gateway Endpoint YAML File section for more information on the GatewayEndpoint data structure.


Gateway Endpoint Authorization​

The External Auth Server evaluates whether incoming requests are authorized to access the PATH service based on the AuthType field of the GatewayEndpoint proto struct.

Three authorization types are supported:

  1. JSON Web Token (JWT) Authorization
  2. API Key Authorization
  3. No Authorization

JSON Web Token (JWT) Authorization​

For GatewayEndpoints with the AuthType field set to JWT_AUTH, a valid JWT issued by the auth provider specified in the envoy.yaml file is required to access the PATH service.

tip

The make init_envoy command will prompt you about whether you wish to use JWT authorization.

If you do wish to use it, you will be asked to enter your auth provider's domain and audience.

Auth0 is an example of a JWT issuer that can be used with PATH.

Their docs page on JWTs gives a good overview of the JWT format and how to issue JWTs to your users:

Example Request Header:

-H "Authorization: Bearer <JWT>"

The jwt_authn filter will verify the JWT and, if valid, set the jwt-user-id header from the sub claim of the JWT. An invalid JWT will result in an error.

The External Auth Server will use the jwt-user-id header to make an authorization decision; if the GatewayEndpoint's Auth.AuthorizedUsers field contains the jwt-user-id value, the request will be authorized.

Example auth provider user ID header:

jwt-user-id: auth0|a12b3c4d5e6f7g8h9
info

For more information, see the Envoy JWT Authn Docs

API Key Authorization​

For GatewayEndpoints with the AuthType field set to API_KEY_AUTH, a static API key is required to access the PATH service.

Example Request Header:

-H "Authorization: <API_KEY>"

The External Auth Server will use the authorization header to make an authorization decision; if the GatewayEndpoint's Auth.ApiKey field matches the API_KEY value, the request will be authorized.

No Authorization​

For GatewayEndpoints with the AuthType field set to NO_AUTH, no authorization is required to access the PATH service.

All requests for GatewayEndpoints with the AuthType field set to NO_AUTH will be authorized by the External Auth Server.

External Auth Server​

info

See PATH PADS Repository for more information on authorization service provided by Grove for PATH support.

The envoy/auth_server directory contains the External Auth Server called by the Envoy ext_authz filter. It evaluates whether incoming requests are authorized to access the PATH service.

This server communicates with a Remote gRPC Server to populate its in-memory Gateway Endpoint Store, which provides data on which endpoints are authorized to use the PATH service.

External Auth Server Sequence Diagram​

External Auth Server Configuration​

The external authorization server loads its config from the auth_server_config section of PATH's .config.yaml file. For the local Tilt stack, this file is located at local/path/config/.config.yaml.

.config.yaml auth_server_config example:

auth_server_config:
grpc_host_port: path-auth-data-server:50051
grpc_use_insecure_credentials: true
endpoint_id_extractor_type: url_path

See the PATH Configuration section for more information on the .config.yaml file.

For more information on external authorization using Envoy Proxy, see the Envoy documentation:

Gateway Endpoints gRPC Service​

Both the External Auth Server and the Remote gRPC Server use the gRPC service and types defined in the gateway_endpoint.proto file.

This service defines two main methods for populating the External Auth Server's Gateway Endpoint Store:

service GatewayEndpoints {
// GetInitialData requests the initial set of GatewayEndpoints from the remote gRPC server.
rpc GetInitialData(InitialDataRequest) returns (InitialDataResponse);

// StreamUpdates listens for updates from the remote gRPC server and streams them to the client.
rpc StreamUpdates(UpdatesRequest) returns (stream Update);
}

Remote gRPC Auth Server​

The Remote gRPC Server is responsible for providing the External Auth Server with data on which endpoints are authorized to use the PATH service.

info

The implementation of the remote gRPC server is up to the Gateway operator but PADS is provided as a functional implementation for most users.

PATH Auth Data Server​

The PADS repo provides a functioning implementation of the remote gRPC server.

This service is available as a Docker image and may be configured to load data from a YAML file or using a simple Postgres database that adheres to the provided minimal schema.

Docker Image Registry:

ghcr.io/buildwithgrove/path-auth-data-server:latest

This Docker image is loaded by default in the Tiltfile file at the root of the PATH repo.

If the Gateway Operator wishes to implement a custom remote gRPC server, see the Implementing a Custom Remote gRPC Server section.

Gateway Endpoint YAML File​

PADS loads data from the Gateway Endpoints YAML file specified by the YAML_FILEPATH environment variable.\

info

An example gateway-endpoints.yaml file may be seen in the PADS repo.

The yaml file below provides an example for a particular gateway operator where:

  • endpoint_1_static_key is authorized with a static API Key
  • endpoint_2_jwt is authorized using an auth-provider issued JWT for two users
  • endpoint_3_no_auth requires no authorization and has a rate limit set
endpoints:
# 1. Example of a gateway endpoint using API Key Authorization
endpoint_1_static_key:
auth:
api_key: "api_key_1"

# 2. Example of a gateway endpoint using JWT Authorization
endpoint_2_jwt:
auth:
jwt_authorized_users:
- "auth0|user_1"
- "auth0|user_2"

# 3. Example of a gateway endpoint with no authorization and rate limiting set
endpoint_3_no_auth:
rate_limiting:
throughput_limit: 30
capacity_limit: 100000
capacity_limit_period: "CAPACITY_LIMIT_PERIOD_MONTHLY"
tip

The PADS repo also provides a YAML schema for the gateway-endpoints.yaml file, which can be used to validate the configuration.

Implementing a Custom Remote gRPC Server​

If the Gateway operator wishes to implement a custom remote gRPC server, the implementation must import the Go github.com/buildwithgrove/path/envoy/auth_server/proto package, which is autogenerated from the gateway_endpoint.proto file.

The custom implementation must use the methods defined in the GatewayEndpoints service:

  • FetchAuthDataSync
  • StreamAuthDataUpdates
tip

If you wish to implement your own custom database driver, forking the PADS repo is the easiest way to get started, though any gRPC server implementation that adheres to the gateway_endpoint.proto service definition should suffice.

Rate Limiter​

Rate Limit Configuration​

  1. The External Auth Server sets the rl-endpoint-id and rl-throughput headers if the GatewayEndpoint for the request should be rate limited.

  2. Envoy Proxy is configured to forward the rl-endpoint-id and rl-throughput headers to the rate limiter service as descriptors.

    .envoy.yaml

    rate_limits:
    - actions:
    - request_headers:
    header_name: "rl-endpoint-id"
    descriptor_key: "rl-endpoint-id"
    - request_headers:
    header_name: "rl-throughput"
    descriptor_key: "rl-throughput"
  3. Rate limiting is configured through the .ratelimit.yaml file.

    .ratelimit.yaml

    domain: rl
    descriptors:
    - key: rl-endpoint-id
    descriptors:
    - key: rl-throughput
    value: "PLAN_FREE"
    rate_limit:
    unit: second
    requests_per_unit: 30
info

The default throughput limit is 30 requests per second for GatewayEndpoints with the PLAN_FREE plan type based on the rl-endpoint-id and rl-throughput descriptors.

The rate limiting configuration may be configured to suit the needs of the Gateway Operator in the .ratelimit.yaml file.

Documentation and Examples​

As Envoy's rate limiting configuration is fairly complex, this blog article provides a good overview of the configuration options:

For more advanced configuration options, refer to the Envoy documentation: