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): update PolicyStore parser to support agama-lab generated policies #10098

Open
wants to merge 36 commits into
base: main
Choose a base branch
from

Conversation

rmarinn
Copy link
Contributor

@rmarinn rmarinn commented Nov 10, 2024

Prepare


Description

This PR enhances the PolicyStore struct to support policy stores generated by the Agama Lab Policy Designer, enabling seamless loading of policies in both JSON and YAML formats.

New Features:

  • JSON Loading: Use PolicyStore::load_from_json(json_str) to load policy stores from JSON.
  • YAML Loading: Use PolicyStore::load_from_yaml(yaml_str) to load policy stores from YAML.

Target issue

The issue addressed by this PR involves users being unable to directly use policy stores exported from Agama Lab's Policy Designer. This enhancement enables seamless integration of Agama-generated policies (see Updated JSON Policy Store Schema).

closes #10038

Implementation Details

This update introduces a revised schema for the PolicyStore, including updates to trusted_issuers and TokenEntityMetadata. The following sections provide detailed information on the changes.

Updated JSON Policy Store Schema

The JSON structure has been updated to include additional fields and configurations:

{
    "cedar_version": "v4.0.0",
    "policy_stores": {
            "some_random_id": {
                "name": "policy name",
                "description": "a brief description about the policy",
                "policies": {...}
                "trusted_issuers": {...},
                "schema": "base_64_encoded_json_cedar_schema"
            }
    },
}
Updated trusted_issuers schema
"trusted_issuers": {
  "some_unique_id" : {
    "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,
      "principlal_identifier": "jti",
      ...
    },
    "id_tokens": { ... },
    "userinfo_tokens": { ... },
    "tx_tokens": { ... },
  },
  ...
}
  • Note: access_tokens now includes new fields like trusted and principal_identifier alongside existing fields.
Updated Token Entity Metadata schema (used for: access_tokens, id_tokens, usrinfo_tokens, and tx_tokens).
{
  "token_type": {
    "user_id": "<field name in token (e.g., 'email', 'sub', 'uid', etc.) or '' if not used>",
    "role_mapping": "<field for role assignment (e.g., 'role', 'memberOf', etc.) or '' if not used>",
    "claim_mapping": {
      "mapping_target": {
        "parser": "<type of parser ('regex' or 'json')>",
        "type": "<type identifier (e.g., 'Acme::Email')>",
        "...": "Additional configurations specific to the parser"
      },
    },
  }
}
Updated YAML Policy Store Schema

For easier readability and authoring, the YAML format has been simplified:

cedar_version: v4.0.0
name: PolicyStoreOk
description: A test policy store where everything is fine.
policies:
  840da5d85403f35ea76519ed1a18a33989f855bf1cf8:
    description: simple policy example for principal workload
    creation_date: '2024-09-20T17:22:39.996050'
    policy_content: |-
      permit(
          principal is Jans::Workload,
          action in [Jans::Action::"Update"],
          resource is Jans::Issue
      )when{
          principal.org_id == resource.org_id
      };
  444da5d85403f35ea76519ed1a18a33989f855bf1cf8:
    description: simple policy example for principal user
    creation_date: '2024-09-20T17:22:39.996050'
    policy_content: |-
      permit(
          principal is Jans::User,
          action in [Jans::Action::"Update"],
          resource is Jans::Issue
      )when{
          principal.country == resource.country
      };
schema: |-
  namespace Jans {
    type Url = {"host": String, "path": String, "protocol": String};
    entity Access_token = {"aud": String, "exp": Long, "iat": Long, "iss": TrustedIssuer, "jti": String};
    entity Issue = {"country": String, "org_id": String};
    entity Role;
    entity TrustedIssuer = {"issuer_entity_id": Url};
    entity User in [Role] = {"country": String, "email": String, "sub": String, "username": String};
    entity Workload = {"client_id": String, "iss": TrustedIssuer, "name": String, "org_id": String};
    entity id_token = {"acr": String, "amr": String, "aud": String, "exp": Long, "iat": Long, "iss": TrustedIssuer, "jti": String, "sub": String};
    action "Update" appliesTo {

      principal: [Workload, User, Role],
      resource: [Issue],
      context: {}
    };
  }
trusted_issuers:
  IDP1:
    name: 'Google'
    description: 'Consumer IDP'
    openid_configuration_endpoint: 'https://accounts.google.com/.well-known/openid-configuration'
    access_tokens:
        trusted: true
        principal_identifier: jti
    id_tokens:
        user_id: 'sub'
        role_mapping: 'role'
        claim_mapping: {}
  • Default values are implemented for missing fields.
Updated Rust Implementation

The PolicyStore struct and related methods have been refactored to support the new schema:

pub struct PolicyStore {
    pub name: Option<String>,
    pub description: Option<String>,
    pub cedar_version: Option<Version>,
    pub policies: HashMap<String, PolicyContent>,
    pub cedar_schema: CedarSchema,
    pub trusted_issuers: HashMap<String, TrustedIssuerMetadata>,
    policy_set: PolicySet,
}

impl PolicyStore {
    pub fn load_from_json(json: &str) -> Result<Self, LoadPolicyStoreError> {
        let json_store = serde_json::from_str::<PolicyStoreJson>(json)
            .map_err(LoadFromJsonError::Deserialization)?;
        json_store.try_into().map_err(LoadPolicyStoreError::Json)
    }
    pub fn load_from_yaml(yaml: &str) -> Result<Self, LoadPolicyStoreError> {
        let yaml_store = serde_yml::from_str::<PolicyStoreYaml>(yaml)
            .map_err(LoadFromYamlError::Deserialization)?;
        Ok(yaml_store.into())
    }

    pub fn policy_set(&self) -> &PolicySet {
        &self.policy_set
    }
}
Testing and Validation
  • Unit Tests: Added tests for JSON and YAML loading to ensure the new functionality works correctly.
  • Integration Tests: Tested compatibility with policies exported from Agama Lab Policy Designer.

Test and Document the changes

  • Static code analysis has been run locally and issues have been fixed
  • Relevant unit and integration tests have been added/updated
  • Relevant documentation has been updated if any (i.e. user guides, installation and configuration guides, technical design docs etc)

Please check the below before submitting your PR. The PR will not be merged if there are no commits that start with docs: to indicate documentation changes or if the below checklist is not selected.

  • I confirm that there is no impact on the docs due to the code changes in this PR.

- implement a `ClaimMapping` struct for the new `claim_mapping` field in
  the policy store
- implement deserialize for the `ClaimMapping` struct

Signed-off-by: rmarinn <[email protected]>
- implement `TokenEntityMetada` struct
- implement `Deserialize` for `TokenEntityMetadata`

Signed-off-by: rmarinn <[email protected]>
- implement new struct TrustedIssuerMetadata
- implement Deserialize for TrustedIssuerMetadata

Signed-off-by: rmarinn <[email protected]>
- Implement AgamaPolicyStore struct.
- Implement Deserialize for AgamaPolicyStore struct.

Signed-off-by: rmarinn <[email protected]>
- change the type of AgamaPolicyStore.cedar_schema from
  cedar_policy::Schema to CedarSchema to make it compatibale with the
  existsing implementation

Signed-off-by: rmarinn <[email protected]>
- update the token_metadata implementation in the Cerdarling PolicyStore
  to support the new schema.

Signed-off-by: rmarinn <[email protected]>
- remove old implementation for IdentitySource struct and related
  implementations. The new implementation, TrustedIssuerMetadata, has
  now been implementd with the main policy store.

Signed-off-by: rmarinn <[email protected]>
@rmarinn rmarinn added the comp-jans-cedarling Touching folder /jans-cedarling label Nov 10, 2024
@rmarinn rmarinn self-assigned this Nov 10, 2024
Copy link

dryrunsecurity bot commented Nov 10, 2024

DryRun Security Summary

The provided code changes focus on improving the security and reliability of the Cedarling application, including updates to the policy store management, JWT token validation, and overall application configuration.

Expand for full summary

Summary:

The provided code changes cover a wide range of updates to the Cedarling application, with a focus on improving the security and reliability of the policy store management, JWT token validation, and overall application configuration. The changes include:

  1. Refactoring the policy store implementation to support loading from both JSON and YAML formats, with enhanced error handling and input validation.
  2. Updating the JWT service to use the more comprehensive TrustedIssuerMetadata struct, improving the handling of trusted issuers and token validation.
  3. Adding comprehensive test suites to validate the behavior of the JWT service, including handling of missing claims, invalid signatures, expired tokens, and other potential security issues.
  4. Restructuring the policy store configuration to include a new trusted_issuers section, allowing for better integration with external identity providers and more robust token mapping.
  5. Improving the error handling and input validation throughout the codebase, reducing the risk of potential security vulnerabilities.

Files Changed:

  • jans-cedarling/cedarling/src/authz/mod.rs: Updates the authorization logic to use the more efficient policy_set() method instead of cedar_policies.
  • jans-cedarling/bindings/cedarling_python/tests/test_policy_store.py: Adds new test cases to handle various error scenarios when loading the policy store from different file formats.
  • jans-cedarling/cedarling/src/authz/entities/mod.rs: Defines the creation of entities for different token types, including handling of role mapping.
  • docs/cedarling/cedarling-policy-store.md: Describes the new policy store structure, including support for multiple policy stores and detailed configuration for trusted issuers and token entity metadata.
  • jans-cedarling/cedarling/src/common/cedar_schema.rs: Implements custom deserialization for the CedarSchema struct, handling different input formats.
  • jans-cedarling/cedarling/src/common/policy_store/claim_mapping.rs: Introduces a custom deserialization implementation for the ClaimMapping enum, improving the handling of claim mapping data.
  • jans-cedarling/cedarling/src/common/policy_store/json_store.rs: Implements the JSON-based policy store, including decoding of Base64-encoded policy and schema data.
  • jans-cedarling/cedarling/src/common/policy_store.rs: Significant refactoring and restructuring of the PolicyStore module, improving modularity and security-related features.
  • jans-cedarling/cedarling/src/common/policy_store/token_entity_metadata.rs: Defines the TokenEntityMetadata struct, which is used to store metadata associated with token entities.
  • jans-cedarling/cedarling/src/common/policy_store/trusted_issuer_metadata.rs: Implements the TrustedIssuerMetadata struct, which contains information about trusted issuers of JWT tokens.
  • jans-cedarling/cedarling/src/common/policy_store/yaml_store.rs: Implements the YAML-based policy store, including parsing of human-readable Cedar policies and schema.
  • jans-cedarling/cedarling/src/common/policy_store/test.rs: Adds comprehensive test cases for handling various error scenarios when loading the policy store.
  • jans-cedarling/cedarling/src/init/service_config.rs: Updates the service configuration to simplify the handling of trusted issuers and OpenID configurations.
  • jans-cedarling/cedarling/src/init/policy_store.rs: Simplifies the policy store loading process and improves error handling.
  • jans-cedarling/cedarling/src/jwt/jwt_service_config.rs: Renames the TrustedIssuer type to TrustedIssuerMetadata and updates the associated structures.
  • jans-cedarling/cedarling/src/jwt/decoding_strategy.rs: Implements the JWT decoding strategies, including validation using a KeyService and supported algorithms.
  • jans-cedarling/cedarling/src/jwt/mod.rs: Updates the usage of the TrustedIssuer struct to the `Tru

Code Analysis

We ran 9 analyzers against 30 files and 0 analyzers had findings. 9 analyzers had no findings.

Riskiness

🟢 Risk threshold not exceeded.

View PR in the DryRun Dashboard.

@mo-auto mo-auto added area-documentation Documentation needs to change as part of issue or PR comp-docs Touching folder /docs kind-feature Issue or PR is a new feature request labels Nov 10, 2024
nynymike
nynymike previously approved these changes Nov 11, 2024
@rmarinn
Copy link
Contributor Author

rmarinn commented Nov 11, 2024

please don't approve merge yet, this is still a work in progress. i just made this so i could close the other PR.

- Simplify YAML test files by removing the need for
  a top-level `policy_store` ID
- Ensure YAML test files exclusively contain human-readable Cedar code;
  base64-encoded schemas are now only used for JSON test files.
- Pending: Replace the existing implementation with the new parser.

Signed-off-by: rmarinn <[email protected]>
- split the parsing for TokenEntityMetadata into separate functions per
  field for easier unit-testing

Signed-off-by: rmarinn <[email protected]>
- add test for parsing JSON into TokenEntityMetadata
- add test for parsing YAML into TokenEntityMetadata

Signed-off-by: rmarinn <[email protected]>
- implement parsing into default for missing fields in
  TrustedIssuerMetadata

Signed-off-by: rmarinn <[email protected]>
- Refactor deserialization logic to utilize existing helper functions.

Signed-off-by: rmarinn <[email protected]>
- rename AgamaPolicyStore to PolicySource
- move PolicySouceJson into it's own file
- move PolicySouceYaml into it's own file

Signed-off-by: rmarinn <[email protected]>
- moved a test file to the /test_files directory

Signed-off-by: rmarinn <[email protected]>
@rmarinn rmarinn changed the title feat(jans-cedarling): implement parser for agama-lab generated policies feat(jans-cedarling): update PolicyStore parser to support agama-lab generated policies Nov 13, 2024
@rmarinn rmarinn marked this pull request as ready for review November 13, 2024 09:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-documentation Documentation needs to change as part of issue or PR comp-docs Touching folder /docs comp-jans-cedarling Touching folder /jans-cedarling kind-feature Issue or PR is a new feature request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

fix(cedarling): Make cedarling Policy Store compatible with Agama Lab
3 participants