Essential Apigee Shared Flows and Policies
Core Shared Flows You Should Build
1. Security Enforcement Shared Flow
Purpose: Centralized security validation including API key validation, OAuth token verification, and IP restrictions.
Implementation:
<!-- Security-Enforcement-SF.xml -->
<SharedFlow name="Security-Enforcement-SF">
<Step>
<Name>IP-Whitelist-Policy</Name>
</Step>
<Step>
<Name>API-Key-Validation</Name>
</Step>
<Step>
<Name>OAuth-Token-Validation</Name>
<Condition>request.header.authorization != null</Condition>
</Step>
<Step>
<Name>Rate-Limiting-Policy</Name>
</Step>
<Step>
<Name>Quota-Policy</Name>
</Step>
</SharedFlow>
Key Policies:
IP Whitelist Policy:
<!-- IP-Whitelist-Policy.xml -->
<AccessControl name="IP-Whitelist-Policy">
<IPRules noRuleMatchAction="DENY">
<MatchRule action="ALLOW">
<SourceAddress mask="24">192.168.1.0</SourceAddress>
</MatchRule>
<MatchRule action="ALLOW">
<SourceAddress mask="16">10.0.0.0</SourceAddress>
</MatchRule>
</IPRules>
</AccessControl>
API Key Validation:
<!-- API-Key-Validation.xml -->
<VerifyAPIKey name="API-Key-Validation">
<APIKey ref="request.queryparam.apikey"/>
</VerifyAPIKey>
OAuth Token Validation:
<!-- OAuth-Token-Validation.xml -->
<OAuthV2 name="OAuth-Token-Validation">
<Operation>VerifyAccessToken</Operation>
<AccessToken ref="request.header.authorization"/>
</OAuthV2>
2. Request Validation Shared Flow
Purpose: Validate request headers, parameters, and payload structure.
Implementation:
<!-- Request-Validation-SF.xml -->
<SharedFlow name="Request-Validation-SF">
<Step>
<Name>Content-Type-Validation</Name>
</Step>
<Step>
<Name>Request-Size-Check</Name>
</Step>
<Step>
<Name>JSON-Schema-Validation</Name>
<Condition>request.header.content-type = "application/json"</Condition>
</Step>
<Step>
<Name>Required-Headers-Check</Name>
</Step>
<Step>
<Name>Request-Sanitization</Name>
</Step>
</SharedFlow>
Key Policies:
Content Type Validation:
<!-- Content-Type-Validation.xml -->
<RaiseFault name="Content-Type-Validation">
<Condition>request.header.content-type != "application/json" AND request.verb != "GET"</Condition>
<FaultResponse>
<Set>
<StatusCode>400</StatusCode>
<ReasonPhrase>Bad Request</ReasonPhrase>
</Set>
<Set>
<Payload contentType="application/json">
{
"error": {
"code": "INVALID_CONTENT_TYPE",
"message": "Content-Type must be application/json"
}
}
</Payload>
</Set>
</FaultResponse>
</RaiseFault>
Request Size Check:
<!-- Request-Size-Check.xml -->
<RaiseFault name="Request-Size-Check">
<Condition>request.header.content-length > 1048576</Condition>
<FaultResponse>
<Set>
<StatusCode>413</StatusCode>
<ReasonPhrase>Payload Too Large</ReasonPhrase>
</Set>
<Set>
<Payload contentType="application/json">
{
"error": {
"code": "PAYLOAD_TOO_LARGE",
"message": "Request payload exceeds 1MB limit"
}
}
</Payload>
</Set>
</FaultResponse>
</RaiseFault>
JSON Schema Validation:
<!-- JSON-Schema-Validation.xml -->
<JSONThreatProtection name="JSON-Schema-Validation">
<ArrayElementCount>100</ArrayElementCount>
<ContainerDepth>10</ContainerDepth>
<ObjectEntryCount>50</ObjectEntryCount>
<ObjectEntryNameLength>100</ObjectEntryNameLength>
<StringValueLength>500</StringValueLength>
</JSONThreatProtection>
3. Error Handling Shared Flow
Purpose: Standardize error responses across all APIs.
Implementation:
<!-- Error-Handling-SF.xml -->
<SharedFlow name="Error-Handling-SF">
<Step>
<Name>Extract-Error-Details</Name>
</Step>
<Step>
<Name>Log-Error</Name>
</Step>
<Step>
<Name>Format-Error-Response</Name>
</Step>
<Step>
<Name>Set-CORS-Headers</Name>
</Step>
</SharedFlow>
Key Policies:
Extract Error Details:
<!-- Extract-Error-Details.xml -->
<ExtractVariables name="Extract-Error-Details">
<Source>message</Source>
<VariablePrefix>error</VariablePrefix>
<JSONPayload>
<Variable name="code">
<JSONPath>$.fault.detail.errorcode</JSONPath>
</Variable>
<Variable name="message">
<JSONPath>$.fault.faultstring</JSONPath>
</Variable>
</JSONPayload>
</ExtractVariables>
Log Error:
<!-- Log-Error.xml -->
<MessageLogging name="Log-Error">
<Syslog>
<Message>API Error - Code: {error.code}, Message: {error.message}, API: {apiproxy.name}, Client: {client_ip}</Message>
<Host>logs.company.com</Host>
<Port>514</Port>
<Protocol>TCP</Protocol>
</Syslog>
</MessageLogging>
Format Error Response:
<!-- Format-Error-Response.xml -->
<AssignMessage name="Format-Error-Response">
<Set>
<Headers>
<Header name="Content-Type">application/json</Header>
</Headers>
<Payload contentType="application/json">
{
"error": {
"code": "{error.code}",
"message": "{error.message}",
"timestamp": "{system.timestamp}",
"path": "{request.uri}",
"requestId": "{messageid}"
}
}
</Payload>
</Set>
</AssignMessage>
4. Response Enhancement Shared Flow
Purpose: Add consistent response headers, CORS support, and response transformation.
Implementation:
<!-- Response-Enhancement-SF.xml -->
<SharedFlow name="Response-Enhancement-SF">
<Step>
<Name>Add-Response-Headers</Name>
</Step>
<Step>
<Name>CORS-Policy</Name>
</Step>
<Step>
<Name>Remove-Sensitive-Headers</Name>
</Step>
<Step>
<Name>Response-Cache-Control</Name>
</Step>
</SharedFlow>
Key Policies:
Add Response Headers:
<!-- Add-Response-Headers.xml -->
<AssignMessage name="Add-Response-Headers">
<Set>
<Headers>
<Header name="X-API-Version">{apiproxy.revision}</Header>
<Header name="X-Request-ID">{messageid}</Header>
<Header name="X-Response-Time">{client.received.end.timestamp - client.received.start.timestamp}ms</Header>
<Header name="X-Rate-Limit-Remaining">{ratelimit.Quota-Policy.remaining.count}</Header>
</Headers>
</Set>
</AssignMessage>
CORS Policy:
<!-- CORS-Policy.xml -->
<AssignMessage name="CORS-Policy">
<Set>
<Headers>
<Header name="Access-Control-Allow-Origin">*</Header>
<Header name="Access-Control-Allow-Methods">GET, POST, PUT, DELETE, OPTIONS</Header>
<Header name="Access-Control-Allow-Headers">Content-Type, Authorization, X-API-Key</Header>
<Header name="Access-Control-Max-Age">3628800</Header>
</Headers>
</Set>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>
5. Logging and Analytics Shared Flow
Purpose: Centralized logging for monitoring, debugging, and analytics.
Implementation:
<!-- Logging-Analytics-SF.xml -->
<SharedFlow name="Logging-Analytics-SF">
<Step>
<Name>Extract-Request-Data</Name>
</Step>
<Step>
<Name>Log-Request-Response</Name>
</Step>
<Step>
<Name>Custom-Analytics</Name>
</Step>
<Step>
<Name>Performance-Metrics</Name>
</Step>
</SharedFlow>
Key Policies:
Extract Request Data:
<!-- Extract-Request-Data.xml -->
<ExtractVariables name="Extract-Request-Data">
<Source>request</Source>
<Header name="user-agent">
<Pattern ignoreCase="true">{user_agent}</Pattern>
</Header>
<Header name="x-forwarded-for">
<Pattern ignoreCase="true">{client_ip}</Pattern>
</Header>
<QueryParam name="version">
<Pattern ignoreCase="true">{api_version}</Pattern>
</QueryParam>
</ExtractVariables>
Log Request Response:
<!-- Log-Request-Response.xml -->
<MessageLogging name="Log-Request-Response">
<Syslog>
<Message>
{
"timestamp": "{system.timestamp}",
"apiproxy": "{apiproxy.name}",
"method": "{request.verb}",
"uri": "{request.uri}",
"client_ip": "{client_ip}",
"user_agent": "{user_agent}",
"response_code": "{response.status.code}",
"response_time": "{client.received.end.timestamp - client.received.start.timestamp}",
"request_id": "{messageid}"
}
</Message>
<Host>logs.company.com</Host>
<Port>514</Port>
<Protocol>TCP</Protocol>
</Syslog>
</MessageLogging>
6. Traffic Management Shared Flow
Purpose: Handle rate limiting, quotas, and traffic shaping.
Implementation:
<!-- Traffic-Management-SF.xml -->
<SharedFlow name="Traffic-Management-SF">
<Step>
<Name>Spike-Arrest</Name>
</Step>
<Step>
<Name>Rate-Limit-Policy</Name>
</Step>
<Step>
<Name>Quota-Policy</Name>
</Step>
<Step>
<Name>Concurrent-Rate-Limit</Name>
</Step>
</SharedFlow>
Key Policies:
Spike Arrest:
<!-- Spike-Arrest.xml -->
<SpikeArrest name="Spike-Arrest">
<Rate>100pm</Rate>
<Identifier ref="client_ip"/>
</SpikeArrest>
Rate Limit Policy:
<!-- Rate-Limit-Policy.xml -->
<Quota name="Rate-Limit-Policy">
<Allow count="1000"/>
<Interval>1</Interval>
<TimeUnit>hour</TimeUnit>
<Identifier ref="verifyapikey.API-Key-Validation.client_id"/>
</Quota>
Advanced Shared Flows
7. Circuit Breaker Shared Flow
Purpose: Implement circuit breaker pattern for backend service resilience.
<!-- Circuit-Breaker-SF.xml -->
<SharedFlow name="Circuit-Breaker-SF">
<Step>
<Name>Check-Circuit-State</Name>
</Step>
<Step>
<Name>Record-Success</Name>
<Condition>response.status.code < 400</Condition>
</Step>
<Step>
<Name>Record-Failure</Name>
<Condition>response.status.code >= 500</Condition>
</Step>
<Step>
<Name>Update-Circuit-State</Name>
</Step>
</SharedFlow>
8. Request Transformation Shared Flow
Purpose: Handle common request/response transformations.
<!-- Request-Transformation-SF.xml -->
<SharedFlow name="Request-Transformation-SF">
<Step>
<Name>JSON-to-XML</Name>
<Condition>request.header.accept = "application/xml"</Condition>
</Step>
<Step>
<Name>Add-Default-Parameters</Name>
</Step>
<Step>
<Name>Normalize-Headers</Name>
</Step>
</SharedFlow>
How to Build and Deploy Shared Flows
Step 1: Create Shared Flow Structure
# Create directory structure
mkdir shared-flows/Security-Enforcement-SF
cd shared-flows/Security-Enforcement-SF
# Create required directories
mkdir policies
mkdir sharedflowbundle
mkdir sharedflowbundle/policies
Step 2: Create Shared Flow Bundle
<!-- sharedflowbundle/Security-Enforcement-SF.xml -->
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SharedFlowBundle revision="1" name="Security-Enforcement-SF">
<Description>Centralized security enforcement</Description>
<SharedFlows>
<SharedFlow name="default">
<Step>
<Name>API-Key-Validation</Name>
</Step>
<Step>
<Name>Rate-Limiting-Policy</Name>
</Step>
</SharedFlow>
</SharedFlows>
<Policies>
<Policy>API-Key-Validation</Policy>
<Policy>Rate-Limiting-Policy</Policy>
</Policies>
</SharedFlowBundle>
Step 3: Using Apigee CLI (Recommended)
# Install Apigee CLI
npm install -g apigeecli
# Authenticate
apigeecli token gen -a
# Deploy shared flow
apigeecli sharedflows create \
-n Security-Enforcement-SF \
-p ./sharedflowbundle \
-o your-org
# Deploy to environment
apigeecli sharedflows deploy \
-n Security-Enforcement-SF \
-o your-org \
-e test
Step 4: Using in API Proxy
<!-- In your API Proxy flow -->
<Flow name="PreFlow">
<Request>
<Step>
<Name>Security-Flow-Callout</Name>
</Step>
</Request>
</Flow>
<!-- Flow Callout Policy -->
<FlowCallout name="Security-Flow-Callout">
<SharedFlowBundle>Security-Enforcement-SF</SharedFlowBundle>
</FlowCallout>
Best Practices for Shared Flows
1. Design Principles
- Single Responsibility: Each shared flow should have one clear purpose
- Parameterization: Use flow variables for configuration
- Error Handling: Always include proper error handling
- Documentation: Maintain clear documentation for each shared flow
2. Variable Management
<!-- Use consistent variable naming -->
<AssignMessage name="Set-Shared-Flow-Variables">
<Set>
<Variable name="sf.security.enabled">true</Variable>
<Variable name="sf.ratelimit.count">1000</Variable>
<Variable name="sf.ratelimit.timeunit">hour</Variable>
</Set>
</AssignMessage>
3. Conditional Execution
<!-- Make shared flows conditional -->
<Step>
<Name>Security-Enforcement</Name>
<Condition>sf.security.enabled = true</Condition>
</Step>
4. Version Management
- Use semantic versioning (v1.0.0, v1.1.0)
- Maintain backward compatibility
- Document breaking changes
- Use environment-specific configurations
5. Testing Strategy
// Example test for shared flow
describe('Security-Enforcement-SF', function() {
it('should validate API key', function() {
// Test API key validation
});
it('should enforce rate limits', function() {
// Test rate limiting
});
});
Deployment Pipeline Example
CI/CD Pipeline (GitHub Actions)
# .github/workflows/deploy-shared-flows.yml
name: Deploy Shared Flows
on:
push:
branches: [main]
paths: ['shared-flows/**']
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install Apigee CLI
run: npm install -g apigeecli
- name: Deploy to Test
run: |
apigeecli sharedflows create -o ${{ secrets.APIGEE_ORG }} -n Security-Enforcement-SF -p ./shared-flows/Security-Enforcement-SF
apigeecli sharedflows deploy -o ${{ secrets.APIGEE_ORG }} -e test -n Security-Enforcement-SF
Monitoring and Maintenance
1. Health Checks
- Monitor shared flow usage across proxies
- Track error rates and performance impact
- Set up alerts for shared flow failures
2. Performance Monitoring
<!-- Add performance tracking -->
<AssignMessage name="Track-Shared-Flow-Performance">
<Set>
<Variable name="sf.start.time">{system.timestamp}</Variable>
</Set>
</AssignMessage>
<!-- At the end of shared flow -->
<AssignMessage name="Calculate-SF-Performance">
<Set>
<Variable name="sf.execution.time">{system.timestamp - sf.start.time}</Variable>
</Set>
</AssignMessage>
3. Documentation Template
# Shared Flow: Security-Enforcement-SF
## Purpose
Centralized security validation for all API proxies.
## Features
- API key validation
- OAuth token verification
- Rate limiting
- IP whitelisting
## Usage
xml
Security-Enforcement-SF
## Configuration Variables
- `sf.security.enabled`: Enable/disable security checks
- `sf.ratelimit.count`: Rate limit threshold
## Dependencies
- OAuth provider configuration
- API product configuration
These shared flows will significantly accelerate your API development and ensure consistency across your API ecosystem. Start with the core flows (Security, Error Handling, Logging) and gradually build more specialized ones based on your specific needs.
Top comments (0)