This repository demonstrates a production-grade implementation of external authorization (AuthZ) using Envoy Proxy, with a complete microservices architecture showcasing access control and authentication.
This implementation is based on Google's Zanzibar paper, which describes a globally distributed authorization system used by Google to handle authorization for services like Google Drive, Calendar, and Cloud Platform. The paper can be found here: Google Zanzibar Paper
The Zanzibar architecture consists of several key components:
┌─────────────────────────────────────────────────────────────────┐
│ Client Service │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Envoy Proxy │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ AuthZ Service │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Storage Layer │
└─────────────────────────────────────────────────────────────────┘
-
Relation Tuples
- Objects are identified by their namespace and ID
- Relations define how objects are connected
- Example:
document:readme#owner@user:alice
-
Consistency Model
- Strong consistency for writes
- Strong consistency for reads (this is different from the original Zanzibar Implementation )
- Global snapshot reads
-
Performance Characteristics
- 95th percentile latency < 10ms
- 99th percentile latency < 100ms
- Handles millions of QPS
-
Namespace-based Authorization
namespace:object#relation@user └─────────┴─────┴────────┴────┘ │ │ │ │ │ │ │ └─ Subject (user or group) │ │ └─ Relation (permission) │ └─ Object ID └─ Namespace -
Relation-based Access Control
┌─────────────────────────────────────────────────────────────┐ │ Access Control Graph │ │ │ │ document:readme ────── owner ──────► user:alice │ │ │ │ │ └─────── reader ───────► group:engineering │ │ │ └─────────────────────────────────────────────────────────────┘ -
Consistency Model
┌─────────────────────────────────────────────────────────────┐ │ Consistency Model │ │ │ │ Write ──────► Strong Consistency ──────► Global State │ │ │ │ Read ──────► Stong Consistency ──────► Global State │ │ │ └─────────────────────────────────────────────────────────────┘
The system consists of the following components:
- Front Envoy: Acts as the API Gateway/Edge Proxy
- AuthZ Service: Handles authorization decisions
- Demo Service: Example backend service with protected endpoints
- Redis: For caching and session management
- PostgreSQL: Persistent storage for authorization data
-
Front Envoy (Port 18000)
- Main entry point for all API requests
- Implements external authorization filter
- Routes traffic to appropriate services
- Admin interface available on port 8001
-
AuthZ Service (Port 8080, 8081)
- Implements authorization logic
- Provides ACL management API
- Integrates with Redis for caching
- Uses PostgreSQL for persistent storage
-
Demo Service (Port 8002)
- Example protected service
- Demonstrates integration with the authorization system
- Provides sample protected endpoints
-
Supporting Infrastructure
- Redis (Port 6379): For caching and session management
- PostgreSQL (Port 5432): For persistent storage
- Docker
- Docker Compose
- Java Development Kit (JDK) 11 or higher (for development)
-
Clone the repository:
git clone <repository-url> cd envoy-authz
-
Start the services:
docker-compose up -d
-
Verify the setup:
curl localhost:18000/contact/
The system supports both coarse-grained and fine-grained authorization. Here's how to set up different authorization levels:
Create roles and assign them to users:
# Create a new role
curl -X POST http://localhost:8081/acl/roles \
-H "Content-Type: application/json" \
-d '{
"name": "admin",
"permissions": ["read", "write", "delete"]
}'
# Assign role to user
curl -X POST http://localhost:8081/acl/users \
-H "Content-Type: application/json" \
-d '{
"userId": "user123",
"roles": ["admin"]
}'Set up specific permissions for resources:
# Create a resource with specific permissions
curl -X POST http://localhost:8081/acl/resources \
-H "Content-Type: application/json" \
-d '{
"namespace": "contact",
"resourceId": "contact123",
"permissions": {
"user123": ["read", "write"],
"user456": ["read"]
}
}'Verify authorization rules:
# Test coarse-grained access
curl -X GET http://localhost:18000/contact/ \
-H "X-User-ID: user123"
# Test fine-grained access
curl -X GET http://localhost:18000/contact/contact123 \
-H "X-User-ID: user456"-
Role-based Access Control (RBAC)
- Define roles (admin, user, guest)
- Assign permissions to roles
- Assign roles to users
-
Attribute-based Access Control (ABAC)
- Define attributes (department, location)
- Create policies based on attributes
- Apply policies to resources
-
Resource-based Access Control
- Define resource types
- Set permissions per resource
- Apply inheritance rules
Example RBAC setup:
curl -X POST http://localhost:8081/acl/roles \
-H "Content-Type: application/json" \
-d '{
"name": "user",
"permissions": ["read", "write"]
}'
# Assign roles to users
curl -X POST http://localhost:8081/acl/users \
-H "Content-Type: application/json" \
-d '{
"userId": "admin1",
"roles": ["admin"]
}'
curl -X POST http://localhost:8081/acl/users \
-H "Content-Type: application/json" \
-d '{
"userId": "user1",
"roles": ["user"]
}'For local development:
-
Install dependencies:
./demo.sh setup
-
Run tests:
./demo.sh test
The main Envoy configuration is in front-envoy.yaml. Key features:
- External authorization filter configuration
- Route configurations for different services
- Security settings and timeouts
Authorization rules can be configured through:
- ACL API endpoints
- Direct database configuration
- Environment-specific configuration files
-
Contact API (
/contact/)- Requires authentication
- Supports CRUD operations
- Namespace: "contact"
-
ACL API (
/acl/)- Administrative endpoints
- Manages access control rules
- Namespace: "acl"
The repository includes several test suites:
- Unit tests
- Integration tests
- Performance tests
Run tests using:
./demo.sh test- Redis caching improves authorization decision performance
- Envoy's connection pooling handles high concurrency
- Configurable timeouts and circuit breakers
- All services run in isolated containers
- PostgreSQL credentials should be changed in production
- Redis security should be configured for production use
- TLS should be enabled in production deployments
- Fork the repository
- Create a feature branch
- Submit a pull request
See License.md for details.
Common issues and solutions:
-
Connection refused:
- Ensure all containers are running
- Check port mappings
-
Authorization failures:
- Verify Redis connection
- Check PostgreSQL connectivity
- Review authorization logs
For issues and support, please create an issue in the repository.