-
Notifications
You must be signed in to change notification settings - Fork 74
Cedarling Nativity Plan
- Needs to call the WASM component using a few javascript lines of code (ideally 1-2)
- Input from JS component is object
input = {
"access_token": "...",
"id_token": "...",
"userinfo_token": "...",
"tx_token": "...",
"resource": {"id": "12345", "type": "Ticket", "creator": "mike@gluu.org", "organization": "gluu"},
"action": "View",
"context": {
"ip_address": "54.9.21.201",
"network_type": "VPN",
"user_agent": "Chrome 125.0.6422.77 (Official Build) (arm64)",
"time": "1719266610.98636",
}
}
decision_result = authz(input)
-
CEDARLING_APPLICATION_NAME
: Human friendly identifier for this application -
CEDARLING_POLICY_STORE_URI
: Location of policy store JSON, used if policy store is not local, or retreived from Lock Master. -
CEDARLING_POLICY_STORE_ID
: The identifier of the policy store in case there is more then one policy_store_id in the policy store. -
CEDARLING_LOG_TYPE
:off
,memory
,std_out
,lock
-
CEDARLING_LOG_TTL
: in case ofmemory
store, TTL (time to live) of log entities in seconds. -
CEDARLING_LOCAL_JWKS
: JWKS file with public keys -
CEDARLING_LOCAL_POLICY_STORE
: JSON object with policy store -
CEDARLING_JWT_SIG_VALIDATION
:Enabled
|Disabled
-- Whether to check the signature of all JWT tokens. This requires aniss
is present. -
CEDARLING_JWT_STATUS_VALIDATION
:Enabled
|Disabled
-- Whether to check the status of the JWT. On startup, the Cedarling should fetch and retreive the latest Status List JWT from the.well-known/openid-configuration
via thestatus_list_endpoint
claim and cache it. See the IETF Draft for more info. -
CEDARLING_JWT_SIGNATURE_ALGORITHMS_SUPPORTED
: Only tokens signed with these algorithms are acceptable to the Cedarling. -
CEDARLING_AT_ISS_VALIDATION
: When enabled, theiss
claim must be present in access token and the scheme must behttps
. -
CEDARLING_AT_JTI_VALIDATION
: When enabled, thejti
claim must be present in access token. -
CEDARLING_AT_NBF_VALIDATION
: When enabled, thenbf
claim must be present in access token and the Cedarling should verify that the current date is after thenbf
. -
CEDARLING_AT_EXP_VALIDATION
: When enabled, theexp
claim must be present and not past the date specified. -
CEDARLING_IDT_ISS_VALIDATION
: When enabled, theiss
claim must be present in id_token and the scheme must behttps
. -
CEDARLING_IDT_SUB_VALIDATION
: When enabled, thesub
claim must be present in id_token. -
CEDARLING_IDT_EXP_VALIDATION
: When enabled, theexp
claim must be present and not past the date specified. -
CEDARLING_IDT_IAT_VALIDATION
: When enabled, theiat
claim must be present in id_token. -
CEDARLING_IDT_AUD_VALIDATION
: When enabled, theaud
claim must be present in id_token. -
CEDARLING_USERINFO_ISS_VALIDATION
: When enabled, theiss
claim must be present and the scheme must behttps
. -
CEDARLING_USERINFO_SUB_VALIDATION
: When enabled, thesub
claim must be present in Userinfo JWT. -
CEDARLING_USERINFO_AUD_VALIDATION
: When enabled, theaud
claim must be present in Userinfo JWT. -
CEDARLING_USERINFO_EXP_VALIDATION
: When enabled, theexp
claim must be present and not past the date specified. -
CEDARLING_ID_TOKEN_TRUST_MODE
:Strict
|None
. Varying levels of validations based on the preference of the developer.Strict
mode requires (1) id_tokenaud
matches the access_tokenclient_id
; (2) if a Userinfo token is present, thesub
matches the id_token, and that theaud
matches the access token client_id.
The following bootstrap properties are only needed for enterprise deployments.
-
CEDARLING_LOCK
: Enabled | Disabled. If Enabled, the Cedarling will connect to the Lock Master for policies, and subscribe for SSE events. -
CEDARLING_LOCK_MASTER_CONFIGURATION_URI
: Required ifLOCK
==Enabled
. URI where Cedarling can get JSON file with all required metadata about Lock Master, i.e..well-known/lock-master-configuration
. -
CEDARLING_DYNAMIC_CONFIGURATION
: Enabled | Disabled, controls whether Cedarling should listen for SSE config updates. -
CEDARLING_LOCK_SSA_JWT
: SSA for DCR in a Lock Master deployment. The Cedarling will validate this SSA JWT prior to DCR. -
CEDARLING_AUDIT_LOG_INTERVAL
: How often to send log messages to Lock Master (0 to turn off trasmission). -
CEDARLING_AUDIT_HEALTH_INTERVAL
: How often to send health messages to Lock Master (0 to turn off transmission). -
CEDARLING_AUDIT_TELEMETRY_INTERVAL
: How often to send telemetry messages to Lock Master (0 to turn off transmission). -
CEDARLING_LISTEN_SSE
: Enabled | Disabled: controls whether Cedarling should listen for updates from the Lock Server.
The Cedarling Policy Store is a JSON file that contains all the data the Cedarling needs to verify JWT tokens and evaluate policies:
- Cedar Schema - JSON format Schema file
- Cedar Policies - JSON format Policy Set file (beware CLI bug cedar-950)
- Trusted Issuers - JSON file with below syntax
cedarling_store.json
schema
{
"cedar_version": "v4.0.0",
"policy_stores": {
"some_random_id": {
"name": "",
"description": "",
"policies": {...}
"trusted_issuers": {...},
"schema": ""
}
},
}
Currently cedarling
support only one policy_store
in policy_stores
map.
We have policy_stores
map to avoid incompatible change in future.
This record contains the information needed to validate tokens from this issuer:
{
"name": "Google",
"description": "Consumer IDP",
"openid_configuration_endpoint": "https://accounts.google.com/.well-known/openid-configuration",
"access_tokens": {...},
"id_tokens": {...},
"userinfo_tokens": {...},
"tx_tokens": {...}
}
see below for the "access_tokens"
, "id_tokens"
, "userinfo_tokens"
, and "tx_tokens"
schema.
{
"user_id": "...", <-- OPTIONAL e.g. email, sub, uid
"role_mapping": "...", <-- OPTIONAL e.g. role, memberOf
"claim_mapping": { <-- OPTIONAL
"email": {
"parser": "regex",
"type": "Acme::Email",
"regex_expression" : "^(?P<UID>[^@]+)@(?P<DOMAIN>.+)$",
"UID": {"attr": "uid", "type":"string"},
"DOMAIN": {"attr": "domain", "type":"string"}
},
"profile": {
"parser": "regex",
"type": "Acme::URI",
"regex_expression": "(?x) ^(?P<SCHEME>[a-zA-Z][a-zA-Z0-9+.-]*):\/\/ (?P<HOST>[^\/:#?]+) (?::(?P<PORT>\d+))? (?P<PATH>\/[^?#]*)? (?:\?(?P<QUERY>[^#]*))? (?:#(?P<FRAGMENT>.*))?$",
"SCHEME": {"attr": "scheme", "type":"string"},
"HOST": {"attr": "host", "type":"string"},
"PORT": {"attr": "port", "type":"string"},
"PATH": {"attr": "path", "type":"string"},
"QUERY": {"attr": "query", "type":"string"},
"FRAGMENT": {"attr": "fragment", "type":"string"}
},
"dolphin": {
"parser": "json",
"type": "Acme::Dolphin"}
}
}
}
Note use of regex named capture groups which is more readable by referring to parts of a regex match by descriptive names rather than numbers. For example, (?P<name>...)
defines a named capture group where name is the identifier, and ... is the regex pattern for what you want to capture.
namespace Jans {
// ****** TYPES ******
type Url = {
protocol: String,
host: String,
path: String,
};
type email_address = {
id: String,
domain: String,
};
type Context = {
network: ipaddr,
network_type: String,
user_agent: String,
operating_system: String,
device_health: Set<String>,
current_time: Long,
geolocation: Set<String>,
fraud_indicators: Set<String>,
};
// ****** Entities ******
entity Workload = {
client_id: String,
iss: TrustedIssuer,
name: String,
spiffe_id: String,
rp_id: String
};
entity Access_token = {
aud: String,
exp: Long,
iat: Long,
iss: TrustedIssuer,
jti: String,
nbf: Long,
scope: String,
};
entity TrustedIssuer = {
issuer_entity_id: Url,
};
entity Role;
entity User in [Role] {
sub: String,
username: String,
email: email_address,
phone_number: String,
role: Set<String>,
};
entity id_token = {
acr: Set<String>,
amr: String,
aud: String,
azp: String,
birthdate: String,
email: email_address,
exp: Long,
iat: Long,
iss: TrustedIssuer,
jti: String,
name: String,
phone_number: String,
role: Set<String>,
sub: String,
};
entity Userinfo_token = {
aud: String,
birthdate: String,
email: email_address,
exp: Long,
iat: Long,
iss: TrustedIssuer,
jti: String,
name: String,
phone_number: String,
role: Set<String>,
sub: String,
};
entity HTTP_Request = {
"url": Url,
"header": Set<String>,
"accept": Set<String>,
};
// ****** Actions ******
action Compare appliesTo {
principal: [User, Role],
resource: Workload,
context: Context,
};
action Execute appliesTo {
principal: [User, Role],
resource: Workload,
context: Context,
};
action Monitor appliesTo {
principal: [User, Role],
resource: Workload,
context: Context,
};
action Read appliesTo {
principal: [User, Role],
resource: Workload,
context: Context,
};
action Search appliesTo {
principal: [User, Role],
resource: Workload,
context: Context,
};
action Share appliesTo {
principal: [User, Role],
resource: Workload,
context: Context,
};
action Tag appliesTo {
principal: [User, Role],
resource: Workload,
context: Context,
};
action Write appliesTo {
principal: [User, Role],
resource: Workload,
context: Context,
};
action GET appliesTo {
principal: Workload,
resource: HTTP_Request,
context: Context,
};
action PUT appliesTo {
principal: Workload,
resource: HTTP_Request,
context: Context,
};
action DELETE appliesTo {
principal: Workload,
resource: HTTP_Request,
context: Context,
};
action HEAD appliesTo {
principal: Workload,
resource: HTTP_Request,
context: Context,
};
action PATCH appliesTo {
principal: Workload,
resource: HTTP_Request,
context: Context,
};
}
- TrustedIssuer: Created on startup from Policy Store
- Workload: Created from access token client_id
- Application: Created if input supplies an Application name
-
Role: Created for each
role
claim value in the joined id_token and userinfo token -
User: Created based on the joined id_token and userinfo token.
sub
is the entity identifier - Access_token: 1:1 mapping from claims in token
- id_token: 1:1 mapping from claims in token
- Userinfo_token: 1:1 mapping from claims in token
{
"version": "1.0",
"issuer": "yurem-evolved-woodcock.gluu.info",
"audit": {
"health_endpoint": "https://yurem-evolved-woodcock.gluu.info/jans-lock/v1/audit/health",
"log_endpoint": "https://yurem-evolved-woodcock.gluu.info/jans-lock/v1/audit/log",
"telemetry_endpoint": "https://yurem-evolved-woodcock.gluu.info/jans-lock/v1/audit/telemetry"
},
"config": {
"config_endpoint": "https://yurem-evolved-woodcock.gluu.info/jans-lock/v1/config",
"issuers_endpoint": "https://yurem-evolved-woodcock.gluu.info/jans-lock/v1/config/issuers",
"policy_endpoint": "https://yurem-evolved-woodcock.gluu.info/jans-lock/v1/config/policy",
"schema_endpoint": "https://yurem-evolved-woodcock.gluu.info/jans-lock/v1/config/schema",
"sse_endpoint": "https://yurem-evolved-woodcock.gluu.info/jans-lock/v1/sse"
}
}
Cedarling application has internal logger.
Using configuration parameter CEDARLING_LOG_TYPE
you can set up:
-
off
- disabled -
memory
- store log entry in memory -
std_out
- write log entry data to std output stream -
lock
- centralize logs by sending to Jans Lock Server
Using the memory
logger, we can set time to live entry in memory using CEDARLING_LOG_TTL
.
Each log entry marked with log type. In field log_kind
.
Possible variants:
Decision
System
Metric
pub trait LogStorage {
/// return logs and remove them from the storage
fn pop_logs(&self) -> Vec<LogEntry>;
/// get specific log entry
fn get_log_by_id(&self, id: &str) -> Option<LogEntry>;
/// returns a list of all log ids
fn get_log_ids(&self) -> Vec<String>;
}
Note: no JWT status check