Skip to content

Jans Lock Design

Michael Schwartz edited this page Aug 22, 2025 · 1 revision

Requirements Document

Introduction

The Janssen Lock Server is a Java Weld application that serves as the centralized control plane for domains using Cedar to secure distributed applications. It connects ephemeral Cedarlings to the enterprise infrastructure, providing policy distribution, configuration management, and audit capabilities. The Lock Server acts as a Policy Retrieval Point (PRP) in the distributed authorization architecture, serving policies authored in external tools like Agama Lab Policy Designer.

Requirements

Requirement 1

User Story: As a system administrator, I want to deploy Lock Server either standalone or integrated with Jans Auth Server, so that I can choose the deployment model that best fits my infrastructure.

Acceptance Criteria

  1. WHEN deploying as standalone THEN the system SHALL provide independent web server capabilities
  2. WHEN deploying with Jans Auth Server THEN the system SHALL integrate seamlessly with existing OAuth/OpenID services
  3. WHEN either deployment option is chosen THEN the system SHALL maintain full Lock Server functionality

Requirement 2

User Story: As a Cedarling client, I want to retrieve the current Policy Store from Lock Server, so that I can evaluate authorization policies with up-to-date data.

Acceptance Criteria

  1. WHEN a Cedarling requests Policy Store, if authorized, THEN the Lock Server SHALL return the latest version of the requested policy store.
  2. Lock Server SHALL forbid any Policy Store request not authorized by an embedded Cedarling PDP.
  3. The Policy Store syntax shall align with the latest Cedar policy store standard.

Requirement 3

User Story: As a Cedarling client, I want to send authorization audit data to Lock Server via OAuth-protected endpoints, so that centralized logging and compliance requirements are met.

Acceptance Criteria

  1. WHEN Cedarling sends audit data THEN Lock Server SHALL use the Cedarling to authorize the request
  2. WHEN audit data is received THEN Lock Server SHALL store it in lock_server_audit.log or configured audit storage
  3. WHEN OAuth access token is invalid THEN Lock Server SHALL reject the audit request with appropriate error
  4. WHEN audit data is malformed THEN Lock Server SHALL log error and return validation failure

Requirement 4

User Story: As a system administrator, I want to manage Policy Store configurations through CLI/TUI interfaces, so that I can configure policy distribution and monitor Lock Server operations.

Acceptance Criteria

  1. WHEN using Jans CLI THEN administrator SHALL be able to configure Policy Store sources and endpoints
  2. WHEN using Jans CLI THEN administrator SHALL be able to view current Policy Store configurations
  3. WHEN using Jans CLI THEN administrator SHALL be able to update Policy Store distribution settings
  4. WHEN using Jans CLI THEN administrator SHALL be able to monitor policy distribution status
  5. WHEN Policy Store configuration is modified via CLI THEN changes SHALL be reflected in Lock Server immediately
  6. WHEN using CLI THEN administrator SHALL be able to view connected Cedarling clients and their status

Requirement 5

User Story: As a system administrator, I want to view authorization metrics and Cedarling client activity, so that I can monitor system usage and troubleshoot issues.

Acceptance Criteria

  1. WHEN accessing metrics THEN system SHALL display total authorization requests per day
  2. WHEN viewing client details THEN system SHALL show authorization activity for specific Cedarling instances
  3. WHEN metrics are requested THEN system SHALL provide real-time data from current operations

Requirement 6

User Story: As a system administrator, I want comprehensive logging capabilities, so that I can audit system activity and troubleshoot issues.

Acceptance Criteria

  1. WHEN Lock Server operates THEN it SHALL generate lock_server_config.log for configuration events
  2. WHEN authorization events occur THEN system SHALL log to lock_server_audit.log (with RDBMS option)
  3. WHEN logs are written THEN they SHALL include timestamp, event type, and relevant context data

Requirement 7

User Story: As a Lock Server, I want to use the Cedarling for authorization decisions, so that I only show policy store data to authorized entities.

Acceptance Criteria

  1. WHEN client requests specific policy store THEN Lock Server SHALL use Cedarling to authorize access with policy store ID as resource
  2. WHEN making authorization request THEN Lock Server SHALL specify appropriate action (GET, POST) based on the operation
  3. WHEN Cedarling denies authorization THEN Lock Server SHALL reject the client request with appropriate error
  4. WHEN Cedarling allows authorization THEN Lock Server SHALL proceed with the requested operation
  5. The Lock Server SHALL use its own embedded Cedarling instance with appropriate policies

Requirement 8

User Story: As a Lock Server, I want to provide well-known configuration endpoints, so that Cedarlings can discover my capabilities and endpoints.

Acceptance Criteria

  1. WHEN Cedarling requests /.well-known/lock-master-configuration THEN Lock Server SHALL return configuration metadata
  2. WHEN configuration is requested THEN Lock Server SHALL include configuration and policy store endpoints
  3. WHEN configuration is requested THEN Lock Server SHALL include supported features and capabilities
  4. WHEN configuration changes THEN Lock Server SHALL update the well-known endpoint immediately

Lock Server Design Document

Overview

The Janssen Lock Server is a Java Weld application that serves as the centralized Policy Retrieval Point (PRP) in a distributed Cedar-based authorization architecture. It connects ephemeral Cedarling instances to enterprise infrastructure by providing policy distribution, audit log collection, and OAuth-protected endpoints for secure communication.

The Lock Server acts as the bridge between policy authoring tools (like Agama Lab Policy Designer) and distributed Cedarling instances, ensuring consistent policy enforcement across the network while maintaining high availability and security.

Architecture

High-Level Architecture

graph TB
    subgraph "Policy Authoring"
        AL[Agama Lab Policy Designer]
        GH[GitHub Repository]
    end
    
    subgraph "Lock Server Infrastructure"
        LS[Lock Server]
        CL[Embedded Cedarling]
        PS[Policy Store Cache]
        AL_LOG[Audit Logs]
    end
    
    subgraph "OAuth Infrastructure"
        AS[Jans Auth Server]
        DCR[Dynamic Client Registration]
    end
    
    subgraph "Cedarling Clients"
        C1[Cedarling Client 1]
        C2[Cedarling Client 2]
        CN[Cedarling Client N]
    end
    
    AL --> GH
    GH --> PS
    
    C1 --> DCR
    C2 --> DCR
    CN --> DCR
    DCR --> AS
    
    C1 -.->|OAuth Token| LS
    C2 -.->|OAuth Token| LS
    CN -.->|OAuth Token| LS
    
    LS --> CL
    LS --> PS
    LS --> AL_LOG
        
    C1 -.->|Audit Data| LS
    C2 -.->|Audit Data| LS
    CN -.->|Audit Data| LS
Loading

Component Architecture

graph TB
    subgraph "Lock Server Application"
        subgraph "Web Layer"
            REST[REST Endpoints]
            WK[Well-Known Endpoints]
        end
        
        subgraph "Security Layer"
            OAuth[OAuth Token Validation]
            CL_AUTH[Cedarling Authorization]
        end
        
        subgraph "Business Logic Layer"
            PSM[Policy Store Manager]
            AUD[Audit Manager]
            CLIENT_MGR[Client Manager]
        end
        
        subgraph "Data Layer"
            PS_CACHE[Policy Store Cache]
            LOG_STORE[Log Storage]
            CLIENT_REG[Client Registry]
        end
        
        subgraph "Integration Layer"
            CL_EMB[Embedded Cedarling]
            EXT_PS[External Policy Sources]
        end
    end
    
    REST --> OAuth
    OAuth --> CL_AUTH
    CL_AUTH --> CL_EMB
    
    REST --> PSM
    REST --> AUD
    
    PSM --> PS_CACHE
    PSM --> EXT_PS
    AUD --> LOG_STORE
    CLIENT_MGR --> CLIENT_REG
Loading

Components and Interfaces

1. REST API Endpoints

Policy Store Endpoints

  • GET /policy-store/{id} - Retrieve specific policy store
  • GET /policy-stores - List available policy stores
  • GET /.well-known/lock-master-configuration - Lock Server metadata

Audit Endpoints

  • POST /audit/logs - Submit audit logs from Cedarlings
  • POST /audit/health - Submit health status
  • POST /audit/telemetry - Submit telemetry data

2. OAuth Security Layer

@Component
public class OAuthSecurityFilter {
    
    @Autowired
    private TokenValidator tokenValidator;
    
    @Autowired
    private CedarlingAuthorizationService cedarlingAuth;
    
    public boolean validateRequest(HttpServletRequest request, String policyStoreId) {
        // Extract OAuth token from Authorization header
        String token = extractBearerToken(request);
        
        // Validate token signature and claims
        TokenValidationResult validation = tokenValidator.validate(token);
        if (!validation.isValid()) {
            return false;
        }
        
        // Use embedded Cedarling for authorization
        AuthorizationRequest authzRequest = AuthorizationRequest.builder()
            .tokens(Map.of("access_token", token))
            .action("Jans::Action::\"GET\"")
            .resource(createPolicyStoreResource(policyStoreId))
            .context(createRequestContext(request))
            .build();
            
        return cedarlingAuth.authorize(authzRequest).isAllowed();
    }
}

3. Policy Store Manager

@Service
public class PolicyStoreManager {
    
    @Autowired
    private PolicyStoreCache cache;
    
    @Autowired
    private ExternalPolicySourceClient externalClient;
    
    public PolicyStore getPolicyStore(String storeId) {
        // Check cache first
        PolicyStore cached = cache.get(storeId);
        if (cached != null && !cached.isExpired()) {
            return cached;
        }
        
        // Fetch from external source (e.g., GitHub, S3)
        PolicyStore fresh = externalClient.fetchPolicyStore(storeId);
        
        // Update cache
        cache.put(storeId, fresh);        
        return fresh;
    }
}

5. Embedded Cedarling Integration

@Component
public class CedarlingAuthorizationService {
    
    private final Cedarling cedarling;
    
    @PostConstruct
    public void initializeCedarling() {
        BootstrapConfig config = BootstrapConfig.builder()
            .applicationName("Lock Server")
            .policyStoreUri(lockServerPolicyStoreUri)
            .userAuthz(true)
            .workloadAuthz(true)
            .logType(LogType.MEMORY)
            .build();
            
        this.cedarling = new Cedarling(config);
    }
    
    public AuthorizeResult authorize(AuthorizationRequest request) {
        return cedarling.authorize(request);
    }
}

Data Models

Policy Store Structure

{
  "cedar_version": "v4.0.0",
  "policy_stores": {
    "store_id": {
      "name": "Policy Store Name",
      "description": "Description",
      "policies": {
        "policy_id": {
          "description": "Policy description",
          "creation_date": "2024-01-01T00:00:00Z",
          "policy_content": {
            "encoding": "none",
            "content_type": "cedar",
            "body": "permit(principal, action, resource) when { ... };"
          }
        }
      },
      "schema": {
        "encoding": "none",
        "content_type": "cedar",
        "body": "namespace Jans { ... }"
      },
      "trusted_issuers": {
        "issuer_id": {
          "name": "Issuer Name",
          "openid_configuration_endpoint": "https://...",
          "token_metadata": {
            "access_tokens": {
              "entity_type_name": "Jans::Access_token",
              "workload_id": "client_id",
              "principal_mapping": ["Jans::Workload"]
            }
          }
        }
      }
    }
  }
}

Lock Server Configuration

{
  "issuer": "https://lock-server.example.com",
  "policy_store_endpoint": "https://lock-server.example.com/policy-store",
  "audit_endpoint": "https://lock-server.example.com/audit",
  "jwks_uri": "https://idp.example.com/.well-known/jwks",
  "scopes_supported": [
    "https://jans.io/oauth/lock/log.write",
    "https://jans.io/oauth/lock/health.write",
    "https://jans.io/oauth/lock/telemetry.write"
  ]
}

Audit Log Entry

@Entity
public class AuditLogEntry {
    @Id
    private String id;
    
    private String clientId;
    private String requestId;
    private Instant timestamp;
    private String logKind; // Decision, System, Metric
    private String pdpId;
    private String policyStoreId;
    private String decision;
    private String principal;
    private String action;
    private String resource;
    private String diagnostics;
    private Long decisionTimeMs;
    
    // getters/setters
}

Error Handling

Error Response Format

{
  "error": "invalid_token",
  "error_description": "The access token is invalid or expired",
  "error_uri": "https://docs.jans.io/lock-server/errors#invalid_token",
  "timestamp": "2024-01-01T12:00:00Z",
  "request_id": "req-123456"
}

Error Categories

  1. Authentication Errors

    • invalid_token - OAuth token is invalid or expired
    • insufficient_scope - Token lacks required scopes
    • token_validation_failed - Token signature validation failed
  2. Authorization Errors

    • access_denied - Cedarling denied access to resource
    • policy_store_not_found - Requested policy store doesn't exist
    • unauthorized_policy_store - Client not authorized for policy store
  3. System Errors

    • policy_store_unavailable - External policy source unavailable
    • cedarling_error - Embedded Cedarling authorization failed
    • internal_server_error - Unexpected system error

Exception Handling Strategy

@ControllerAdvice
public class LockServerExceptionHandler {
    
    @ExceptionHandler(InvalidTokenException.class)
    public ResponseEntity<ErrorResponse> handleInvalidToken(InvalidTokenException e) {
        ErrorResponse error = ErrorResponse.builder()
            .error("invalid_token")
            .errorDescription(e.getMessage())
            .timestamp(Instant.now())
            .build();
        return ResponseEntity.status(401).body(error);
    }
    
    @ExceptionHandler(CedarlingAuthorizationException.class)
    public ResponseEntity<ErrorResponse> handleAuthorizationDenied(CedarlingAuthorizationException e) {
        ErrorResponse error = ErrorResponse.builder()
            .error("access_denied")
            .errorDescription("Access denied by authorization policy")
            .timestamp(Instant.now())
            .build();
        return ResponseEntity.status(403).body(error);
    }
}

Testing Strategy

Unit Testing

  1. OAuth Token Validation

    • Valid token scenarios
    • Expired token handling
    • Invalid signature detection
    • Missing scope validation
  2. Cedarling Authorization

    • Policy store access authorization
    • Different software roles and permissions
    • Context-based authorization decisions
  3. Policy Store Management

    • Cache hit/miss scenarios
    • External source failures
    • Policy store updates and notifications

Integration Testing

  1. End-to-End Flows

    • Cedarling client registration with SSA
    • Policy store retrieval with OAuth token
    • Audit log submission
  2. Security Testing

    • Token tampering attempts
    • Unauthorized policy store access

Performance Testing

  1. Load Testing

    • Concurrent policy store requests
    • Audit log ingestion rates
  2. Stress Testing

    • Policy store cache under load
    • Cedarling authorization performance

Deployment Considerations

Standalone Deployment

# docker-compose.yml
version: '3.8'
services:
  lock-server:
    image: janssenproject/lock-server:latest
    ports:
      - "8080:8080"
    environment:
      - LOCK_SERVER_POLICY_STORE_SOURCE=github
      - LOCK_SERVER_GITHUB_REPO=org/policy-repo
      - LOCK_SERVER_OAUTH_ISSUER=https://auth.example.com
    volumes:
      - ./config:/opt/jans/lock-server/config
      - ./logs:/opt/jans/lock-server/logs

Integrated with Jans Auth Server

# Jans Auth Server configuration
services:
  jans-auth:
    image: janssenproject/jans-auth-server:latest
    environment:
      - JANS_LOCK_SERVER_ENABLED=true
      - JANS_LOCK_SERVER_POLICY_STORE_SOURCE=local
    volumes:
      - ./lock-server-config:/opt/jans/jetty/jans-auth/custom/lock-server

High Availability Setup

# HA deployment with load balancer
services:
  nginx:
    image: nginx:alpine
    ports:
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      
  lock-server-1:
    image: janssenproject/lock-server:latest
    environment:
      - LOCK_SERVER_INSTANCE_ID=lock-server-1
      
  lock-server-2:
    image: janssenproject/lock-server:latest
    environment:
      - LOCK_SERVER_INSTANCE_ID=lock-server-2
      
  redis:
    image: redis:alpine
    # Shared cache for policy stores

This design provides a comprehensive foundation for implementing the Lock Server while maintaining security, scalability, and integration with the broader Janssen ecosystem.

Implementation Plan

  • 1. Set up project structure and core dependencies

    • Create Maven project structure for Lock Server with Java Weld CDI framework
    • Configure dependencies for JAX-RS, Jackson JSON processing, and OAuth token validation
    • Set up logging framework (SLF4J with Logback) and basic configuration files
    • Requirements: 1.1, 1.2, 1.3
  • 2. Implement OAuth token validation infrastructure

    • 2.1 Create OAuth token validation service

      • Implement JWT signature validation using JWKS from Auth Server
      • Create token claims extraction and validation logic
      • Write unit tests for token validation scenarios (valid, expired, invalid signature)
      • Requirements: 7.1, 7.2, 7.3
    • 2.2 Implement OAuth security filter

      • Create JAX-RS filter to intercept requests and validate Bearer tokens
      • Implement token scope validation for Lock Server endpoints
      • Write integration tests for OAuth-protected endpoint access
      • Requirements: 2.3, 4.1, 7.4
  • 3. Integrate embedded Cedarling for authorization

    • 3.1 Create Cedarling authorization service

      • Initialize embedded Cedarling instance with Lock Server policies
      • Implement authorization request builder for policy store access decisions
      • Create service to map OAuth token claims to Cedarling entities
      • Requirements: 10.1, 10.2, 10.3
    • 3.2 Implement authorization decision logic

      • Create authorization wrapper that uses Cedarling for policy store access control
      • Implement resource mapping (policy store ID as resource, GET/POST as action)
      • Write unit tests for authorization decisions with different software roles
      • Requirements: 10.4, 10.5, 10.6
  • 4. Implement policy store management

    • 4.1 Create policy store cache and retrieval service

      • Implement in-memory cache for policy stores with TTL expiration
      • Create service to fetch policy stores from external sources (GitHub, file system)
      • Implement policy store validation and parsing logic
      • Requirements: 2.1, 2.2, 5.2
    • 4.2 Create policy store REST endpoints

      • Implement GET /policy-store/{id} endpoint with OAuth protection
      • Create GET /policy-stores endpoint to list available policy stores
      • Add proper error handling for policy store not found and unauthorized access
      • Requirements: 2.1, 2.3, 2.6
  • 5. Implement Server Sent Events (SSE) functionality

    • 5.1 Create SSE manager and subscription service

      • Implement SSE emitter management with client registration and cleanup
      • Create subscription endpoint GET /events/policy-updates with OAuth validation
      • Implement client connection lifecycle management (connect, disconnect, timeout)
      • Requirements: 3.1, 3.4
    • 5.2 Implement policy update notifications

      • Create event notification system for policy store updates
      • Implement SSE event broadcasting to subscribed Cedarling clients
      • Add error handling for failed SSE message delivery
      • Requirements: 3.2, 3.3
  • 6. Implement audit log collection

    • 6.1 Create audit log data models and storage

      • Define audit log entry entity with all required fields (request_id, timestamp, decision, etc.)
      • Implement audit log storage service (file-based and optional RDBMS)
      • Create audit log validation and parsing logic
      • Requirements: 4.2, 8.2
    • 6.2 Create audit endpoints

      • Implement POST /audit/logs endpoint for Cedarling decision logs
      • Create POST /audit/health and POST /audit/telemetry endpoints
      • Add OAuth token validation and proper error responses for audit endpoints
      • Requirements: 4.1, 4.3, 4.4
  • 7. Implement configuration and well-known endpoints

    • 7.1 Create Lock Server configuration service

      • Implement configuration management for Lock Server metadata
      • Create service to generate Lock Server capability information
      • Implement configuration update detection and SSE notification
      • Requirements: 11.1, 11.4
    • 7.2 Create well-known configuration endpoint

      • Implement GET /.well-known/lock-master-configuration endpoint
      • Return Lock Server metadata including endpoints, scopes, and capabilities
      • Add proper content-type headers and caching directives
      • Requirements: 11.1, 11.2, 11.3
  • 8. Implement CLI/TUI management interfaces

    • 8.1 Create Jans CLI commands for Lock Server

      • Implement CLI commands for policy store configuration management
      • Create commands to view connected Cedarling clients and their status
      • Add CLI commands for monitoring authorization metrics and audit logs
      • Requirements: 5.1, 5.6, 6.1
    • 8.2 Implement Lock Server status and monitoring

      • Create service to track connected Cedarling clients and their activity
      • Implement authorization metrics collection (requests per day, success/failure rates)
      • Add CLI commands to search and view Cedarling client authorization activity
      • Requirements: 5.2, 5.3, 5.4, 5.5, 6.2, 6.3
  • 9. Implement comprehensive logging system

    • 9.1 Create Lock Server logging infrastructure

      • Configure structured logging for lock_server_config.log with configuration events
      • Implement JWT processing logging to lock_server_jwt_status.log
      • Add contextual logging with timestamps, event types, and request correlation
      • Requirements: 8.1, 8.3, 8.4
    • 9.2 Implement audit log management

      • Create audit log rotation and retention policies
      • Implement optional RDBMS storage for audit logs with proper indexing
      • Add audit log search and filtering capabilities for CLI access
      • Requirements: 8.2
  • 10. Implement trusted issuer configuration

    • 10.1 Create trusted issuer management service

      • Implement service to manage trusted identity provider configurations
      • Create validation for OpenID configuration endpoints and token metadata
      • Implement token metadata schema validation including claim mapping and parsers
      • Requirements: 9.1, 9.2, 9.4
    • 10.2 Integrate trusted issuers with policy stores

      • Implement policy store generation with trusted issuer configurations
      • Create service to validate and update token metadata schemas
      • Add support for regex and JSON parsers in claim mapping configuration
      • Requirements: 9.3, 9.5
  • 11. Implement deployment configurations

    • 11.1 Create standalone deployment configuration

      • Configure Docker containerization with proper environment variables
      • Implement configuration file management for standalone deployment
      • Create health check endpoints for container orchestration
      • Requirements: 1.1
    • 11.2 Create Jans Auth Server integration

      • Implement integration configuration for embedded Lock Server deployment
      • Create shared configuration management with Jans Auth Server
      • Add proper service discovery and endpoint registration
      • Requirements: 1.1
  • 12. Implement comprehensive testing suite

    • 12.1 Create unit tests for core services

      • Write unit tests for OAuth token validation with various token scenarios
      • Create unit tests for Cedarling authorization with different policy configurations
      • Implement unit tests for policy store management and caching logic
      • Requirements: All requirements validation
    • 12.2 Create integration tests

      • Implement end-to-end tests for Cedarling client registration and policy retrieval
      • Create integration tests for SSE subscription and policy update notifications
      • Write integration tests for audit log submission and storage
      • Requirements: All requirements validation
  • 13. Wire together all components and create main application

    • 13.1 Create main Lock Server application class

      • Configure CDI beans and dependency injection for all services
      • Implement application startup and shutdown lifecycle management
      • Create configuration loading and validation on startup
      • Requirements: All requirements integration
    • 13.2 Create application configuration and deployment artifacts

      • Configure JAX-RS application with all REST endpoints and filters
      • Create production-ready configuration files and deployment scripts
      • Implement proper error handling and logging throughout the application
      • Requirements: All requirements integration

Clone this wiki locally