Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(jans-cedarling): ensure that all cedarling test fixture files are human-readable. #10036

Merged
merged 30 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8f3d25a
feat(jans-cedarling): parse schema with agama names
djellemah Nov 5, 2024
c47f556
fix(jans-cedarling): fix loading policy store compatible for agama lab
olehbozhok Nov 5, 2024
ddbc38e
chore(jans-cedarling): fix clippy issue
olehbozhok Nov 5, 2024
f98675a
fix(jans-cedarling): fix python unit tests
olehbozhok Nov 5, 2024
bb3bb7e
fix(jans-cedarling): fix alias for trusted_issuers added as `identity…
olehbozhok Nov 5, 2024
6c71362
feat(jans-cedarling): add name and description fields
djellemah Nov 5, 2024
4f799fd
feat(jans-cedarling): make the cedar_version field optional
djellemah Nov 5, 2024
943bc30
feat(jans-cedarling): make struct for top-level key
djellemah Nov 5, 2024
6c84c5b
feat(jans-cedarling): parse identity_source: {}
djellemah Nov 5, 2024
92560d3
feat(jans-cedarling): update cedarling policy store documentation to …
djellemah Nov 3, 2024
febcaf1
feat(jans-cedarling): convert json fixtures to yaml
djellemah Nov 3, 2024
d2c1954
feat(jans-cedarling): update python tests to handle yaml fixtures
djellemah Nov 4, 2024
cf5a6cd
feat(jans-cedarling): remove unnecessary test-related files
djellemah Nov 4, 2024
7f27aa6
feat(jans-cedarling): update test_files/README.md and some other smal…
djellemah Nov 4, 2024
d326706
feat(jans-cedarling): rectify top-level policy-store parsing to handl…
djellemah Nov 6, 2024
54a49a7
feat(jans-cedarling): rectify test fixtures to compliance with policy…
djellemah Nov 6, 2024
73bf09d
feat(jans-cedarling): rectify top-level reading of policy-store data …
djellemah Nov 6, 2024
521660d
feat(jans-cedarling): rectify clippy warning
djellemah Nov 7, 2024
ea127fe
feat(jans-cedarling): add comment in python test that yaml is for tes…
djellemah Nov 7, 2024
c353817
feat(jans-cedarling): rectify python binding test failures due to inc…
djellemah Nov 7, 2024
7246b3f
feat(jans-cedarling): idiomatic python
djellemah Nov 7, 2024
dc63cbb
feat(jans-cedarling): remove commented-out code in parse_single_polic…
djellemah Nov 7, 2024
861d4a6
feat(jans-cedarling): update cedarling readme docs on policy-store
djellemah Nov 7, 2024
76e55e5
Merge branch 'main' into jans-cedarling-issue-10021
moabu Nov 7, 2024
a925c48
Merge branch 'main' into jans-cedarling-issue-10021
olehbozhok Nov 7, 2024
caa7e24
feat(jans-cedarling): rectify discrepancies in documentation with res…
djellemah Nov 7, 2024
4d3f54e
Merge remote-tracking branch 'origin/main' into jans-cedarling-issue-…
djellemah Nov 7, 2024
6f8465d
chore(jans-cedarling): clippy error from merge
djellemah Nov 7, 2024
737cd8a
feat(jans-cedarling): rectify another name & description at the wrong…
djellemah Nov 7, 2024
fb81db6
feat(jans-cedarling): "cedar_version": "v2.4.7" to "v4.0.0"
djellemah Nov 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
204 changes: 155 additions & 49 deletions docs/cedarling/cedarling-policy-store.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,101 +14,192 @@ The Cedarling Policy Store uses a JSON file named `cedarling_store.json` to stor

1. **Cedar Schema**: The Cedar schema encoded in Base64.
2. **Cedar Policies**: The Cedar policies encoded in Base64.
3. **Trusted Issuers**: Details about the trusted issuers (see [below](#trusted-issuer-schema) for syntax).
3. **Identity Source**: Details about the trusted issuers (see [below](#identity-source-schema) for syntax).

**Note:** The `cedarling_store.json` file is only needed if the bootstrap properties: `CEDARLING_LOCK`; `CEDARLING_POLICY_STORE_URI`; and `CEDARLING_POLICY_STORE_ID` are not set to a local location. If you're fetching the policies remotely, you don't need a `cedarling_store.json` file.

### JSON Schema

The JSON Schema is for the `policy_store.json` defined as follows:
The JSON Schema accepted by cedarling is defined as follows:

```json
{
"cedar_version": "v2.4.7",
"cedar_policies": { ... },
"cedar_schema": "cedar_schema_encoded_in_base64",
"trusted_issuers": [ ... ]
"cedar_version": "v4.0.0",
"policy_stores": {
"name": "TestPolicy",
"description": "Once upon a time there was a Policy, that lived in a Store.",
"some_unique_string_id": {
"policies": { ... },
"schema": { ... },
"identity_source": { ... }
}
}
}

```

- **cedar_version** : (*String*) The version of [Cedar policy](https://docs.cedarpolicy.com/). The protocols of this version will be followed when processing Cedar schema and policies.
- **cedar_policies** : (*Object*) Object containing one or more policy IDs as keys, with their corresponding objects as values. See: [cedar_policies schema](#cedar-policies-schema).
- **cedar_schema** : (*String*) The Cedar schema, encoded in Base64 format.
- **trusted_issuers** : (*Array of [TrustedIssuer](#trusted-issuer-schema)*) List of metadata for Trusted Issuers.
- **policies** : (*Object*) Object containing one or more policy IDs as keys, with their corresponding objects as values. See: [policies schema](#cedar-policies-schema).
- **schema** : (*String* | *Object*) The Cedar Schema. See [schema](#schema) below.
- **identity_source** : (*Object of {unique_id => IdentitySource}(#trusted-issuer-schema)*) List of metadata for Identity Sources.

### `schema`
Either *String* or *Object*, where *Object* is preferred.

Where *Object* - An object with `encoding`, `content_type` and `body` keys. For example:

``` json
"schema": {
"encoding": "none", // can be one of "none" or "base64"
"content_type": "cedar", // can be one of "cedar" or "cedar-json"
"body": "namespace Jans {\ntype Url = {"host": String, "path": String, "protocol": String};..."
}
```
Where *String* - The schema in cedar-json format, encoded as Base64. For example:
``` json
"schema": "cGVybWl0KAogICAgc..."
```

## Cedar Policies Schema

The `cedar_policies` field outlines the Cedar policies that will be used in Cedarling. Multiple policies can be defined, with policy requiring a unique `policy_id`.
The `policies` field describes the Cedar policies that will be used in Cedarling. Multiple policies can be defined, with each policy requiring a `unique_policy_id`.

```json
"cedar_policies": {
"policies": {
"unique_policy_id": {
"cedar_version" : "v2.4.7",
"name": "Policy for Unique Id",
"description": "simple policy example",
"creation_date": "2024-09-20T17:22:39.996050",
"policy_content": "cGVybWl0KAogICAgc..."
"policy_content": { ... },
},
...
}
```

- **unique_policy_id**: (*String*) A uniqe policy ID used to for tracking and auditing purposes.
- **name** : (*String*) A name for the policy
- **description** : (*String*) A brief description of cedar policy
- **creation_date** : (*String*) Policy creating date in `YYYY-MM-DDTHH:MM:SS.ssssss`
- **policy_content** : (*String*) The policy content, encoded in Base64 format.
- **policy_content** : (*String* | *Object*) The Cedar Policy. See [policy_content](#policy_content) below.

### `policy_content`
Either *String* or *Object*, where *Object* is preferred.

Where *Object* - An object with `encoding`, `content_type` and `body` keys. For example:

``` json
"policy_content": {
"encoding": "none", // can be one of "none" or "base64"
djellemah marked this conversation as resolved.
Show resolved Hide resolved
"content_type": "cedar", // ONLY "cedar" for now due to limitations in cedar-policy crate
"body": "permit(\n principal is Jans::User,\n action in [Jans::Action::\"Update\"],\n resource is Jans::Issue\n)when{\n principal.country == resource.country\n};"
}
```
Where *String* - The policy in cedar format, encoded as Base64. For example:
``` json
"policy_content": "cGVybWl0KAogICAgc..."
```

### Example of `cedar_policies`
### Example of `policies`

Here is a non-normative example of the `cedar_policies` field:
Here is a non-normative example of the `policies` field:

```json
"cedar_policies": {
"policies": {
"name": "non-normative",
"description": "An example of the structure for the policies field",
"840da5d85403f35ea76519ed1a18a33989f855bf1cf8": {
"description": "simple policy example",
"cedar_version": "v2.7.4",
"name": "Policy-the-first",
"description": "simple policy example for principal workload",
"creation_date": "2024-09-20T17:22:39.996050",
"policy_content": "cGVybWl0KAogICAgc..."
},
"0fo1kl928Afa0sc9123scma0123891asklajsh1233ab": {
"cedar_version": "v2.7.4",
"name": "Policy-the-second",
"description": "another policy example",
"creation_date": "2024-09-20T18:22:39.192051",
"policy_content": "kJW1bWl0KA0g3CAxa..."
},
"1fo1kl928Afa0sc9123scma0123891asklajsh1233ac": {
"cedar_version": "v2.7.4",
"name": "Policy-the-third",
"description": "another policy example",
"creation_date": "2024-09-20T18:22:39.192051",
"policy_content": {
"encoding": "none",
"content_type" : "cedar",
"body": "permit(...) where {...}"
}
},
"2fo1kl928Afa0sc9123scma0123891asklajsh1233ad": {
"cedar_version": "v2.7.4",
"name": "Policy-the-fourth",
"description": "another policy example",
"creation_date": "2024-09-20T18:22:39.192051",
"policy_content": {
"encoding": "base64",
"content_type" : "cedar",
"body": "kJW1bWl0KA0g3CAxa..."
}
},
...
}
```

## Trusted Issuer Schema
## Identity Source Schema

This record contains the information needed to validate tokens from this issuer:

```json
"trusted_issuers": [
"identity_source": {
"some_unique_id" :
{
"name": "name_of_the_trusted_issuer",
"description": "description_of_the_trusted_issuer",
"openid_configuration_endpoint": "https://<trusted-issuer-hostname>/.well-known/openid-configuration",
"token_metadata": [ ... ]
"name": "name_of_the_trusted_issuer",
"description": "description for the trusted issuer",
"openid_configuration_endpoint": "https://<trusted-issuer-hostname>/.well-known/openid-configuration",
"access_tokens": {
"trusted": true,
"principal_identifier": "",
"role_mapping": "",
},
"id_tokens": {
"trusted": true,
"principal_identifier": "sub",
"role_mapping": "",
},
"userinfo_tokens": {
"trusted": true,
"principal_identifier": "",
"role_mapping": "role",
},
"tx_tokens": {
"trusted": true,
"principal_identifier": "",
"role_mapping": "",
},
}
]
...
}
```

- **name** : (*String*) The name of the trusted issuer.
- **description** : (*String*) A brief description of the trusted issuer, providing context for administrators.
- **openid_configuration_endpoint** : (*String*) The HTTPS URL for the OpenID Connect configuration endpoint (usually found at `/.well-known/openid-configuration`).
- **token_metadata** : (*Array of [TokenMetadata](#token-metadata-schema)*, *optional*) Metadata related to the tokens issued by this issuer.
- **identity_source** : (*Object*, *optional*) Metadata related to the tokens issued by this issuer.

### Token Metadata Schema

```json
{
"type": "access_token"
"user_id": "some_user123",
"trusted": true|false
"principal_identifier": "some_user123",
"role_mapping": "role",
}
```

- **type** : (String, no spaces) The type of token (e.g., Access, ID, Userinfo, Transaction).
- **user_id** : (String) The claim used to create the Cedar entity associated with this token.
- **trusted** : (Boolean) The type of token
- **principal_id** : (String) The claim used to create the Cedar entity associated with this token.
- **role_mapping** : (String, *optional*) The claim used to create a role for the token. The default value of `role_mapping` is `role`. The claim can be string or array of string.

**Note**: Only one token should include the `role_mapping` field in the list of `token_metadata`.
Expand All @@ -120,36 +211,43 @@ Here is a non-normative example of a `cedarling_store.json` file:
```json
{
"cedar_version": "v2.4.7",
"cedar_policies": {
"policies": {
"840da5d85403f35ea76519ed1a18a33989f855bf1cf8": {
"description": "simple policy example",
"creation_date": "2024-09-20T17:22:39.996050",
"policy_content": "cedar_policy_encoded_in_base64"
}
},
"cedar_schema": "cedar_schema_encoded_in_base64",
"trusted_issuers": [
{
"schema": "schema_encoded_in_base64",
"identity_source": {
"08c6c18a654f492adcf3fe069d729b4d9e6bf82605cb" : {
"name": "Google",
"description": "Consumer IDP",
"openid_configuration_endpoint": "https://accounts.google.com/.well-known/openid-configuration",
"token_metadata": [
{
"type": "access_token",
"user_id": "aud"
"identity_source": {
"access_tokens": {
"trusted": true,
"principal_identifier": "",
"role_mapping": "",
},
"id_tokens": {
"trusted": true,
"principal_identifier": "sub",
"role_mapping": "",
},
{
"type": "id_token",
"user_id": "sub"
"userinfo_tokens": {
"trusted": true,
"principal_identifier": "",
"role_mapping": "role",
},
{
"type": "userinfo_token",
"user_id": "email",
"role_mapping": "role"
}
]
"tx_tokens": {
"trusted": true,
"principal_identifier": "",
"role_mapping": "",
},
}
}
]
}
}
```

Expand Down Expand Up @@ -186,7 +284,7 @@ action "Update" appliesTo {

You can extend all of this entites and add your own.

Mandatory entities is: `id_token`, `Role`, `User`, `Access_token`, `Workload`.
Mandatory entities is: `id_token`, `Role`, `User`, `Access_token`, `Workload`.
`Issue` entity and `Update` action are optinal. Is created for example, you can create others for your needs.

`Context` and `Resource` entities you can pass during authorization request and next entites creating based on the JWT tokens:
Expand All @@ -208,3 +306,11 @@ Mandatory entities is: `id_token`, `Role`, `User`, `Access_token`, `Workload`.

- `Workload` - entity based on the `access` JWT token fields.
- ID for entity based in `client_id` field.

## Note on test fixtures

You will notice that test fixtures in the cedarling code base are quite often in yaml rather than in json.

yaml is intended for **cedarling internal use only**.

The rationale is that yaml has excellent support for embedded, indented, multiline string values. That is far easier to read than base64 encoded json strings, and is beneficial for debugging and validation that test cases are correct.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class DisabledLoggingConfig:

@final
class PolicyStoreSource:
def __init__(self, json: Optional[str] = None) -> None: ...
def __init__(self, json: Optional[str] = None, yaml: Optional[str] = None) -> None: ...


@final
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,19 @@ pub struct PolicyStoreSource {
#[pymethods]
impl PolicyStoreSource {
#[new]
#[pyo3(signature = (json=None))]
#[pyo3(signature = (json=None, yaml=None))]
// signature will be extended when will be extended rust `PolicyStoreSource` enum
fn new(json: Option<String>) -> PyResult<Self> {
fn new(json: Option<String>, yaml: Option<String>) -> PyResult<Self> {
let inner =
if let Some(json_val) = json {
Ok(Self {
inner: cedarling::PolicyStoreSource::Json(json_val),
})
cedarling::PolicyStoreSource::Json(json_val)
} else if let Some(yaml_val) = yaml {
cedarling::PolicyStoreSource::Yaml(yaml_val)
} else {
Err(PyValueError::new_err("value not specified"))
}
return Err(PyValueError::new_err("value not specified"))
};

Ok(Self { inner })
}
}

Expand Down
8 changes: 4 additions & 4 deletions jans-cedarling/bindings/cedarling_python/tests/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ def sample_bootstrap_config():
# log_config = DisabledLoggingConfig()

# Create policy source configuration
with open(join(TEST_FILES_PATH, "policy-store_ok.json"),
# NOTE yaml is only used for test fixtures. Real imports use json.
with open(join(TEST_FILES_PATH, "policy-store_ok.yaml"),
djellemah marked this conversation as resolved.
Show resolved Hide resolved
mode="r", encoding="utf8") as f:
policy_raw_json = f.read()
# for now we support only json source
policy_source = PolicyStoreSource(json=policy_raw_json)
policy_raw = f.read()
policy_source = PolicyStoreSource(yaml=policy_raw)

policy_store_config = PolicyStoreConfig(
source=policy_source)
Expand Down
Loading