Lock Server Configuration and Operation#
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.
Overview#
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.
Key Capabilities#
- Policy Distribution: Centralized management and distribution of Cedar policies
- Policy Updates: Efficient policy change management and distribution
- Audit Collection: Centralized logging of authorization decisions and system events
- OAuth Security: Comprehensive OAuth 2.0 protection for all endpoints
- Flexible Deployment: Standalone or integrated with Jans Auth Server
- Management Interfaces: CLI, TUI, and REST API for administration
Architecture#
High-Level Components#
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
Internal Architecture#
The Lock Server consists of several layers:
- Web Layer: REST endpoints for policy and audit operations
- Security Layer: OAuth token validation and Cedarling authorization
- Business Logic: Policy store management, audit collection, client management
- Data Layer: Policy store cache, audit storage, client registry
- Integration Layer: Embedded Cedarling, external policy sources
Installation and Deployment#
Deployment Options#
The Lock Server supports two primary deployment models:
Standalone Deployment#
Deploy Lock Server as an independent web application:
# 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
- LOCK_SERVER_JWKS_URI=https://auth.example.com/.well-known/jwks
volumes:
- ./config:/opt/jans/lock-server/config
- ./logs:/opt/jans/lock-server/logs
networks:
- jans-network
redis:
image: redis:alpine
networks:
- jans-network
networks:
jans-network:
driver: bridge
Integrated Deployment#
Deploy Lock Server embedded within 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
- JANS_LOCK_SERVER_EMBEDDED_MODE=true
volumes:
- ./lock-server-config:/opt/jans/jetty/jans-auth/custom/lock-server
- ./policy-stores:/opt/jans/lock-server/policy-stores
High Availability Setup#
For production deployments requiring high availability:
# HA deployment with load balancer
services:
nginx:
image: nginx:alpine
ports:
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- lock-server-1
- lock-server-2
lock-server-1:
image: janssenproject/lock-server:latest
environment:
- LOCK_SERVER_INSTANCE_ID=lock-server-1
- LOCK_SERVER_REDIS_URL=redis://redis:6379
depends_on:
- redis
lock-server-2:
image: janssenproject/lock-server:latest
environment:
- LOCK_SERVER_INSTANCE_ID=lock-server-2
- LOCK_SERVER_REDIS_URL=redis://redis:6379
depends_on:
- redis
redis:
image: redis:alpine
command: redis-server --appendonly yes
volumes:
- redis-data:/data
volumes:
redis-data:
Installation Steps#
- Prerequisites
- Java 11 or higher
- Jans Auth Server (for OAuth services)
-
Redis (for HA deployments)
-
Download and Extract
wget https://github.com/JanssenProject/jans/releases/latest/download/lock-server.tar.gz tar -xzf lock-server.tar.gz cd lock-server -
Configure Environment
cp config/lock-server.properties.template config/lock-server.properties # Edit configuration file with your settings -
Start Lock Server
./bin/start-lock-server.sh
Configuration#
Core Configuration Properties#
The Lock Server uses a properties file for configuration:
# Lock Server Configuration
lock.server.host=0.0.0.0
lock.server.port=8080
lock.server.context.path=/
# OAuth Configuration
lock.server.oauth.issuer=https://auth.example.com
lock.server.oauth.jwks.uri=https://auth.example.com/.well-known/jwks
lock.server.oauth.token.validation.enabled=true
# Policy Store Configuration
lock.server.policy.store.source=github
lock.server.policy.store.github.repo=organization/policy-repo
lock.server.policy.store.github.branch=main
lock.server.policy.store.github.token=${GITHUB_TOKEN}
lock.server.policy.store.cache.ttl=300
# Cedarling Configuration
lock.server.cedarling.policy.store.uri=file:///opt/jans/lock-server/policies/lock-server-policies.json
lock.server.cedarling.log.level=INFO
# Audit Configuration
lock.server.audit.enabled=true
lock.server.audit.storage=file
lock.server.audit.file.path=/opt/jans/lock-server/logs/lock_server_audit.log
lock.server.audit.rdbms.enabled=false
# Policy Update Configuration
lock.server.policy.update.enabled=true
lock.server.policy.update.check.interval=60
# Logging Configuration
lock.server.log.level=INFO
lock.server.log.config.file=/opt/jans/lock-server/logs/lock_server_config.log
lock.server.log.jwt.status.file=/opt/jans/lock-server/logs/lock_server_jwt_status.log
TRACE Configuration#
The traceConfiguration block of the Lock Server dynamic configuration (jansConfDyn) controls
the TRACE evidence-ingestion feature: which OAuth clients may submit or read evidence for which
evidence domain, lateness policy, and request limits enforced before any cryptographic
verification. See TRACE Evidence for the feature description and API.
| Property | Type | Default | Meaning |
|---|---|---|---|
enabled |
boolean | true |
When false, every TRACE endpoint returns a structured invalid_request error and the receipt repair timer does not run. |
defaultEvidenceDomainId |
string | null |
Evidence domain used for a submitting/reading client that has no explicit entry in clientDomainBindings. |
defaultAllowedProducerIds |
array | [] |
Producer ids a client without a binding may submit records for in the default evidence domain. Empty means such a client can submit nothing (producer_not_allowed). Read and admin paths are unaffected. |
clientDomainBindings |
array | [] |
List of { clientId, evidenceDomainId, allowedProducerIds[] } bindings. A client without a binding and without defaultEvidenceDomainId set is rejected with client_not_bound. allowedProducerIds may contain "*" to allow any producer. |
latenessThresholdSeconds |
integer | 300 |
Seconds after signed_at a record may still be accepted before it is flagged late_flag: true. |
policyMismatchGraceSeconds |
integer | 300 |
Seconds after the last Lock node stops serving a policy store release during which records judged under it are not flagged policy_mismatch_flag. The check uses the larger of this and latenessThresholdSeconds, plus about 130 seconds for update and cache lag. See TRACE. |
policyReleaseRetentionDays |
integer | 30 |
Days a policy store release no node serves any more is kept before it is deleted; never less than the check's acceptance window. |
maxFutureSkewSeconds |
integer | 300 |
Seconds signed_at may be ahead of Lock's clock. A later signed_at is rejected with invalid_assertion (signed_at_in_future). |
maxRequestBytes |
integer | 262144 |
Maximum accepted TRACE request body size, in bytes. |
maxJsonDepth |
integer | 32 |
Maximum accepted JSON nesting depth of a TRACE assertion. |
maxStringLength |
integer | 8192 |
Maximum accepted JSON string length (UTF-16 units) in a TRACE assertion. |
maxArrayLength |
integer | 256 |
Maximum accepted JSON array length in a TRACE assertion. |
maxObjectMembers |
integer | 256 |
Maximum accepted JSON object member count in a TRACE assertion. |
receiptAllocationRetryLimit |
integer | 8 |
Maximum retries when allocating the next receipt-chain sequence number under multi-node contention. |
correlationRetryLimit |
integer | 3 |
Maximum retries when a neighbor-flag update after a record insert hits a version conflict. After the limit Lock logs a warning and gives up on that update; the request still succeeds. |
receiptRepairIntervalSeconds |
integer | 300 |
Interval between runs of the receipt repair timer, which settles stale PENDING receipts. |
pendingReceiptTimeoutSeconds |
integer | 120 |
Seconds a PENDING receipt may remain unresolved before the repair timer marks it COMMITTED or VOID. |
maxBulkRecords |
integer | 100 |
Maximum number of assertions accepted in one POST /audit/trace/bulk request. |
maxBulkRequestBytes |
integer | 4194304 |
Maximum total body size, in bytes, buffered for one POST /audit/trace/bulk request. Independent of maxRequestBytes/maxBulkRecords, and always clamped to 16777216 regardless of configuration. |
chainRegistrationMode |
string | PRE_REGISTERED |
How producer chains come to exist. PRE_REGISTERED: a chain must be registered through the admin API before its records are accepted. FIRST_OBSERVED: a record with sequence_number 1 and the all-zero prev_record_hash on an unregistered chain registers the chain, after the key, event-kind and signature checks pass. Any other record on an unregistered chain is still rejected with chain_not_registered. A value that is not a mode name is treated as PRE_REGISTERED and logged once at WARN. Changing the mode affects only later submissions; existing chains are not rewritten. |
cryptoProvider |
string | JAVA |
TRACE cryptography implementation. JAVA: BouncyCastle, in-process. NATIVE: jans-trace-core through the jans-trace-java binding. Both produce the same digests, thumbprints and receipt hashes, so switching does not invalidate the stored receipt chain. When the selected provider is not available, every TRACE submission fails with crypto_unavailable; Lock never falls back to the other provider. A value that is not a provider name is treated as JAVA and logged once at WARN. See TRACE. |
Every numeric limit above falls back to its default when configured with a value <= 0.
Policy Store Sources#
The Lock Server supports multiple policy store sources:
GitHub Repository#
lock.server.policy.store.source=github
lock.server.policy.store.github.repo=organization/policy-repo
lock.server.policy.store.github.branch=main
lock.server.policy.store.github.path=policy-stores/
lock.server.policy.store.github.token=${GITHUB_TOKEN}
Local File System#
lock.server.policy.store.source=file
lock.server.policy.store.file.path=/opt/jans/lock-server/policy-stores/
lock.server.policy.store.file.watch.enabled=true
HTTP Endpoint#
lock.server.policy.store.source=http
lock.server.policy.store.http.base.url=https://policy-server.example.com/api/v1/
lock.server.policy.store.http.auth.type=bearer
lock.server.policy.store.http.auth.token=${POLICY_SERVER_TOKEN}
REST API Endpoints#
The Lock Server provides several REST API endpoints for different operations:
Policy Store Endpoints#
Get Policy Store#
GET /policy-store/{id}
Authorization: Bearer <access_token>
Response:
{
"cedar_version": "v4.0.0",
"policy_store": {
"name": "Application Policy Store",
"description": "Policies for application authorization",
"policies": { ... },
"schema": { ... },
"trusted_issuers": { ... }
}
}
List Policy Stores#
GET /policy-stores
Authorization: Bearer <access_token>
Response:
{
"policy_stores": [
{
"id": "app-policies",
"name": "Application Policies",
"description": "Main application policy store",
"version": "1.2.3",
"last_updated": "2024-01-01T12:00:00Z"
}
]
}
Audit Endpoints#
Submit Audit Logs#
POST /api/v1/audit/log
Authorization: Bearer <access_token>
Content-Type: application/json
{
"creation_date": "2026-03-23T11:50:37.504Z",
"event_time": "2026-03-23T11:50:37.504Z",
"service": "my_app",
"node_name": "0195c6f2-8d1a-7c3e-9b4f-2a6d8e0f1b3c",
"event_type": "Decision",
"severity_level": "INFO",
"action": "Jans::Action::\"Update\"",
"decision_result": "ALLOW",
"requested_resource": "Jans::Issue::\"random_id\"",
"principal_id": "Jans::User, Jans::Workload",
"client_id": "lock-client-123",
"context_information": {
"request_id": "0195c6f2-8d1a-7c3e-9b4f-2a6d8e0f1b3e",
"policystore_id": "a1bf63d5a5e4a0b7d0d5c9e3",
"policystore_version": "1.0.0",
"diagnostics": { "reason": [], "errors": [] },
"decision_time_micro_sec": 42
}
}
This is the shape Cedarling sends. POST /audit/log/bulk takes an array of the same objects. Both need the https://jans.io/oauth/lock/log.write scope. Lock also accepts the camelCase member names it returns (creationDate, eventTime, nodeName, contextInformation, and so on). contextInformation is stored as a flat string map: a string value is kept as is, and an object, array, number or boolean value is stored as its JSON text, as on the gRPC path.
Search Audit Logs#
Config API serves stored decision logs at GET /jans-config-api/lock/audit/log/search. eventStartDate and eventEndDate (ISO 8601) are required. Optional exact-match filters:
| Parameter | Matches |
|---|---|
requestId |
Cedarling request_id of the decision |
policyStoreId |
Policy store id used for the decision |
policyStoreVersion |
Policy store version used for the decision |
A stored entry takes these from the request_id, policystore_id and policystore_version keys of contextInformation when present, and otherwise from the entry's own requestId, policyStoreId and policyStoreVersion. A request_id longer than 64 characters or a policy store value longer than 255 characters is not indexed. Entries stored before this release are not indexed and match only the date range.
Submit Health Status#
POST /audit/health
Authorization: Bearer <access_token>
Content-Type: application/json
{
"pdp_id": "cedarling-001",
"timestamp": "2024-01-01T12:00:00Z",
"status": "healthy",
"policy_store_version": "1.2.3",
"uptime_seconds": 86400,
"memory_usage_mb": 128,
"cpu_usage_percent": 15.5
}
Submit Telemetry Data#
POST /audit/telemetry
Authorization: Bearer <access_token>
Content-Type: application/json
{
"pdp_id": "cedarling-001",
"timestamp": "2024-01-01T12:00:00Z",
"metrics": {
"total_requests": 1000,
"successful_requests": 950,
"failed_requests": 50,
"average_response_time_ms": 12.5,
"policy_evaluations": 1000,
"cache_hits": 800,
"cache_misses": 200
}
}
Well-Known Configuration#
Lock Server Configuration#
GET /.well-known/lock-server-configuration
Response:
{
"version": "1.0",
"issuer": "lock-server.example.com",
"audit": {
"health_endpoint": "https://lock-server.example.com/jans-lock/api/v1/audit/health",
"health_bulk_endpoint": "https://lock-server.example.com/jans-lock/api/v1/audit/health/bulk",
"log_endpoint": "https://lock-server.example.com/jans-lock/api/v1/audit/log",
"log_bulk_endpoint": "https://lock-server.example.com/jans-lock/api/v1/audit/log/bulk",
"telemetry_endpoint": "https://lock-server.example.com/jans-lock/api/v1/audit/telemetry",
"telemetry_bulk_endpoint": "https://lock-server.example.com/jans-lock/api/v1/audit/telemetry/bulk",
"trace_endpoint": "https://lock-server.example.com/jans-lock/api/v1/audit/trace",
"trace_bulk_endpoint": "https://lock-server.example.com/jans-lock/api/v1/audit/trace/bulk",
"trace_record_endpoint": "https://lock-server.example.com/jans-lock/api/v1/audit/trace/records",
"trace_execution_endpoint": "https://lock-server.example.com/jans-lock/api/v1/audit/trace/executions"
},
"config": {
"policy_endpoint": "https://lock-server.example.com/jans-lock/api/v1/policy"
}
}
The trace_* members appear only when TRACE is enabled.
OAuth Security#
Scope-Based Access Control#
The Lock Server uses OAuth 2.0 scopes to control access to different endpoints:
| Scope | Endpoints | Description |
|---|---|---|
https://jans.io/oauth/lock/policy-store.read |
/policy-store/*, /policy-stores |
Read access to policy stores |
https://jans.io/oauth/lock/log.write |
/audit/logs |
Submit authorization decision logs |
https://jans.io/oauth/lock/health.write |
/audit/health |
Submit health status information |
https://jans.io/oauth/lock/telemetry.write |
/audit/telemetry |
Submit telemetry and metrics data |
https://jans.io/oauth/lock/trace.write |
/audit/trace |
Submit TRACE evidence records |
https://jans.io/oauth/lock/trace.readonly |
/audit/trace/records, /audit/trace/records/*, /audit/trace/executions/* |
Read and search TRACE records and executions |
https://jans.io/oauth/lock/trace.admin |
/audit/trace/admin/* |
Manage TRACE producer keys and chains |
Logging and Monitoring#
Log Files#
The Lock Server generates several log files for different purposes:
Configuration Log (lock_server_config.log)#
Records configuration changes and system events:
2024-01-01 12:00:00 INFO [ConfigService] Policy store configuration updated: app-policies
2024-01-01 12:01:00 INFO [ConfigService] Trusted issuer added: enterprise_idp
2024-01-01 12:02:00 WARN [ConfigService] Policy store cache miss for: test-policies
2024-01-01 12:03:00 ERROR [ConfigService] Failed to fetch policy store from GitHub: network timeout
Audit Log (lock_server_audit.log)#
Stores authorization decisions and audit events:
{
"timestamp": "2024-01-01T12:00:00Z",
"request_id": "req-123456",
"log_kind": "Decision",
"pdp_id": "cedarling-001",
"policy_store_id": "app-policies",
"decision": "ALLOW",
"principal": "Jans::User::\"user123\"",
"action": "Jans::Action::\"read\"",
"resource": "Jans::Application::\"app001\"",
"decision_time_ms": 15
}
JWT Status Log (lock_server_jwt_status.log)#
Tracks JWT token validation and processing:
2024-01-01 12:00:00 INFO [JWTValidator] Token validated successfully for client: client123
2024-01-01 12:01:00 WARN [JWTValidator] Token expired for client: client456
2024-01-01 12:02:00 ERROR [JWTValidator] Invalid signature for token from issuer: https://malicious.com
RDBMS Audit Storage#
With auditPersistenceMode set to internal, Lock stores decision logs in the jansLogEntry table of the Janssen database (entries under ou=log of the audit base DN). With config-api, Lock forwards them to Config API, which stores them in the same table.
| Column | Source |
|---|---|
inum |
Generated by Lock |
creationDate, eventTime |
creation_date, event_time |
jansService, jansNodeName |
service, node_name |
eventType, severityLevel |
event_type, severity_level |
actionName, decisionResult, requestedResource |
action, decision_result, requested_resource |
principalId, clientId, jti |
principal_id, client_id, jti |
contextInformation |
context_information, as a JSON object of strings |
jansRequestId, jansPolicyStoreId, jansPolicyStoreVersion |
Indexed copies of request_id, policystore_id, policystore_version (see Search Audit Logs) |
eventTime, jansRequestId, jansPolicyStoreId and jansPolicyStoreVersion are indexed.
Upgrading an Existing Deployment#
The audit log and TRACE search filters need new columns and indexes, and the policy release check needs the jansTracePolicyRelease table. Container and Kubernetes deployments get them automatically: the persistence loader adds missing columns and indexes on its next run. An existing VM install needs them added once, by hand. Back up the database first.
ALTER TABLE "jansLogEntry" ADD COLUMN "jansRequestId" VARCHAR(64);
ALTER TABLE "jansLogEntry" ADD COLUMN "jansPolicyStoreId" VARCHAR(255);
ALTER TABLE "jansLogEntry" ADD COLUMN "jansPolicyStoreVersion" VARCHAR(255);
CREATE INDEX "jansLogEntry_jansRequestId" ON "jansLogEntry" ("jansRequestId");
CREATE INDEX "jansLogEntry_jansPolicyStoreId" ON "jansLogEntry" ("jansPolicyStoreId");
CREATE INDEX "jansLogEntry_jansPolicyStoreVersion" ON "jansLogEntry" ("jansPolicyStoreVersion");
ALTER TABLE "jansTraceRecord" ADD COLUMN "jansTracePolicyStoreId" VARCHAR(255);
ALTER TABLE "jansTraceRecord" ADD COLUMN "jansTracePolicyStoreVersion" VARCHAR(255);
ALTER TABLE "jansTraceRecord" ADD COLUMN "jansTraceBundleHash" VARCHAR(255);
ALTER TABLE "jansTraceRecord" ADD COLUMN "jansTracePolicyMismatch" BOOLEAN;
ALTER TABLE "jansTraceRecord" ADD COLUMN "jansTraceReservedMembers" JSONB;
CREATE INDEX "jansTraceRecord_jansTracePolicyStoreId" ON "jansTraceRecord" ("jansTracePolicyStoreId");
CREATE INDEX "jansTraceRecord_jansTracePolicyStoreVersion" ON "jansTraceRecord" ("jansTracePolicyStoreVersion");
CREATE INDEX "jansTraceRecord_jansTraceBundleHash" ON "jansTraceRecord" ("jansTraceBundleHash");
CREATE TABLE "jansTracePolicyRelease" (
doc_id VARCHAR(64) NOT NULL UNIQUE,
"objectClass" VARCHAR(48),
dn VARCHAR(128),
"jansId" VARCHAR(128),
"jansTracePolicyStoreId" VARCHAR(255),
"jansTraceBundleHash" VARCHAR(255),
"jansTracePolicyStoreVersion" VARCHAR(255),
"jansTraceFirstServedAtMs" BIGINT,
"jansTraceLastServedAtMs" BIGINT,
"jansVersion" BIGINT,
PRIMARY KEY (doc_id)
);
CREATE INDEX "jansTracePolicyRelease_jansId" ON "jansTracePolicyRelease" ("jansId");
CREATE INDEX "jansTracePolicyRelease_jansTracePolicyStoreId" ON "jansTracePolicyRelease" ("jansTracePolicyStoreId");
CREATE INDEX "jansTracePolicyRelease_jansTraceLastServedAtMs" ON "jansTracePolicyRelease" ("jansTraceLastServedAtMs");
ALTER TABLE jansLogEntry ADD COLUMN jansRequestId VARCHAR(64);
ALTER TABLE jansLogEntry ADD COLUMN jansPolicyStoreId VARCHAR(255);
ALTER TABLE jansLogEntry ADD COLUMN jansPolicyStoreVersion VARCHAR(255);
ALTER TABLE jansLogEntry ADD INDEX jansLogEntry_jansRequestId (jansRequestId);
ALTER TABLE jansLogEntry ADD INDEX jansLogEntry_jansPolicyStoreId (jansPolicyStoreId);
ALTER TABLE jansLogEntry ADD INDEX jansLogEntry_jansPolicyStoreVersion (jansPolicyStoreVersion);
ALTER TABLE jansTraceRecord ADD COLUMN jansTracePolicyStoreId VARCHAR(255);
ALTER TABLE jansTraceRecord ADD COLUMN jansTracePolicyStoreVersion VARCHAR(255);
ALTER TABLE jansTraceRecord ADD COLUMN jansTraceBundleHash VARCHAR(255);
ALTER TABLE jansTraceRecord ADD COLUMN jansTracePolicyMismatch SMALLINT;
ALTER TABLE jansTraceRecord ADD COLUMN jansTraceReservedMembers JSON;
ALTER TABLE jansTraceRecord ADD INDEX jansTraceRecord_jansTracePolicyStoreId (jansTracePolicyStoreId);
ALTER TABLE jansTraceRecord ADD INDEX jansTraceRecord_jansTracePolicyStoreVersion (jansTracePolicyStoreVersion);
ALTER TABLE jansTraceRecord ADD INDEX jansTraceRecord_jansTraceBundleHash (jansTraceBundleHash);
CREATE TABLE jansTracePolicyRelease (
doc_id VARCHAR(64) NOT NULL UNIQUE,
objectClass VARCHAR(48),
dn VARCHAR(128),
jansId VARCHAR(128),
jansTracePolicyStoreId VARCHAR(255),
jansTraceBundleHash VARCHAR(255),
jansTracePolicyStoreVersion VARCHAR(255),
jansTraceFirstServedAtMs BIGINT,
jansTraceLastServedAtMs BIGINT,
jansVersion BIGINT,
PRIMARY KEY (doc_id),
INDEX jansTracePolicyRelease_jansId (jansId),
INDEX jansTracePolicyRelease_jansTracePolicyStoreId (jansTracePolicyStoreId),
INDEX jansTracePolicyRelease_jansTraceLastServedAtMs (jansTraceLastServedAtMs)
);
Records and log entries stored before the upgrade have empty values in the new columns, so release search and log filters do not return them.
Metrics and Monitoring#
The Lock Server exposes metrics for monitoring:
- Policy Store Metrics: Cache hit/miss rates, fetch times, update frequencies
- Authorization Metrics: Request rates, decision times, success/failure ratios
- Client Metrics: Active connections, request patterns, error rates
- System Metrics: Memory usage, CPU utilization, response times
CLI Management#
Jans CLI Commands#
The Lock Server can be managed using Jans CLI commands:
Policy Store Management#
# List policy stores
jans-cli --operation-id get-lock-policy-stores
# Get specific policy store
jans-cli --operation-id get-lock-policy-store --url-suffix "app-policies"
# Update policy store configuration
jans-cli --operation-id put-lock-policy-store --url-suffix "app-policies" \
--data '{"source": "github", "repository": "org/new-repo"}'
# Delete policy store
jans-cli --operation-id delete-lock-policy-store --url-suffix "app-policies"
Client Management#
# List connected Cedarling clients
jans-cli --operation-id get-lock-clients
# Get client details
jans-cli --operation-id get-lock-client --url-suffix "client123"
# Search clients by username
jans-cli --operation-id get-lock-clients --query "username=john.doe"
# View client authorization activity
jans-cli --operation-id get-lock-client-activity --url-suffix "client123" \
--query "start_date=2024-01-01&end_date=2024-01-31"
Metrics and Monitoring#
# Get authorization metrics
jans-cli --operation-id get-lock-metrics --query "metric=authorization_requests&period=daily"
# Get system health
jans-cli --operation-id get-lock-health
# Get audit log summary
jans-cli --operation-id get-lock-audit-summary --query "start_date=2024-01-01"
TUI Interface#
The Text-based User Interface provides an interactive way to manage Lock Server:
- Access TUI:
sudo /opt/jans/bin/jans-tui.py - Navigate to Lock Server:
Lock Server>Configuration - Available Sections:
- Policy Store Management
- Client Registry
- Audit Logs
- System Metrics
- Configuration Settings
Troubleshooting#
Common Issues#
Policy Store Not Loading#
Symptoms: Cedarling clients cannot retrieve policy stores Causes: - Invalid policy store source configuration - Network connectivity issues - Authentication failures with external sources
Solutions:
# Check policy store configuration
jans-cli --operation-id get-lock-policy-store-config
# Test policy store connectivity
curl -H "Authorization: Bearer <token>" \
https://lock-server.example.com/policy-store/app-policies
# Check logs for errors
tail -f /opt/jans/lock-server/logs/lock_server_config.log
OAuth Token Validation Failures#
Symptoms: Clients receive 401 Unauthorized responses Causes: - Expired or invalid access tokens - Incorrect JWKS URI configuration - Clock synchronization issues
Solutions:
# Verify JWKS URI configuration
jans-cli --operation-id get-lock-oauth-config
# Check JWT status logs
tail -f /opt/jans/lock-server/logs/lock_server_jwt_status.log
# Test token validation manually
curl -H "Authorization: Bearer <token>" \
https://lock-server.example.com/.well-known/lock-master-configuration
Policy Update Issues#
Symptoms: Cedarling clients not receiving latest policy updates Causes: - Policy store cache configuration issues - Network connectivity problems - Policy source synchronization failures
Solutions:
# Check policy store cache status
jans-cli --operation-id get-lock-policy-cache-status
# Force policy store refresh
jans-cli --operation-id post-lock-policy-refresh --url-suffix "app-policies"
# Monitor policy update logs
tail -f /opt/jans/lock-server/logs/lock_server_config.log
Performance Optimization#
Policy Store Caching#
- Increase cache TTL for stable policy stores
- Use Redis for distributed caching in HA setups
- Monitor cache hit rates and adjust accordingly
Database Optimization#
- Create appropriate indexes for audit log queries
- Implement log rotation and archival policies
- Use connection pooling for database access
Network Optimization#
- Use CDN for policy store distribution
- Implement compression for large policy stores
- Configure appropriate timeout values
Security Considerations#
Production Deployment Security#
- TLS Configuration: Always use HTTPS in production
- Token Security: Implement proper token rotation and validation
- Network Security: Use firewalls and network segmentation
- Audit Security: Protect audit logs from tampering
- Access Control: Implement least-privilege access principles
Security Best Practices#
- Regular security updates and patches
- Monitoring and alerting for security events
- Regular audit log reviews
- Secure backup and recovery procedures
- Incident response planning
API Reference#
For complete API documentation, see the Lock Server OpenAPI Specification.
See Also#
- Janssen Lock Overview: Complete Lock ecosystem documentation
- Cedarling Documentation: Client-side authorization engine
- Cedar Policy Language: Official Cedar documentation
- OAuth 2.0 Configuration: OAuth implementation details
- Jans CLI Reference: Command-line interface documentation