Examples
Real-world configuration examples for API-Fence
This page provides complete, working examples for common API-Fence use cases.
Basic Request Validation
Validate incoming requests against your OpenAPI specification:
http_filters:
- name: envoy.filters.http.dynamic_modules
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.dynamic_modules.v3.DynamicModuleFilter
dynamic_module_config:
name: api_fence
do_not_close: true
filter_name: api_fence
filter_config:
"@type": "type.googleapis.com/google.protobuf.StringValue"
value: |
{
"api_name": "users_api",
"openapi_spec_path": "/etc/envoy/users-api.yaml",
"validation": {
"validate_request": true,
"validate_response": false,
"fail_on_request_error": true
}
}
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
Behavior: Invalid requests return 400 Bad Request with validation error details.
Pass-Through Mode (Log Only)
Validate requests but don’t block invalid ones - useful for monitoring:
filter_config:
"@type": "type.googleapis.com/google.protobuf.StringValue"
value: |
{
"api_name": "monitoring_api",
"openapi_spec_path": "/etc/envoy/api.yaml",
"validation": {
"validate_request": true,
"validate_response": true,
"fail_on_request_error": false,
"fail_on_response_error": false
}
}
Behavior: All requests pass through. Validation results are recorded in:
- Envoy dynamic metadata (accessible in access logs)
- Prometheus metrics
Access Log with Validation Metadata
access_log:
- name: envoy.access_loggers.file
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
path: /dev/stdout
log_format:
text_format_source:
inline_string: |
[%START_TIME%] "%REQ(:METHOD)% %REQ(:PATH)%" %RESPONSE_CODE% request_verdict=%DYNAMIC_METADATA(api_fence:request.verdict)% request_errors=%DYNAMIC_METADATA(api_fence:request.errors)% response_verdict=%DYNAMIC_METADATA(api_fence:response.verdict)%
Full Request and Response Validation
Validate both requests and responses with thread pool:
filter_config:
"@type": "type.googleapis.com/google.protobuf.StringValue"
value: |
{
"api_name": "strict_api",
"openapi_spec_path": "/etc/envoy/strict-api.yaml",
"cache": {
"max_capacity": 500,
"ttl_seconds": 7200
},
"validation": {
"validate_request": true,
"validate_response": true,
"fail_on_request_error": true,
"fail_on_response_error": false,
"pool": {
"enabled": true,
"thread_count": 4,
"timeout_ms": 100,
"timeout_action": "allow"
}
}
}
Behavior:
- Invalid requests are blocked with
400 - Invalid responses are logged but not blocked
- Validation runs in a separate thread pool to avoid blocking Envoy workers
WAF Protection with Bundled CRS
Enable ModSecurity WAF with OWASP CoreRuleSet:
filter_config:
"@type": "type.googleapis.com/google.protobuf.StringValue"
value: |
{
"api_name": "secure_api",
"openapi_spec_path": "/etc/envoy/api.yaml",
"validation": {
"validate_request": true,
"fail_on_request_error": true
},
"modsecurity": {
"scan_request": true,
"request_action": "block",
"primary_ruleset": {
"name": "crs",
"use_bundled_crs": true,
"bundled_crs_profile": "full"
}
}
}
Behavior: Requests containing SQL injection, XSS, or other attack patterns are blocked with 403 Forbidden.
WAF in Alert Mode (Monitoring)
Monitor WAF matches without blocking:
filter_config:
"@type": "type.googleapis.com/google.protobuf.StringValue"
value: |
{
"api_name": "monitored_api",
"openapi_spec_path": "/etc/envoy/api.yaml",
"modsecurity": {
"scan_request": true,
"request_action": "alert",
"primary_ruleset": {
"name": "crs",
"use_bundled_crs": true,
"bundled_crs_profile": "minimal"
}
}
}
Behavior: WAF matches are logged but requests continue. Use this to tune rules before enforcing.
Minimal WAF (Low Latency)
Use minimal CRS profile for fastest scanning:
filter_config:
"@type": "type.googleapis.com/google.protobuf.StringValue"
value: |
{
"api_name": "fast_api",
"openapi_spec_path": "/etc/envoy/api.yaml",
"modsecurity": {
"scan_request": true,
"request_action": "block",
"pool": {
"timeout_ms": 50,
"timeout_action": "allow"
},
"primary_ruleset": {
"name": "crs_minimal",
"use_bundled_crs": true,
"bundled_crs_profile": "minimal"
}
}
}
Behavior: Only SQLi, XSS, and RCE rules are applied for minimal latency overhead.
Mock Response Generation
Generate mock responses from OpenAPI examples for testing:
filter_config:
"@type": "type.googleapis.com/google.protobuf.StringValue"
value: |
{
"api_name": "mock_api",
"openapi_spec_path": "/etc/envoy/api-with-examples.yaml",
"validation": {
"validate_request": true,
"fail_on_request_error": false
},
"mocking": {
"enabled": true,
"prefer_examples": true,
"add_mock_header": true,
"delay_ms": 50
}
}
Behavior:
- Requests are validated but not blocked
- Responses are generated from OpenAPI examples or schemas
X-Mock-Response: trueheader is added- 50ms simulated latency
Inline OpenAPI Spec
Embed the OpenAPI spec directly in configuration:
filter_config:
"@type": "type.googleapis.com/google.protobuf.StringValue"
value: |
{
"api_name": "inline_api",
"openapi_spec_inline": "openapi: 3.0.0\ninfo:\n title: Simple API\n version: 1.0.0\npaths:\n /health:\n get:\n responses:\n '200':\n description: OK",
"validation": {
"validate_request": true
}
}
Use case: Simple APIs or testing without external spec files.
Custom Security Limits
Configure strict security limits for sensitive APIs:
filter_config:
"@type": "type.googleapis.com/google.protobuf.StringValue"
value: |
{
"api_name": "sensitive_api",
"openapi_spec_path": "/etc/envoy/api.yaml",
"validation": {
"validate_request": true,
"fail_on_request_error": true
},
"security": {
"max_path_length": 1024,
"max_body_size": 1048576,
"max_json_depth": 10,
"max_array_items": 100,
"max_object_properties": 50
}
}
Behavior:
- Maximum 1KB path length (returns 414 if exceeded)
- Maximum 1MB request body (returns 413 if exceeded)
- Maximum 10 levels of JSON nesting
- Arrays limited to 100 items for validation
Complete Production Example
Full configuration with validation, WAF, and logging:
admin:
address:
socket_address:
address: 0.0.0.0
port_value: 9901
static_resources:
listeners:
- name: api_listener
address:
socket_address:
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: api_gateway
codec_type: AUTO
route_config:
name: api_routes
virtual_hosts:
- name: api_backend
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: api_cluster
http_filters:
# API-Fence: Validation + WAF
- name: envoy.filters.http.dynamic_modules
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.dynamic_modules.v3.DynamicModuleFilter
dynamic_module_config:
name: api_fence
do_not_close: true
filter_name: api_fence
filter_config:
"@type": "type.googleapis.com/google.protobuf.StringValue"
value: |
{
"api_name": "production_api",
"openapi_spec_path": "/etc/envoy/api.yaml",
"cache": {
"max_capacity": 1000,
"ttl_seconds": 3600
},
"validation": {
"validate_request": true,
"validate_response": false,
"fail_on_request_error": true,
"pool": {
"enabled": true,
"thread_count": 4,
"timeout_ms": 100
}
},
"security": {
"max_body_size": 5242880,
"max_json_depth": 20
},
"modsecurity": {
"scan_request": true,
"request_action": "block",
"pool": {
"timeout_ms": 100,
"timeout_action": "allow"
},
"primary_ruleset": {
"name": "crs",
"use_bundled_crs": true,
"bundled_crs_profile": "request"
}
}
}
# Router
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
# Access logging
access_log:
- name: envoy.access_loggers.file
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
path: /dev/stdout
log_format:
text_format_source:
inline_string: |
[%START_TIME%] "%REQ(:METHOD)% %REQ(:PATH)% %PROTOCOL%" %RESPONSE_CODE% %BYTES_RECEIVED% %BYTES_SENT% %DURATION%ms verdict=%DYNAMIC_METADATA(api_fence:request.verdict)%
clusters:
- name: api_cluster
connect_timeout: 5s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: api_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: backend-service
port_value: 8080
Testing Your Configuration
Test Valid Request
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{"name": "John Doe", "email": "john@example.com"}'
Test Invalid Request (Validation)
# Missing required field
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{"name": "John Doe"}'
# Returns 400 Bad Request
Test WAF (SQL Injection)
curl -X POST http://localhost:8080/search \
-H "Content-Type: application/json" \
-d '{"query": "1; DROP TABLE users;--"}'
# Returns 403 Forbidden (if WAF enabled with block action)
Check Metrics
curl http://localhost:9901/stats/prometheus | grep api_fence