Skip to main content

Auth Service

The Auth Service provides centralized Role-Based Access Control (RBAC) and permission management for the Rippler platform. It manages roles, permissions, principal bindings, and validates access requests with caching for performance.

Architecture Diagram

The following diagram illustrates the internal architecture of the Auth Service, showing the flow from API requests through role and permission management, caching layers, integration with Keycloak JWT validation, and data persistence.

Update the Architecture Diagram

To view and edit the architecture diagram:

  1. Open /docs/architecture/services/auth-service.drawio in diagrams.net or VS Code with the Draw.io extension
  2. The diagram shows the complete RBAC architecture including role management, permission checking, Redis caching, PostgreSQL persistence, and Keycloak integration
  3. After making changes, export to HTML and copy to /website/static/architecture/services/auth-service.drawio.html

Overview

Port: 18008
Technology: Spring Boot 3.2.0, Java 17, PostgreSQL, Redis
API Prefix: /api/v1

Features

  • ✅ Role management (create, list, assign permissions)
  • ✅ Permission management with resource types
  • ✅ Principal (user/service account) management
  • ✅ Role bindings with optional resource scoping
  • ✅ Permission checks with Redis caching (10 min TTL)
  • ✅ Flyway database migrations
  • ✅ Integration with Keycloak for JWT validation

Architecture

graph TD
A[Client] -->|JWT Token| B[Auth Service]
B -->|Validate| C[Keycloak JWKS]
B -->|Query| D[PostgreSQL]
B -->|Cache| E[Redis]
B -->|Return| A

Database Schema

Tables

  • roles - Role definitions (reader, contributor, maintainer, admin)
  • permissions - Permission definitions (impact:read, llm:use, etc.)
  • role_permissions - Many-to-many role-permission mapping
  • principals - User/service account records
  • principal_roles - Role bindings with optional resource patterns

Entity Relationships

principals 1---* principal_roles *---1 roles
|
|
1---*
|
permissions

API Endpoints

Role Management

Create Role

POST /api/v1/roles
Content-Type: application/json

{
"name": "service-owner",
"description": "Owner of a specific service"
}

Response: 201 Created

{
"id": 5,
"name": "service-owner",
"description": "Owner of a specific service",
"permissions": [],
"createdAt": "2024-01-15T10:00:00",
"updatedAt": "2024-01-15T10:00:00"
}

List Roles

GET /api/v1/roles

Response: 200 OK

[
{
"id": 1,
"name": "reader",
"description": "Read-only access to all services",
"permissions": [...]
}
]

Get Role by Name

GET /api/v1/roles/{name}

Permission Management

Create Permission

POST /api/v1/permissions
Content-Type: application/json

{
"name": "impact:admin",
"description": "Full admin access to impact analyzer",
"resourceType": "impact-analyzer"
}

List Permissions

GET /api/v1/permissions

Add Permission to Role

POST /api/v1/roles/{roleId}/permissions/{permissionId}

Role Bindings

Create Binding

POST /api/v1/bindings
Content-Type: application/json

{
"principalSubject": "user|alice",
"roleId": 2,
"resourcePattern": "service:impact-analyzer",
"grantedBy": "admin"
}

Resource Patterns:

  • null or omitted - Global access
  • service:impact-analyzer - Specific service
  • service:* - All services (wildcard)

List Bindings

GET /api/v1/bindings?user=user|alice

Permission Checks

Check Permission

POST /api/v1/check
Content-Type: application/json

{
"principalSubject": "user|alice",
"permissionName": "impact:read",
"resourcePattern": "service:impact-analyzer"
}

Response: 200 OK

{
"granted": true,
"reason": "Permission granted through role: contributor",
"matchedRole": "contributor",
"matchedResourcePattern": null
}

Default Roles

The service automatically creates these roles on startup:

RoleDescriptionPermissions
readerRead-only accessimpact:read, metadata:read, graph:read
contributorRead + contributeimpact:read, impact:run, metadata:read, graph:read, llm:use
maintainerMaintain servicesAll contributor permissions + impact:simulate, metadata:modify, graph:modify, notifications:send
adminFull administrative accessAll permissions

Default Permissions

Service-specific permissions included by default:

  • Impact Analyzer: impact:read, impact:run, impact:simulate
  • Notifications: notifications:send
  • Metadata: metadata:read, metadata:modify
  • LLM: llm:use
  • Dependency Graph: graph:read, graph:modify

Environment Variables

# Database
SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/rippler_auth
SPRING_DATASOURCE_USERNAME=rippler
SPRING_DATASOURCE_PASSWORD=rippler_pass

# Redis Cache
REDIS_HOST=redis
REDIS_PORT=6379

# Keycloak
KEYCLOAK_ISSUER_URI=http://keycloak:8080/realms/rippler
KEYCLOAK_JWK_SET_URI=http://keycloak:8080/realms/rippler/protocol/openid-connect/certs

# Application
SERVER_PORT=8008
SPRING_JPA_HIBERNATE_DDL_AUTO=update

Caching Strategy

Permission checks are cached in Redis for 10 minutes to improve performance.

Cache Key Format:

{principalSubject}:{permissionName}:{resourcePattern}

Cache Invalidation:

  • When roles are created or modified
  • When permissions are created or modified
  • When role bindings change

Resource Pattern Matching

The service supports flexible resource pattern matching:

  1. Global Binding (null pattern)

    • Matches everything
    • Highest privilege
  2. Exact Match (service:impact-analyzer)

    • Matches specific resource exactly
  3. Wildcard Match (service:*)

    • Matches any service
    • Prefix-based matching

Integration Example

// Check permission before allowing operation
@Autowired
private RestTemplate restTemplate;

public void runImpactAnalysis(String userId) {
PermissionCheckRequest request = PermissionCheckRequest.builder()
.principalSubject(userId)
.permissionName("impact:run")
.resourcePattern("service:impact-analyzer")
.build();

PermissionCheckResponse response = restTemplate.postForObject(
"http://auth-service:8008/api/v1/check",
request,
PermissionCheckResponse.class
);

if (!response.isGranted()) {
throw new AccessDeniedException("Permission denied");
}

// Proceed with operation
}

Health Check

GET /actuator/health

Response:

{
"status": "UP",
"components": {
"db": { "status": "UP" },
"redis": { "status": "UP" }
}
}

Development

Building

cd services/auth-service
mvn clean package

Running Locally

# With Docker Compose
docker-compose up auth-service

# Standalone
java -jar target/auth-service-1.0.0.jar

Testing

# List roles
curl http://localhost:18008/api/v1/roles

# Create binding
curl -X POST http://localhost:18008/api/v1/bindings \
-H "Content-Type: application/json" \
-d '{
"principalSubject": "user|test",
"roleId": 1,
"grantedBy": "admin"
}'

Monitoring

Key metrics available at /actuator/metrics:

  • cache.gets - Cache hit/miss ratio
  • http.server.requests - API request latency
  • jvm.memory.used - Memory usage
  • jdbc.connections.active - Database connections

Troubleshooting

Permission Check Returns False

  1. Verify user has role assigned:

    curl http://localhost:18008/api/v1/bindings?user=user|alice
  2. Check role has required permission:

    curl http://localhost:18008/api/v1/roles
  3. Verify resource pattern matching

Database Connection Issues

  1. Check PostgreSQL is running: docker-compose ps postgres
  2. Verify database exists: docker-compose exec postgres psql -U rippler -l
  3. Check connection string in environment variables

Redis Connection Issues

  1. Check Redis is running: docker-compose ps redis
  2. Test connection: docker-compose exec redis redis-cli ping
  3. Verify Redis host/port configuration

Security Considerations

  • All API endpoints should be protected with JWT validation (except health checks)
  • Role assignments should be audited (use Audit Service)
  • Cache invalidation is critical for security
  • Resource patterns should be validated to prevent injection attacks

See Also