diff --git a/jans-cedarling/cedarling/Cargo.toml b/jans-cedarling/cedarling/Cargo.toml index a7d921f03c4..02aeca9f6d5 100644 --- a/jans-cedarling/cedarling/Cargo.toml +++ b/jans-cedarling/cedarling/Cargo.toml @@ -26,3 +26,4 @@ test_utils = { workspace = true } rand = "0.8.5" jsonwebkey = { version = "0.3.5", features = ["generate", "jwt-convert"] } mockito = "1.5.0" +serde_yml = "0.0.12" diff --git a/jans-cedarling/cedarling/src/common/cedar_schema.rs b/jans-cedarling/cedarling/src/common/cedar_schema.rs index d28de21bdf3..58b0d6afd99 100644 --- a/jans-cedarling/cedarling/src/common/cedar_schema.rs +++ b/jans-cedarling/cedarling/src/common/cedar_schema.rs @@ -6,31 +6,154 @@ */ pub(crate) use cedar_json::CedarSchemaJson; - pub(crate) mod cedar_json; +/// cedar_schema value which specifies both encoding and content_type +/// +/// encoding is one of none or base64 +/// content_type is one of cedar or cedar-json#[derive(Debug, Clone, serde::Deserialize)] +#[derive(Debug, Clone, serde::Deserialize)] +struct EncodedSchema { + pub encoding : super::Encoding, + pub content_type : super::ContentType, + pub body : String, +} + +/// Intermediate struct to handle both kinds of cedar_schema values. +/// +/// Either +/// "cedar_schema": "cGVybWl0KA..." +/// OR +/// "cedar_schema": { "encoding": "...", "content_type": "...", "body": "permit(...)"}#[derive(Debug, Clone, serde::Deserialize)] +#[derive(Debug, Clone, serde::Deserialize)] +#[serde(untagged)] +enum MaybeEncoded { + Plain(String), + Tagged(EncodedSchema) +} + /// Box that holds the [`cedar_policy::Schema`] and /// JSON representation that is used to create entities from the schema in the policy store. #[derive(Debug, Clone)] -#[allow(dead_code)] pub(crate) struct CedarSchema { pub schema: cedar_policy::Schema, pub json: cedar_json::CedarSchemaJson, } +impl PartialEq for CedarSchema { + fn eq(&self, other: &Self) -> bool { + // Have to check principals, resources, action_groups, entity_types, + // actions. Those can contain duplicates, and are not stored in comparison order. + // So use HashSet to compare them. + use std::collections::HashSet; + + let self_principals = self.schema.principals().collect::>(); + let other_principals = other.schema.principals().collect::>(); + if self_principals != other_principals { + return false + } + + let self_resources = self.schema.resources().collect::>(); + let other_resources = other.schema.resources().collect::>(); + if self_resources != other_resources { + return false + } + + let self_action_groups = self.schema.action_groups().collect::>(); + let other_action_groups = other.schema.action_groups().collect::>(); + if self_action_groups != other_action_groups { + return false + } + + let self_entity_types = self.schema.entity_types().collect::>(); + let other_entity_types = other.schema.entity_types().collect::>(); + if self_entity_types != other_entity_types { + return false + } + + let self_actions = self.schema.actions().collect::>(); + let other_actions = other.schema.actions().collect::>(); + if self_actions != other_actions { + return false + } + + // and this only checks the schema anyway + self.json == other.json + } +} + impl<'de> serde::Deserialize<'de> for CedarSchema { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, + fn deserialize>(deserializer: D) -> Result { - deserialize::parse_cedar_schema(deserializer) + // Read the next thing as either a String or a Map, using the MaybeEncoded enum to distinguish + let encoded_schema = match ::deserialize(deserializer)? { + MaybeEncoded::Plain(body) => EncodedSchema{ + // These are the default if the encoding is not specified. + encoding: super::Encoding::Base64, + content_type: super::ContentType::CedarJson, + body + }, + MaybeEncoded::Tagged(encoded_schema) => encoded_schema, + }; + + let decoded_body = match encoded_schema.encoding { + super::Encoding::None => encoded_schema.body, + super::Encoding::Base64 => { + use base64::prelude::*; + let buf = BASE64_STANDARD.decode(encoded_schema.body).map_err(|err| { + serde::de::Error::custom(format!("{}: {}", deserialize::ParseCedarSchemaSetMessage::Base64, err)) + })?; + String::from_utf8(buf).map_err(|err| { + serde::de::Error::custom(format!("{}: {}", deserialize::ParseCedarSchemaSetMessage::Utf8, err)) + })? + } + }; + + // Need both of these because CedarSchema wants both. + let (schema_fragment, json_string) = match encoded_schema.content_type { + super::ContentType::Cedar => { + // parse cedar policy from the cedar representation + // TODO must log warnings or something + let (schema_fragment, _warning) = cedar_policy::SchemaFragment::from_cedarschema_str(&decoded_body) + .map_err(|err| { + serde::de::Error::custom(format!("{}: {}", deserialize::ParseCedarSchemaSetMessage::Parse, err)) + })?; + + // urgh now recreate the json representation + let json_string = schema_fragment.to_json_string() + .map_err(|err| { + serde::de::Error::custom(format!("{}: {}", deserialize::ParseCedarSchemaSetMessage::CedarSchemaJsonFormat, err)) + })?; + + (schema_fragment, json_string) + } + super::ContentType::CedarJson => { + // parse cedar policy from the json representation + let schema_fragment = cedar_policy::SchemaFragment::from_json_str(&decoded_body) + .map_err(|err| { + serde::de::Error::custom(format!("{}: {}", deserialize::ParseCedarSchemaSetMessage::CedarSchemaJsonFormat, err)) + })?; + (schema_fragment, decoded_body) + } + }; + + // create the schema + let fragment_iter = std::iter::once(schema_fragment); + let schema = cedar_policy::Schema::from_schema_fragments(fragment_iter.into_iter()) + .map_err(|err| { + serde::de::Error::custom(format!("{}: {}", deserialize::ParseCedarSchemaSetMessage::Parse, err)) + })?; + + let json = serde_json::from_str(&json_string) + .map_err(|err| { + serde::de::Error::custom(format!("{}: {}", deserialize::ParseCedarSchemaSetMessage::CedarSchemaJsonFormat, err )) + })?; + + Ok(CedarSchema{schema, json}) } } mod deserialize { - use super::*; - use base64::prelude::*; - #[derive(Debug, thiserror::Error)] pub enum ParseCedarSchemaSetMessage { #[error("unable to decode cedar policy schema base64")] @@ -39,40 +162,8 @@ mod deserialize { CedarSchemaJsonFormat, #[error("unable to parse cedar policy schema json")] Parse, - } - - /// A custom deserializer for Cedar's Schema. - // - // is used to deserialize field `cedar_schema` in `PolicyStore` from base64 and get [`cedar_policy::Schema`] - pub(crate) fn parse_cedar_schema<'de, D>(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let source = ::deserialize(deserializer)?; - let decoded: Vec = BASE64_STANDARD.decode(source.as_str()).map_err(|err| { - serde::de::Error::custom(format!("{}: {}", ParseCedarSchemaSetMessage::Base64, err,)) - })?; - - // parse cedar policy schema to the our structure - let cedar_policy_json: CedarSchemaJson = serde_json::from_reader(decoded.as_slice()) - .map_err(|err| { - serde::de::Error::custom(format!( - "{}: {}", - ParseCedarSchemaSetMessage::CedarSchemaJsonFormat, - err - )) - })?; - - // parse cedar policy schema to the `cedar_policy::Schema` - let cedar_policy_schema = cedar_policy::Schema::from_json_file(decoded.as_slice()) - .map_err(|err| { - serde::de::Error::custom(format!("{}: {}", ParseCedarSchemaSetMessage::Parse, err)) - })?; - - Ok(CedarSchema { - schema: cedar_policy_schema, - json: cedar_policy_json, - }) + #[error("invalid utf8 detected while decoding cedar policy")] + Utf8, } #[cfg(test)] @@ -89,7 +180,46 @@ mod deserialize { include_str!("../../../test_files/policy-store_ok.json"); let policy_result = serde_json::from_str::(POLICY_STORE_RAW); - assert!(policy_result.is_ok()); + assert!(policy_result.is_ok(), "{:?}", policy_result.unwrap_err()); + } + + #[test] + fn test_readable_ok() { + static POLICY_STORE_RAW: &str = + include_str!("../../../test_files/policy-store_readable.json"); + + let policy_result = serde_json::from_str::(POLICY_STORE_RAW); + assert!(policy_result.is_ok(), "{:?}", policy_result.unwrap_err()); + } + + #[test] + fn test_readable_yaml_ok() { + static YAML_POLICY_STORE: &str = include_str!("../../../test_files/policy-store_readable.yaml"); + let yaml_policy_result = serde_yml::from_str::(YAML_POLICY_STORE); + assert!(yaml_policy_result.is_ok(), "{:?}", yaml_policy_result.unwrap_err()); + } + + #[test] + fn test_readable_yaml_identical_readable_json() { + static YAML_POLICY_STORE: &str = include_str!("../../../test_files/policy-store_readable.yaml"); + let yaml_policy_result = serde_yml::from_str::(YAML_POLICY_STORE); + + static JSON_POLICY_STORE: &str = include_str!("../../../test_files/policy-store_readable.json"); + let json_policy_result = serde_yml::from_str::(JSON_POLICY_STORE); + + assert_eq!(yaml_policy_result.unwrap(), json_policy_result.unwrap()); + } + + // In fact this fails because of limitations in cedar_policy::Policy::from_json + // see PolicyContentType + fn test_both_ok() { + static POLICY_STORE_RAW: &str = + include_str!("../../../test_files/policy-store_blobby.json"); + + let policy_result = serde_json::from_str::(POLICY_STORE_RAW); + let err = policy_result.unwrap_err(); + let msg = err.to_string(); + assert!(msg.contains("data did not match any variant of untagged enum MaybeEncoded")); } #[test] @@ -98,10 +228,9 @@ mod deserialize { include_str!("../../../test_files/policy-store_schema_err_base64.json"); let policy_result = serde_json::from_str::(POLICY_STORE_RAW); - assert!(policy_result - .unwrap_err() - .to_string() - .contains(&ParseCedarSchemaSetMessage::Base64.to_string())); + let err = policy_result.unwrap_err(); + let msg = err.to_string(); + assert!(msg.contains(&ParseCedarSchemaSetMessage::Base64.to_string()), "{err:?}"); } #[test] @@ -110,10 +239,9 @@ mod deserialize { include_str!("../../../test_files/policy-store_schema_err_json.json"); let policy_result = serde_json::from_str::(POLICY_STORE_RAW); - assert!(policy_result - .unwrap_err() - .to_string() - .contains(&ParseCedarSchemaSetMessage::CedarSchemaJsonFormat.to_string())); + let err = policy_result.unwrap_err(); + let msg = err.to_string(); + assert!(msg.contains("unable to unmarshal cedar policy schema json"), "{err:?}"); } #[test] diff --git a/jans-cedarling/cedarling/src/common/mod.rs b/jans-cedarling/cedarling/src/common/mod.rs index 5da70e74d98..528e43d997a 100644 --- a/jans-cedarling/cedarling/src/common/mod.rs +++ b/jans-cedarling/cedarling/src/common/mod.rs @@ -12,3 +12,27 @@ pub(crate) mod app_types; pub(crate) mod cedar_schema; pub mod policy_store; + +/// Used for decoding the policy and schema metadata +#[derive(Debug, Clone, serde::Deserialize)] +enum Encoding { + /// indicates that the related value is base64 encoded + #[serde(rename = "base64")] + Base64, + + /// indicates that the related value is not encoded, ie it's just a plain string + #[serde(rename = "none")] + None, +} + +/// Used for decoding the policy and schema metadata +#[derive(Debug, Clone, serde::Deserialize)] +enum ContentType { + /// indicates that the related value is in the cedar policy / schema language + #[serde(rename = "cedar")] + Cedar, + + /// indicates that the related value is in the json representation of the cedar policy / schema language + #[serde(rename = "cedar-json")] + CedarJson +} diff --git a/jans-cedarling/cedarling/src/common/policy_store.rs b/jans-cedarling/cedarling/src/common/policy_store.rs index 811a089de5d..1c3d5f5afc3 100644 --- a/jans-cedarling/cedarling/src/common/policy_store.rs +++ b/jans-cedarling/cedarling/src/common/policy_store.rs @@ -9,7 +9,6 @@ mod test; use super::cedar_schema::CedarSchema; -use base64::prelude::*; use cedar_policy::PolicyId; use semver::Version; use serde::{Deserialize, Deserializer}; @@ -19,7 +18,7 @@ use std::{collections::HashMap, fmt}; /// /// The `PolicyStore` contains the schema and a set of policies encoded in base64, /// which are parsed during deserialization. -#[derive(Debug, Clone, serde::Deserialize)] +#[derive(Debug, Clone, serde::Deserialize, PartialEq)] pub struct PolicyStore { /// The cedar version to use when parsing the schema and policies. #[serde(deserialize_with = "parse_cedar_version")] @@ -27,11 +26,11 @@ pub struct PolicyStore { pub cedar_version: Version, /// Cedar schema - pub cedar_schema: CedarSchema, // currently being loaded from a base64-encoded string + pub cedar_schema: CedarSchema, /// Cedar policy set #[serde(deserialize_with = "parse_cedar_policy")] - pub cedar_policies: cedar_policy::PolicySet, // currently being loaded from a base64-encoded string + pub cedar_policies: cedar_policy::PolicySet, /// An optional list of trusted issuers. /// @@ -45,7 +44,7 @@ pub struct PolicyStore { /// /// This struct includes the issuer's name, description, and the OpenID configuration endpoint /// for discovering issuer-related information. -#[derive(Debug, Clone, Deserialize)] +#[derive(Debug, Clone, Deserialize,PartialEq)] #[allow(dead_code)] pub struct TrustedIssuer { /// The name of the trusted issuer. @@ -100,7 +99,7 @@ where /// /// This struct includes the type of token, the ID of the person associated with the token, /// and an optional role mapping for access control. -#[derive(Debug, Clone, Deserialize)] +#[derive(Debug, Clone, Deserialize, PartialEq)] #[allow(dead_code)] pub struct TokenMetadata { /// The type of token (e.g., Access, ID, Userinfo, Transaction). @@ -114,7 +113,7 @@ pub struct TokenMetadata { pub role_mapping: Option, } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq)] #[allow(dead_code)] pub enum TokenKind { /// Access token used for granting access to resources. @@ -211,13 +210,51 @@ enum ParsePolicySetMessage { CreatePolicySet, } +/// content_type for the policy_content field. +/// +/// Only contains a single member, because as of 31-Oct-2024, cedar-policy 4.2.1 +/// cedar_policy::Policy:from_json does not work with a single policy. +/// +/// NOTE if/when cedar_policy::Policy:from_json gains this ability, this type +/// can be replaced by super::ContentType +#[derive(Debug, Clone, serde::Deserialize)] +enum PolicyContentType { + /// indicates that the related value is in the cedar policy / schema language + #[serde(rename = "cedar")] + Cedar, +} + +/// policy_content value which specifies both encoding and content_type +/// +/// encoding is one of none or base64 +/// content_type is one of cedar or cedar-json +#[derive(Debug, Clone, serde::Deserialize)] +struct EncodedPolicy { + pub encoding : super::Encoding, + pub content_type : PolicyContentType, + pub body : String, +} + +/// Intermediate struct to handler both kinds of policy_content values. +/// +/// Either +/// "policy_content": "cGVybWl0KA..." +/// OR +/// "policy_content": { "encoding": "...", "content_type": "...", "body": "permit(...)"} +#[derive(Debug, Clone, serde::Deserialize)] +#[serde(untagged)] +enum MaybeEncoded { + Plain(String), + Tagged(EncodedPolicy) +} + /// Represents a raw policy entry from the `PolicyStore`. /// /// This is a helper struct used internally for parsing base64-encoded policies. #[derive(Debug, serde::Deserialize)] struct RawPolicy { /// Base64-encoded content of the policy. - pub policy_content: String, + pub policy_content: MaybeEncoded, } /// Custom deserializer for converting base64-encoded policies into a `PolicySet`. @@ -274,19 +311,47 @@ fn parse_single_policy<'de, D>( where D: serde::Deserializer<'de>, { - let decoded = BASE64_STANDARD - .decode(policy_raw.policy_content.as_str()) - .map_err(|err| { - serde::de::Error::custom(format!("{}: {err}", ParsePolicySetMessage::Base64)) - })?; - let decoded_str = String::from_utf8(decoded).map_err(|err| { - serde::de::Error::custom(format!("{}: {err}", ParsePolicySetMessage::String)) - })?; - - let policy = - cedar_policy::Policy::parse(Some(PolicyId::new(id)), decoded_str).map_err(|err| { - serde::de::Error::custom(format!("{}: {err}", ParsePolicySetMessage::HumanReadable)) - })?; + let policy_with_metadata = match policy_raw.policy_content { + // It's a plain string, so assume its cedar inside base64 + MaybeEncoded::Plain(base64_encoded) => EncodedPolicy{ + encoding: super::Encoding::Base64, + content_type: PolicyContentType::Cedar, + body: base64_encoded, + }, + MaybeEncoded::Tagged(policy_with_metadata) => policy_with_metadata, + }; + + let decoded_body = match policy_with_metadata.encoding { + super::Encoding::None => policy_with_metadata.body, + super::Encoding::Base64 => { + use base64::prelude::*; + let buf = BASE64_STANDARD.decode(policy_with_metadata.body).map_err(|err| { + serde::de::Error::custom(format!("{}: {}", ParsePolicySetMessage::Base64, err)) + })?; + String::from_utf8(buf).map_err(|err| { + serde::de::Error::custom(format!("{}: {}", ParsePolicySetMessage::String, err)) + })? + } + }; + + let policy = match policy_with_metadata.content_type { + PolicyContentType::Cedar => { + cedar_policy::Policy::parse(Some(PolicyId::new(id)), decoded_body).map_err(|err| { + serde::de::Error::custom(format!("{}: {err}", ParsePolicySetMessage::HumanReadable)) + })? + } + /* see comments for PolicyContentType + PolicyContentType::CedarJson => { + let body_value : serde_json::Value = serde_json::from_str(&decoded_body).map_err(|err| { + serde::de::Error::custom(format!("{}: {err}", ParsePolicySetMessage::CreatePolicySet)) + })?; + + cedar_policy::Policy::from_json(Some(PolicyId::new(id)), body_value).map_err(|err| { + serde::de::Error::custom(format!("{}: {err}", ParsePolicySetMessage::CreatePolicySet)) + })? + }, + */ + }; Ok(policy) } diff --git a/jans-cedarling/test_files/policy-store_blobby.json b/jans-cedarling/test_files/policy-store_blobby.json new file mode 100644 index 00000000000..f4cb7b7dc87 --- /dev/null +++ b/jans-cedarling/test_files/policy-store_blobby.json @@ -0,0 +1,28 @@ +{ + "cedar_version": "v2.4.7", + "cedar_policies": { + "840da5d85403f35ea76519ed1a18a33989f855bf1cf8": { + "description": "simple policy example for pricipal workload", + "creation_date": "2024-09-20T17:22:39.996050", + "policy_content": { + "encoding": "base64", + "content_type": "cedar-json", + "body":"ewogICAgInN0YXRpY1BvbGljaWVzIjogewogICAgICAgICJwb2xpY3kwIjogewogICAgICAgICAgICAiYWN0aW9uIjogewogICAgICAgICAgICAgICAgImVudGl0eSI6IHsKICAgICAgICAgICAgICAgICAgICAiaWQiOiAiVXBkYXRlIiwKICAgICAgICAgICAgICAgICAgICAidHlwZSI6ICJKYW5zOjpBY3Rpb24iCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgIm9wIjogImluIgogICAgICAgICAgICB9LAogICAgICAgICAgICAiY29uZGl0aW9ucyI6IFsKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAiYm9keSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgIj09IjogewogICAgICAgICAgICAgICAgICAgICAgICAgICAgImxlZnQiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIi4iOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJhdHRyIjogIm9yZ19pZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJsZWZ0IjogewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlZhciI6ICJwcmluY2lwYWwiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgInJpZ2h0IjogewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIuIjogewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYXR0ciI6ICJvcmdfaWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibGVmdCI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJWYXIiOiAicmVzb3VyY2UiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICJraW5kIjogIndoZW4iCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIF0sCiAgICAgICAgICAgICJlZmZlY3QiOiAicGVybWl0IiwKICAgICAgICAgICAgInByaW5jaXBhbCI6IHsKICAgICAgICAgICAgICAgICJlbnRpdHlfdHlwZSI6ICJKYW5zOjpXb3JrbG9hZCIsCiAgICAgICAgICAgICAgICAib3AiOiAiaXMiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJyZXNvdXJjZSI6IHsKICAgICAgICAgICAgICAgICJlbnRpdHlfdHlwZSI6ICJKYW5zOjpJc3N1ZSIsCiAgICAgICAgICAgICAgICAib3AiOiAiaXMiCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9LAogICAgInRlbXBsYXRlTGlua3MiOiBbXSwKICAgICJ0ZW1wbGF0ZXMiOiB7fQp9" + } + }, + "444da5d85403f35ea76519ed1a18a33989f855bf1cf8": { + "description": "simple policy example for pricipal user", + "creation_date": "2024-09-20T17:22:39.996050", + "policy_content": { + "encoding": "none", + "content_type": "cedar", + "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};" + } + } + }, + "cedar_schema": { + "encoding": "none", + "content_type": "cedar", + "body": "namespace Jans {\ntype Url = {\"host\": String, \"path\": String, \"protocol\": String};\nentity Access_token = {\"aud\": String, \"exp\": Long, \"iat\": Long, \"iss\": TrustedIssuer, \"jti\": String};\nentity Issue = {\"country\": String, \"org_id\": String};\nentity TrustedIssuer = {\"issuer_entity_id\": Url};\nentity User = {\"country\": String, \"email\": String, \"sub\": String, \"username\": String};\nentity Workload = {\"client_id\": String, \"iss\": TrustedIssuer, \"name\": String, \"org_id\": String};\nentity id_token = {\"acr\": String, \"amr\": String, \"aud\": String, \"exp\": Long, \"iat\": Long, \"iss\": TrustedIssuer, \"jti\": String, \"sub\": String};\naction \"Update\" appliesTo {\n principal: [Workload, User],\n resource: [Issue],\n context: {}\n};\n}\n" + } +} diff --git a/jans-cedarling/test_files/policy-store_readable.json b/jans-cedarling/test_files/policy-store_readable.json new file mode 100644 index 00000000000..291a8b39b93 --- /dev/null +++ b/jans-cedarling/test_files/policy-store_readable.json @@ -0,0 +1,28 @@ +{ + "cedar_version": "v2.4.7", + "cedar_policies": { + "840da5d85403f35ea76519ed1a18a33989f855bf1cf8": { + "description": "simple policy example for pricipal workload", + "creation_date": "2024-09-20T17:22:39.996050", + "policy_content": { + "encoding": "none", + "content_type": "cedar", + "body":"permit(\n principal is Jans::Workload,\n action in [Jans::Action::\"Update\"],\n resource is Jans::Issue\n)when{\n principal.org_id == resource.org_id\n};" + } + }, + "444da5d85403f35ea76519ed1a18a33989f855bf1cf8": { + "description": "simple policy example for pricipal user", + "creation_date": "2024-09-20T17:22:39.996050", + "policy_content": { + "encoding": "none", + "content_type": "cedar", + "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};" + } + } + }, + "cedar_schema": { + "encoding": "none", + "content_type": "cedar", + "body": "namespace Jans {\ntype Url = {\"host\": String, \"path\": String, \"protocol\": String};\nentity Access_token = {\"aud\": String, \"exp\": Long, \"iat\": Long, \"iss\": TrustedIssuer, \"jti\": String};\nentity Issue = {\"country\": String, \"org_id\": String};\nentity TrustedIssuer = {\"issuer_entity_id\": Url};\nentity User = {\"country\": String, \"email\": String, \"sub\": String, \"username\": String};\nentity Workload = {\"client_id\": String, \"iss\": TrustedIssuer, \"name\": String, \"org_id\": String};\nentity id_token = {\"acr\": String, \"amr\": String, \"aud\": String, \"exp\": Long, \"iat\": Long, \"iss\": TrustedIssuer, \"jti\": String, \"sub\": String};\naction \"Update\" appliesTo {\n principal: [Workload, User],\n resource: [Issue],\n context: {}\n};\n}\n" + } +} diff --git a/jans-cedarling/test_files/policy-store_readable.yaml b/jans-cedarling/test_files/policy-store_readable.yaml new file mode 100644 index 00000000000..1c1734dd582 --- /dev/null +++ b/jans-cedarling/test_files/policy-store_readable.yaml @@ -0,0 +1,48 @@ +cedar_version: v2.4.7 +cedar_policies: + 840da5d85403f35ea76519ed1a18a33989f855bf1cf8: + description: simple policy example for pricipal workload + creation_date: '2024-09-20T17:22:39.996050' + policy_content: + encoding: none + content_type: cedar + body: |- + 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 pricipal user + creation_date: '2024-09-20T17:22:39.996050' + policy_content: + encoding: none + content_type: cedar + body: |- + permit( + principal is Jans::User, + action in [Jans::Action::"Update"], + resource is Jans::Issue + )when{ + principal.country == resource.country + }; +cedar_schema: + encoding: none + content_type: cedar + body: | + 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 TrustedIssuer = {"issuer_entity_id": Url}; + entity User = {"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], + resource: [Issue], + context: {} + }; + }