From 28fd705f538791c1a2ff084e882f47d6888b2477 Mon Sep 17 00:00:00 2001 From: shaobo-he-aws <130499339+shaobo-he-aws@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:40:52 -0800 Subject: [PATCH] Update release/4.2.x (#253) Signed-off-by: Felix Zheng Signed-off-by: dependabot[bot] Signed-off-by: Shaobo He Co-authored-by: Mark Creamer Co-authored-by: Felix Zheng <37223155+felixzheng98@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- CedarJava/build.gradle | 44 ++++++++++--------- .../formatter/PolicyFormatter.java | 4 ++ .../cedarpolicy/model/formatter/Config.java | 22 ++++++++++ .../com/cedarpolicy/PolicyFormatterTests.java | 27 ++++++++++++ .../formatted_policy_custom_config.cedar | 6 +++ .../test/resources/malformed_policy_set.cedar | 2 +- .../test/resources/unformatted_policy.cedar | 2 +- CedarJavaFFI/src/interface.rs | 25 +++++++++-- CedarJavaFFI/src/objects.rs | 34 ++++++++++++++ 9 files changed, 140 insertions(+), 26 deletions(-) create mode 100644 CedarJava/src/main/java/com/cedarpolicy/model/formatter/Config.java create mode 100644 CedarJava/src/test/resources/formatted_policy_custom_config.cedar diff --git a/CedarJava/build.gradle b/CedarJava/build.gradle index bd8730b..28145cc 100644 --- a/CedarJava/build.gradle +++ b/CedarJava/build.gradle @@ -5,7 +5,7 @@ buildscript { } } dependencies { - classpath "com.github.spotbugs.snom:spotbugs-gradle-plugin:6.0.24" + classpath "com.github.spotbugs.snom:spotbugs-gradle-plugin:6.0.26" classpath "gradle.plugin.com.github.sherter.google-java-format:google-java-format-gradle-plugin:0.9" } } @@ -78,14 +78,14 @@ configurations { dependencies { // Do not upgrade to Jackson 3.x without addressing stack overflow issues in ValueDeserializer // The upgrade should be reviewed by AppSec - implementation 'com.fasterxml.jackson.core:jackson-databind:2.18.0' - implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.0' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.18.1' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.1' implementation 'com.fizzed:jne:4.1.1' implementation 'com.google.guava:guava:33.3.1-jre' compileOnly 'com.github.spotbugs:spotbugs-annotations:4.8.6' testImplementation 'net.jqwik:jqwik:1.9.1' - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.2' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.2' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.3' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.3' } def ffiDir = '../CedarJavaFFI' @@ -107,37 +107,39 @@ def rustJavaTargets = [ 'x86_64-unknown-linux-gnu' : 'linux/x86_64' ] -tasks.register('installCargoZigbuild', Exec) { - group 'Build' - description 'Installs Cargo Zigbuild for Rust compilation.' +def RustVersion = '1.81' - commandLine 'cargo', 'install', 'cargo-zigbuild@0.19.3' +tasks.register('installRequiredRustVersion', Exec) { + group 'Build' + description 'Install required Rust version.' + commandLine 'rustup', 'install', RustVersion } -tasks.register('installRustTargets') { - dependsOn('installCargoZigbuild') +tasks.register('installCargoZigbuild', Exec) { + dependsOn('installRequiredRustVersion') group 'Build' - description 'Installs Rust platform build targets.' + description 'Installs Cargo Zigbuild for Rust compilation.' - doLast { - rustLibraryTargets.keySet().forEach { rustTarget -> - exec { - commandLine 'rustup', 'target', 'add', rustTarget - } - } - } + commandLine 'cargo', '+' + RustVersion, 'install', 'cargo-zigbuild@0.19.3' } tasks.register('compileFFI') { - dependsOn('installRustTargets') + dependsOn('installCargoZigbuild') group 'Build' description 'Compiles Foreign Function Interface libraries.' + exec { + workingDir = ffiDir + commandLine 'rustup', 'override', 'set', RustVersion + } doLast { rustLibraryTargets.forEach { rustTarget, libraryFile -> + exec { + commandLine 'rustup', 'target', 'add', rustTarget, '--toolchain', RustVersion + } exec { workingDir = ffiDir - commandLine 'cargo', 'zigbuild', '--features', 'partial-eval', '--release', '--target', rustTarget + commandLine 'cargo', '+' + RustVersion, 'zigbuild', '--features', 'partial-eval', '--release', '--target', rustTarget } def sourcePath = "${ffiDir}/target/${rustTarget}/release/${libraryFile}" diff --git a/CedarJava/src/main/java/com/cedarpolicy/formatter/PolicyFormatter.java b/CedarJava/src/main/java/com/cedarpolicy/formatter/PolicyFormatter.java index afd3ae4..2c4f1d1 100644 --- a/CedarJava/src/main/java/com/cedarpolicy/formatter/PolicyFormatter.java +++ b/CedarJava/src/main/java/com/cedarpolicy/formatter/PolicyFormatter.java @@ -2,6 +2,7 @@ import com.cedarpolicy.loader.LibraryLoader; import com.cedarpolicy.model.exception.InternalException; +import com.cedarpolicy.model.formatter.Config; public final class PolicyFormatter { @@ -14,4 +15,7 @@ private PolicyFormatter() { public static native String policiesStrToPretty(String policies) throws InternalException, NullPointerException; + + public static native String policiesStrToPrettyWithConfig(String policies, Config config) + throws InternalException, NullPointerException; } diff --git a/CedarJava/src/main/java/com/cedarpolicy/model/formatter/Config.java b/CedarJava/src/main/java/com/cedarpolicy/model/formatter/Config.java new file mode 100644 index 0000000..3fc20e7 --- /dev/null +++ b/CedarJava/src/main/java/com/cedarpolicy/model/formatter/Config.java @@ -0,0 +1,22 @@ +package com.cedarpolicy.model.formatter; + +public class Config { + + private final int lineWidth; + private final int indentWidth; + + public Config(int lineWidth, int indentWidth) { + this.lineWidth = lineWidth; + this.indentWidth = indentWidth; + } + + @SuppressWarnings("unused") + public int getLineWidth() { + return lineWidth; + } + + @SuppressWarnings("unused") + public int getIndentWidth() { + return indentWidth; + } +} diff --git a/CedarJava/src/test/java/com/cedarpolicy/PolicyFormatterTests.java b/CedarJava/src/test/java/com/cedarpolicy/PolicyFormatterTests.java index abac4d1..ec6ef0d 100644 --- a/CedarJava/src/test/java/com/cedarpolicy/PolicyFormatterTests.java +++ b/CedarJava/src/test/java/com/cedarpolicy/PolicyFormatterTests.java @@ -2,6 +2,7 @@ import com.cedarpolicy.formatter.PolicyFormatter; import com.cedarpolicy.model.exception.InternalException; +import com.cedarpolicy.model.formatter.Config; import java.nio.file.Files; import java.nio.file.Path; import org.junit.jupiter.api.Test; @@ -37,4 +38,30 @@ public void testPoliciesStrToPrettyMalformedCedarPolicy() throws Exception { public void testPoliciesStrToPrettyNullSafety() { assertThrows(NullPointerException.class, () -> PolicyFormatter.policiesStrToPretty(null)); } + + @Test + public void testPoliciesStrToPrettyWithConfigNullSafety() throws Exception { + String cedarPolicy = Files.readString(Path.of(TEST_RESOURCES_DIR + "formatted_policy.cedar")); + + assertThrows(NullPointerException.class, + () -> PolicyFormatter.policiesStrToPrettyWithConfig(null, null)); + + assertThrows(NullPointerException.class, + () -> PolicyFormatter.policiesStrToPrettyWithConfig(cedarPolicy, null)); + + assertThrows(NullPointerException.class, + () -> PolicyFormatter.policiesStrToPrettyWithConfig(null, new Config(120, 4))); + } + + @Test + public void testPoliciesStrToPrettyWithConfig() throws Exception { + String unformattedCedarPolicy = Files.readString( + Path.of(TEST_RESOURCES_DIR + "unformatted_policy.cedar")); + + String formattedCedarPolicyWithCustomConfig = Files.readString( + Path.of(TEST_RESOURCES_DIR + "formatted_policy_custom_config.cedar")); + + assertEquals(formattedCedarPolicyWithCustomConfig, + PolicyFormatter.policiesStrToPrettyWithConfig(unformattedCedarPolicy, new Config(120, 4))); + } } diff --git a/CedarJava/src/test/resources/formatted_policy_custom_config.cedar b/CedarJava/src/test/resources/formatted_policy_custom_config.cedar new file mode 100644 index 0000000..1b940bc --- /dev/null +++ b/CedarJava/src/test/resources/formatted_policy_custom_config.cedar @@ -0,0 +1,6 @@ +permit ( + principal, + action == Action::"update", + resource +) +when { resource.owner == principal }; diff --git a/CedarJava/src/test/resources/malformed_policy_set.cedar b/CedarJava/src/test/resources/malformed_policy_set.cedar index 8097238..7325888 100644 --- a/CedarJava/src/test/resources/malformed_policy_set.cedar +++ b/CedarJava/src/test/resources/malformed_policy_set.cedar @@ -10,4 +10,4 @@ forbid ( principal == User::"Liam", action, resource = Photo::"Husky.jpg" -); \ No newline at end of file +); diff --git a/CedarJava/src/test/resources/unformatted_policy.cedar b/CedarJava/src/test/resources/unformatted_policy.cedar index 35121eb..7897777 100644 --- a/CedarJava/src/test/resources/unformatted_policy.cedar +++ b/CedarJava/src/test/resources/unformatted_policy.cedar @@ -3,4 +3,4 @@ permit( action == Action::"update", resource -) when {resource.owner == principal}; \ No newline at end of file +) when {resource.owner == principal}; diff --git a/CedarJavaFFI/src/interface.rs b/CedarJavaFFI/src/interface.rs index 6a6fff4..419d9af 100644 --- a/CedarJavaFFI/src/interface.rs +++ b/CedarJavaFFI/src/interface.rs @@ -32,6 +32,7 @@ use serde::{Deserialize, Serialize}; use serde_json::{from_str, Value}; use std::{error::Error, str::FromStr, thread}; +use crate::objects::JFormatterConfig; use crate::{ answer::Answer, jset::Set, @@ -537,7 +538,20 @@ pub fn policiesStrToPretty<'a>( _: JClass, policies_jstr: JString<'a>, ) -> jvalue { - match policies_str_to_pretty_internal(&mut env, policies_jstr) { + match policies_str_to_pretty_internal(&mut env, policies_jstr, None) { + Ok(v) => v.as_jni(), + Err(e) => jni_failed(&mut env, e.as_ref()), + } +} + +#[jni_fn("com.cedarpolicy.formatter.PolicyFormatter")] +pub fn policiesStrToPrettyWithConfig<'a>( + mut env: JNIEnv<'a>, + _: JClass, + policies_jstr: JString<'a>, + config_obj: JObject<'a>, +) -> jvalue { + match policies_str_to_pretty_internal(&mut env, policies_jstr, Some(config_obj)) { Ok(v) => v.as_jni(), Err(e) => jni_failed(&mut env, e.as_ref()), } @@ -546,11 +560,16 @@ pub fn policiesStrToPretty<'a>( fn policies_str_to_pretty_internal<'a>( env: &mut JNIEnv<'a>, policies_jstr: JString<'a>, + config_obj: Option>, ) -> Result> { - if policies_jstr.is_null() { + if policies_jstr.is_null() || config_obj.as_ref().is_some_and(|obj| obj.is_null()) { raise_npe(env) } else { - let config = Config::default(); + let config = if let Some(obj) = config_obj { + JFormatterConfig::cast(env, obj)?.get_rust_repr() + } else { + Config::default() + }; let policies_str = String::from(env.get_string(&policies_jstr)?); match policies_str_to_pretty(&policies_str, &config) { Ok(formatted_policies) => Ok(env.new_string(formatted_policies)?.into()), diff --git a/CedarJavaFFI/src/objects.rs b/CedarJavaFFI/src/objects.rs index 8d20a74..5aa24ce 100644 --- a/CedarJavaFFI/src/objects.rs +++ b/CedarJavaFFI/src/objects.rs @@ -21,6 +21,7 @@ use crate::{ use std::{marker::PhantomData, str::FromStr}; use cedar_policy::{EntityId, EntityTypeName, EntityUid}; +use cedar_policy_formatter::Config; use jni::{ objects::{JObject, JString, JValueGen, JValueOwned}, sys::jvalue, @@ -368,3 +369,36 @@ impl<'a> AsRef> for JPolicy<'a> { &self.obj } } + +pub struct JFormatterConfig<'a> { + obj: JObject<'a>, + formatter_config: Config, +} + +impl<'a> JFormatterConfig<'a> { + pub fn get_rust_repr(&self) -> Config { + self.formatter_config.clone() + } +} + +impl<'a> AsRef> for JFormatterConfig<'a> { + fn as_ref(&self) -> &JObject<'a> { + &self.obj + } +} + +impl<'a> Object<'a> for JFormatterConfig<'a> { + fn cast(env: &mut JNIEnv<'a>, obj: JObject<'a>) -> Result { + assert_is_class(env, &obj, "com/cedarpolicy/model/formatter/Config")?; + let line_width_jint = env.call_method(&obj, "getLineWidth", "()I", &[])?.i()?; + let indent_width_jint = env.call_method(&obj, "getIndentWidth", "()I", &[])?.i()?; + let formatter_config = Config { + line_width: usize::try_from(line_width_jint)?, + indent_width: isize::try_from(indent_width_jint)?, + }; + Ok(Self { + obj, + formatter_config, + }) + } +}