DEV Community

Mahmoud Sayed
Mahmoud Sayed

Posted on

Essential Apigee Shared Flows and Policies

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

API Key Validation:

<!-- API-Key-Validation.xml -->
<VerifyAPIKey name="API-Key-Validation">
  <APIKey ref="request.queryparam.apikey"/>
</VerifyAPIKey>
Enter fullscreen mode Exit fullscreen mode

OAuth Token Validation:

<!-- OAuth-Token-Validation.xml -->
<OAuthV2 name="OAuth-Token-Validation">
  <Operation>VerifyAccessToken</Operation>
  <AccessToken ref="request.header.authorization"/>
</OAuthV2>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

Key Policies:

Spike Arrest:

<!-- Spike-Arrest.xml -->
<SpikeArrest name="Spike-Arrest">
  <Rate>100pm</Rate>
  <Identifier ref="client_ip"/>
</SpikeArrest>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

3. Conditional Execution

<!-- Make shared flows conditional -->
<Step>
  <Name>Security-Enforcement</Name>
  <Condition>sf.security.enabled = true</Condition>
</Step>
Enter fullscreen mode Exit fullscreen mode

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
  });
});
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode


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
Enter fullscreen mode Exit fullscreen mode

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)