├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ └── feature_request.yml ├── dependabot.yml └── workflows │ ├── ci.yml │ └── run_cedar_java_reusable.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CedarJava ├── .gitignore ├── CHANGELOG.md ├── DIFFERENCES_FROM_RUST.md ├── LICENSE ├── README.md ├── build.gradle ├── config │ └── checkstyle │ │ ├── checkstyle.xml │ │ └── suppressions.xml ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ ├── junit-platform.properties │ ├── main │ └── java │ │ └── com │ │ └── cedarpolicy │ │ ├── AuthorizationEngine.java │ │ ├── BasicAuthorizationEngine.java │ │ ├── CedarJson.java │ │ ├── Experimental.java │ │ ├── ExperimentalFeature.java │ │ ├── formatter │ │ └── PolicyFormatter.java │ │ ├── loader │ │ └── LibraryLoader.java │ │ ├── model │ │ ├── AuthorizationRequest.java │ │ ├── AuthorizationResponse.java │ │ ├── AuthorizationSuccessResponse.java │ │ ├── Context.java │ │ ├── DetailedError.java │ │ ├── Effect.java │ │ ├── EntityValidationRequest.java │ │ ├── PartialAuthorizationRequest.java │ │ ├── PartialAuthorizationResponse.java │ │ ├── PartialAuthorizationSuccessResponse.java │ │ ├── SourceLocation.java │ │ ├── ValidationRequest.java │ │ ├── ValidationResponse.java │ │ ├── entity │ │ │ ├── Entities.java │ │ │ ├── Entity.java │ │ │ └── package-info.java │ │ ├── exception │ │ │ ├── AuthException.java │ │ │ ├── BadRequestException.java │ │ │ ├── DeserializationRecursionDepthException.java │ │ │ ├── InternalException.java │ │ │ ├── InvalidEUIDException.java │ │ │ ├── InvalidEscapeSequenceException.java │ │ │ ├── InvalidValueDeserializationException.java │ │ │ ├── InvalidValueSerializationException.java │ │ │ ├── MissingExperimentalFeatureException.java │ │ │ └── package-info.java │ │ ├── formatter │ │ │ └── Config.java │ │ ├── package-info.java │ │ ├── policy │ │ │ ├── LinkValue.java │ │ │ ├── Policy.java │ │ │ ├── PolicySet.java │ │ │ ├── TemplateLink.java │ │ │ └── package-info.java │ │ └── schema │ │ │ ├── Schema.java │ │ │ └── package-info.java │ │ ├── package-info.java │ │ ├── serializer │ │ ├── EntityDeserializer.java │ │ ├── EntitySerializer.java │ │ ├── JsonEUID.java │ │ ├── PolicySetSerializer.java │ │ ├── SchemaSerializer.java │ │ ├── TemplateLinkSerializer.java │ │ ├── ValueDeserializer.java │ │ ├── ValueSerializer.java │ │ └── package-info.java │ │ └── value │ │ ├── CedarList.java │ │ ├── CedarMap.java │ │ ├── Decimal.java │ │ ├── EntityIdentifier.java │ │ ├── EntityTypeName.java │ │ ├── EntityUID.java │ │ ├── IpAddress.java │ │ ├── PrimBool.java │ │ ├── PrimLong.java │ │ ├── PrimString.java │ │ ├── Unknown.java │ │ ├── Value.java │ │ └── package-info.java │ └── test │ ├── java │ └── com │ │ └── cedarpolicy │ │ ├── AuthTests.java │ │ ├── ContextTests.java │ │ ├── EntitiesTests.java │ │ ├── EntityIdTests.java │ │ ├── EntityTests.java │ │ ├── EntityTypeNameTests.java │ │ ├── EntityUIDTests.java │ │ ├── EntityValidationTests.java │ │ ├── JSONTests.java │ │ ├── PolicyFormatterTests.java │ │ ├── PolicySetTests.java │ │ ├── PolicyTests.java │ │ ├── SchemaTests.java │ │ ├── SharedIntegrationTests.java │ │ ├── TestUtil.java │ │ ├── ValidationTests.java │ │ ├── package-info.java │ │ └── pbt │ │ ├── EntityGen.java │ │ ├── IntegrationTests.java │ │ ├── ParserTest.java │ │ ├── Utils.java │ │ └── package-info.java │ └── resources │ ├── empty_schema.json │ ├── formatted_policy.cedar │ ├── formatted_policy_custom_config.cedar │ ├── invalid_entities.json │ ├── invalid_entity.json │ ├── library_schema.json │ ├── malformed_policy_set.cedar │ ├── photoflash_schema.json │ ├── policies.cedar │ ├── role_schema.json │ ├── schema_parsing_allow_schema.json │ ├── schema_parsing_deny_schema.json │ ├── template.cedar │ ├── unformatted_policy.cedar │ ├── valid_entities.json │ └── valid_entity.json ├── CedarJavaFFI ├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md └── src │ ├── answer.rs │ ├── interface.rs │ ├── jlist.rs │ ├── jmap.rs │ ├── jset.rs │ ├── jvm_test_utils.rs │ ├── lib.rs │ ├── objects.rs │ ├── tests.rs │ └── utils.rs ├── LICENSE ├── NOTICE ├── README.md ├── THIRD_PARTY_LICENSES.txt └── configure_ci_build.sh /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: Create a report to help us improve Cedar 3 | labels: [pending-triage, bug] 4 | 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out this bug report! Try to include as much information as you can. 10 | 11 | - type: checkboxes 12 | attributes: 13 | label: | 14 | Before opening, please confirm: 15 | options: 16 | - label: I have [searched for duplicate or closed issues](https://github.com/cedar-policy/cedar-java/issues?q=is%3Aissue+). 17 | required: true 18 | - label: I have read the guide for [submitting bug reports](https://github.com/cedar-policy/cedar-java/blob/main/CONTRIBUTING.md#bug-reports). 19 | required: true 20 | - label: I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue. 21 | required: true 22 | 23 | - type: markdown 24 | attributes: 25 | value: | 26 | ## Category 27 | - type: dropdown 28 | attributes: 29 | label: Bug Category 30 | description: What part of Cedar is this bug related to? 31 | multiple: true 32 | options: 33 | - Cedar Parser 34 | - Policy Evaluation 35 | - Schemas and Validation 36 | - Other 37 | validations: 38 | required: true 39 | - type: markdown 40 | attributes: 41 | value: | 42 | ## Details 43 | - type: textarea 44 | attributes: 45 | label: Describe the bug 46 | description: A clear and concise description of what the bug is. 47 | validations: 48 | required: true 49 | - type: textarea 50 | attributes: 51 | label: Expected behavior 52 | description: A clear and concise description of what you expected to happen. 53 | validations: 54 | required: true 55 | - type: textarea 56 | attributes: 57 | label: Reproduction steps 58 | description: | 59 | How do you trigger this bug? Please walk us through it step by step. Screenshots can be attached in textarea below. 60 | placeholder: | 61 | 1. Install '...' 62 | 2. Configure '...' 63 | 3. Go to '...' 64 | 4. See error 65 | validations: 66 | required: true 67 | - type: textarea 68 | attributes: 69 | label: Code Snippet 70 | description: | 71 | Please provide a code snippet or a link to sample code of the issue you are experiencing to help us reproduce the issue. Please also include relevant Cedar policies, Schemas, or Entity Data. 72 | 73 | **Be sure to remove any sensitive data.** 74 | value: | 75 | ```rust 76 | // Put your code below this line. 77 | 78 | ``` 79 | - type: textarea 80 | attributes: 81 | label: Log output 82 | description: | 83 | For example, error messages, or stack traces. 84 | **Be sure to remove any sensitive data.** 85 | value: | 86 | ``` 87 | // Put your output below this line 88 | 89 | ``` 90 | - type: markdown 91 | attributes: 92 | value: | 93 | ## Configuration 94 | - type: textarea 95 | attributes: 96 | label: Additional configuration 97 | description: | 98 | If applicable, provide more configuration data. 99 | **Be sure to remove any sensitive data** 100 | 101 | - type: input 102 | attributes: 103 | label: Operating System 104 | description: e.g. Linux, MacOS 105 | - type: textarea 106 | attributes: 107 | label: Additional information and screenshots 108 | description: | 109 | If you have any additional information, workarounds, etc. for us, use the field below. 110 | Please note, you can attach screenshots or screen recordings here by 111 | dragging and dropping files in the field below. 112 | 113 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Suggest an idea for CedarJava 3 | labels: [pending-triage, feature-request] 4 | 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to submit a feature request! Try to include as much information as you can. 10 | 11 | - type: dropdown 12 | attributes: 13 | label: Category 14 | description: What component of CedarJava does this feature relate to? 15 | multiple: true 16 | options: 17 | - User level API changes 18 | - Internal refactors/changes 19 | - Documentation and code comments 20 | - Other 21 | validations: 22 | required: true 23 | 24 | - type: textarea 25 | attributes: 26 | label: Describe the feature you'd like to request 27 | description: | 28 | A clear and concise description of what you want to happen. Please include **any related issues**, documentation, etc. 29 | validations: 30 | required: true 31 | 32 | - type: textarea 33 | attributes: 34 | label: Describe alternatives you've considered 35 | description: | 36 | A clear and concise description of any alternative solutions or features you've considered. 37 | validations: 38 | required: true 39 | 40 | - type: textarea 41 | attributes: 42 | label: Additional context 43 | description: | 44 | Add any other use cases or context about the feature request here. Please include any prototype/sandbox, workaround, reference implementation, etc. 45 | 46 | - type: checkboxes 47 | attributes: 48 | label: Is this something that you'd be interested in working on? 49 | options: 50 | - label: 👋 I may be able to implement this feature request 51 | - label: ⚠️ This feature might incur a breaking change 52 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "cargo" 9 | directory: "/CedarJavaFFI" 10 | schedule: 11 | interval: "weekly" 12 | - package-ecosystem: "gradle" 13 | directory: "/CedarJava" 14 | schedule: 15 | interval: "weekly" -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Build & Test 2 | 3 | on: 4 | pull_request: 5 | 6 | env: 7 | CARGO_TERM_COLOR: always 8 | 9 | jobs: 10 | get-branch-name: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Get branch name 14 | shell: bash 15 | # The workflow is triggered by pull_request so we use `GITHUB_BASE_REF` 16 | run: echo "branch_name=${GITHUB_BASE_REF}" >> $GITHUB_OUTPUT 17 | id: get_branch_name 18 | 19 | outputs: 20 | branch_name: ${{ steps.get_branch_name.outputs.branch_name }} 21 | 22 | run_cedar_java: 23 | name: run_cedar_java 24 | needs: get-branch-name 25 | uses: ./.github/workflows/run_cedar_java_reusable.yml 26 | with: 27 | cedar_policy_ref: "refs/heads/main" # use the latest commit on main 28 | cedar_java_ref: "${{ github.href }}" # use the current PR's commit 29 | -------------------------------------------------------------------------------- /.github/workflows/run_cedar_java_reusable.yml: -------------------------------------------------------------------------------- 1 | name: Build and Test CedarJava 2 | on: 3 | workflow_call: 4 | inputs: 5 | cedar_policy_ref: 6 | required: false 7 | type: string 8 | cedar_java_ref: 9 | required: false 10 | default: "main" 11 | type: string 12 | 13 | env: 14 | CARGO_TERM_COLOR: always 15 | 16 | jobs: 17 | build: 18 | strategy: 19 | matrix: 20 | os: [ubuntu-latest, macos-14] 21 | include: 22 | - os: ubuntu-latest 23 | name: Build on Linux 24 | zigInstall: wget https://ziglang.org/download/0.11.0/zig-linux-x86_64-0.11.0.tar.xz -O - | tar xJ && echo "$(pwd)/zig-linux-x86_64-0.11.0" >> $GITHUB_PATH 25 | - os: macos-14 26 | name: Build on macOS 27 | zigInstall: wget https://ziglang.org/download/0.11.0/zig-macos-x86_64-0.11.0.tar.xz -O - | tar xJ && echo "$(pwd)/zig-macos-x86_64-0.11.0" >> $GITHUB_PATH 28 | runs-on: ${{ matrix.os }} 29 | name: ${{ matrix.name }} 30 | steps: 31 | - name: Checkout Cedar Java 32 | uses: actions/checkout@v4 33 | with: 34 | repository: cedar-policy/cedar-java 35 | ref: ${{ inputs.cedar_java_ref }} 36 | - name: Checkout cedar-policy 37 | uses: actions/checkout@v4 38 | with: 39 | repository: cedar-policy/cedar 40 | ref: ${{ inputs.cedar_policy_ref }} 41 | path: ./cedar 42 | - name: Prepare Rust Build 43 | run: rustup install stable && rustup default stable 44 | - name: Configure CedarJavaFFI for CI build 45 | run: bash configure_ci_build.sh 46 | - name: Check FFI Formatting 47 | working-directory: CedarJavaFFI 48 | run: cargo fmt --all --check 49 | - name: Run FFI tests 50 | working-directory: CedarJavaFFI 51 | run: cargo test --all-features 52 | - name: Install Zig 53 | run: ${{ matrix.zigInstall }} 54 | - name: Setup Java JDK 55 | uses: actions/setup-java@v4 56 | with: 57 | java-version: '17' 58 | distribution: 'corretto' 59 | cache: 'gradle' 60 | - name: Build FFI and Java Libraries 61 | working-directory: CedarJava 62 | run: ./gradlew build 63 | - name: Generate Java Documentation 64 | working-directory: CedarJava 65 | run: ./gradlew javadoc 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/ 2 | .idea/ 3 | /build 4 | /buildSrc/build/ 5 | /gradle/ 6 | /gradlew 7 | /gradlew.bat 8 | /wrapper/ 9 | .DS_Store 10 | .jqwik-database 11 | *.iml 12 | .classpath 13 | .factorypath 14 | .project 15 | .settings/ 16 | target/ 17 | 18 | # Ignore changes to gradle.properties because we enter passwords here for releases 19 | /gradle.properties 20 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | -------------------------------------------------------------------------------- /CedarJava/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/ 2 | .idea/ 3 | /build 4 | /buildSrc/build/ 5 | /gradle/ 6 | /gradlew 7 | /gradlew.bat 8 | /wrapper/ 9 | .DS_Store 10 | .jqwik-database 11 | *.iml 12 | .classpath 13 | .factorypath 14 | .project 15 | .settings/ 16 | bin/ 17 | # Ignore changes to gradle.properties because we enter passwords here for releases 18 | /gradle.properties 19 | -------------------------------------------------------------------------------- /CedarJava/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Unreleased 4 | ### Added 5 | * Added Zig version validation for publishing artifacts [#306](https://github.com/cedar-policy/cedar-java/pull/306) 6 | 7 | ## 4.3.0 8 | ### Added 9 | * Introduced new model classes for improved type safety and functionality: 10 | * `com.cedarpolicy.model.Context` - Policy context representation (will replace `Map`) [#286](https://github.com/cedar-policy/cedar-java/pull/286) 11 | * `com.cedarpolicy.model.entity.Entities` - Entity collection management (will replace `Set`) [#293](https://github.com/cedar-policy/cedar-java/pull/293) 12 | * Enhanced `AuthorizationError` with public getters and `.toString()` method [#294](https://github.com/cedar-policy/cedar-java/pull/294) 13 | * Added JSON parsing support for `Entity` [#292](https://github.com/cedar-policy/cedar-java/pull/292) 14 | * Implemented additional constructors to improve instantiation options for `Entity` [#288](https://github.com/cedar-policy/cedar-java/pull/288) 15 | * Added support for policy annotations [#296](https://github.com/cedar-policy/cedar-java/pull/296) 16 | 17 | ### Planned Improvements 18 | * The following authorization parameters will be updated in a future release: 19 | * `Map` for context will be replaced by `com.cedarpolicy.model.Context` 20 | * `Set` for entities will be replaced by `com.cedarpolicy.model.entity.Entities` 21 | 22 | ## 3.0 23 | 24 | * Reworked interface of `com.cedarpolicy.value.EntityUID` to support namespaces 25 | * Modified `com.cedarpolicy.model.AuthorizationRequest` to use `com.cedarpolicy.value.EntityUID` instead of Strings 26 | * Removes all use of the deprecated `__expr` syntax in JSON 27 | * Added `com.cedarpolicy.value.EntityTypeName` which represents namespaced types 28 | * Added `com.cedarpolicy.value.EntityIdentifier` which represents Entity Ids 29 | 30 | ## 2.0.0 31 | 32 | Initial release of `CedarJava`. 33 | -------------------------------------------------------------------------------- /CedarJava/DIFFERENCES_FROM_RUST.md: -------------------------------------------------------------------------------- 1 | # Differences from Rust 2 | CedarJava typically lags behind the latest Rust features. Notably, it is currently missing: 3 | 4 | - Partial Evaluation 5 | - Annotations -------------------------------------------------------------------------------- /CedarJava/README.md: -------------------------------------------------------------------------------- 1 | # CedarJava 2 | 3 | This package provides the Java interface for the Cedar language. You can use these to call Cedar from your Java applications. See [java-hello-world](https://github.com/cedar-policy/cedar-examples/tree/main/cedar-java-hello-world) for an example of calling Cedar from a Java application. 4 | 5 | For more information about Cedar, please see: https://www.cedarpolicy.com/ 6 | 7 | ## Prerequisites 8 | 9 | - [JDK 17](https://openjdk.org/projects/jdk/17/) or later 10 | - [Rust](https://rustup.rs/) with `rustup` 11 | - [Zig](https://ziglang.org/learn/getting-started/) for cross compiling with [cargo-zigbuild](https://github.com/rust-cross/cargo-zigbuild) 12 | We currently depend on Zig 0.11. 13 | 14 | ## Building 15 | 16 | Run the [Gradle Wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper_basics.html) 17 | with the `build` task to compile both the Cedar Java Foreign Function Interface and the Cedar Java library. 18 | 19 | ```shell 20 | ./gradlew build 21 | ``` 22 | 23 | Our build is quite long (due to the cross compiling), so to just check 24 | syntax: 25 | ```shell 26 | ./gradlew check -x test 27 | ``` 28 | 29 | ## Debugging 30 | 31 | Debugging calls across the JNI boundary is a bit tricky (as ever a bit more so on a Mac), but can be done by attaching 32 | both a Java and native debugger (such as GDB/LLDB) to the program. 33 | 34 | ## Unsupported Features 35 | You can see a list of features not yet supported in CedarJava at [Differences from Rust](DIFFERENCES_FROM_RUST.md). 36 | 37 | ## Security 38 | 39 | See [CONTRIBUTING](https://github.com/cedar-policy/cedar-java/tree/main/CONTRIBUTING.md#security-issue-notifications) for more information. 40 | 41 | ## License 42 | 43 | This project is licensed under the Apache-2.0 License. 44 | -------------------------------------------------------------------------------- /CedarJava/config/checkstyle/suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /CedarJava/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cedar-policy/cedar-java/38bea1f2e7a697473063297ef72c9e05a7a37ae6/CedarJava/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /CedarJava/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip 4 | networkTimeout=10000 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /CedarJava/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /CedarJava/settings.gradle: -------------------------------------------------------------------------------- 1 | // Always define a settings file: 2 | // https://docs.gradle.org/current/userguide/organizing_gradle_projects.html#always_define_a_settings_file 3 | rootProject.name = 'CedarJava' 4 | -------------------------------------------------------------------------------- /CedarJava/src/junit-platform.properties: -------------------------------------------------------------------------------- 1 | jqwik.tries.default = 1000 -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/CedarJson.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy; 18 | 19 | import com.cedarpolicy.model.entity.Entity; 20 | import com.cedarpolicy.model.policy.PolicySet; 21 | import com.cedarpolicy.model.policy.TemplateLink; 22 | import com.cedarpolicy.model.schema.Schema; 23 | import com.cedarpolicy.serializer.EntitySerializer; 24 | import com.cedarpolicy.serializer.PolicySetSerializer; 25 | import com.cedarpolicy.serializer.TemplateLinkSerializer; 26 | import com.cedarpolicy.serializer.SchemaSerializer; 27 | import com.cedarpolicy.serializer.ValueDeserializer; 28 | import com.cedarpolicy.serializer.ValueSerializer; 29 | import com.cedarpolicy.serializer.EntityDeserializer; 30 | import com.cedarpolicy.value.Value; 31 | import com.fasterxml.jackson.databind.ObjectMapper; 32 | import com.fasterxml.jackson.databind.ObjectReader; 33 | import com.fasterxml.jackson.databind.ObjectWriter; 34 | import com.fasterxml.jackson.databind.module.SimpleModule; 35 | import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; 36 | 37 | public final class CedarJson { 38 | private static final ObjectMapper OBJECT_MAPPER = createObjectMapper(); 39 | 40 | private CedarJson() { 41 | throw new IllegalStateException("Utility class"); 42 | } 43 | 44 | public static ObjectMapper objectMapper() { 45 | return OBJECT_MAPPER.copy(); 46 | } 47 | 48 | public static ObjectWriter objectWriter() { 49 | return OBJECT_MAPPER.writer(); 50 | } 51 | 52 | public static ObjectReader objectReader() { 53 | return OBJECT_MAPPER.reader(); 54 | } 55 | 56 | private static ObjectMapper createObjectMapper() { 57 | final ObjectMapper mapper = new ObjectMapper(); 58 | 59 | final SimpleModule module = new SimpleModule(); 60 | module.addSerializer(Entity.class, new EntitySerializer()); 61 | module.addSerializer(Schema.class, new SchemaSerializer()); 62 | module.addSerializer(TemplateLink.class, new TemplateLinkSerializer()); 63 | module.addSerializer(PolicySet.class, new PolicySetSerializer()); 64 | module.addSerializer(Value.class, new ValueSerializer()); 65 | module.addDeserializer(Value.class, new ValueDeserializer()); 66 | module.addDeserializer(Entity.class, new EntityDeserializer()); 67 | mapper.registerModule(module); 68 | mapper.registerModule(new Jdk8Module()); 69 | 70 | return mapper; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/Experimental.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy; 18 | 19 | import java.lang.annotation.*; 20 | 21 | /** 22 | * Marks this element as experimental. 23 | */ 24 | @Documented 25 | @Inherited 26 | @Retention(RetentionPolicy.RUNTIME) 27 | @Target({ElementType.TYPE, ElementType.METHOD}) 28 | public @interface Experimental { 29 | /** The experimental feature the element depends on. */ 30 | ExperimentalFeature value(); 31 | } 32 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/ExperimentalFeature.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy; 18 | 19 | public enum ExperimentalFeature { 20 | /** Partial evaluation feature */ 21 | PARTIAL_EVALUATION("partial-eval"); 22 | 23 | private String compileFlag; 24 | ExperimentalFeature(String compileFlag) { 25 | this.compileFlag = compileFlag; 26 | } 27 | 28 | public String getCompileFlag() { 29 | return this.compileFlag; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/formatter/PolicyFormatter.java: -------------------------------------------------------------------------------- 1 | package com.cedarpolicy.formatter; 2 | 3 | import com.cedarpolicy.loader.LibraryLoader; 4 | import com.cedarpolicy.model.exception.InternalException; 5 | import com.cedarpolicy.model.formatter.Config; 6 | 7 | public final class PolicyFormatter { 8 | 9 | static { 10 | LibraryLoader.loadLibrary(); 11 | } 12 | 13 | private PolicyFormatter() { 14 | } 15 | 16 | public static native String policiesStrToPretty(String policies) 17 | throws InternalException, NullPointerException; 18 | 19 | public static native String policiesStrToPrettyWithConfig(String policies, Config config) 20 | throws InternalException, NullPointerException; 21 | } 22 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/loader/LibraryLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.loader; 18 | 19 | import com.fizzed.jne.JNE; 20 | 21 | /** 22 | * Native Library Loader encapsulates runtime loading of the Cedar Java FFI library 23 | */ 24 | public final class LibraryLoader { 25 | private static final String LIBRARY_PATH_VARIABLE_NAME = "CEDAR_JAVA_FFI_LIB"; 26 | 27 | private static final String LIBRARY_NAME = "cedar_java_ffi"; 28 | 29 | /** 30 | * Private constructor to prevent instantiation of this utility class 31 | */ 32 | private LibraryLoader() { 33 | } 34 | 35 | /** 36 | * Load Cedar Java FFI library based on runtime operating system and architecture of the Java Virtual Machine 37 | */ 38 | public static void loadLibrary() { 39 | final String libraryPath = System.getenv(LIBRARY_PATH_VARIABLE_NAME); 40 | if (libraryPath == null || libraryPath.isEmpty()) { 41 | JNE.loadLibrary(LIBRARY_NAME); 42 | } else { 43 | System.load(libraryPath); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/AuthorizationResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model; 18 | 19 | import com.fasterxml.jackson.annotation.JsonCreator; 20 | import com.fasterxml.jackson.annotation.JsonProperty; 21 | import com.google.common.collect.ImmutableList; 22 | import java.util.ArrayList; 23 | import java.util.Optional; 24 | 25 | /** 26 | * The result of processing an AuthorizationRequest. 27 | */ 28 | public final class AuthorizationResponse { 29 | /** Is this a success or a failure response */ 30 | @JsonProperty("type") 31 | public final SuccessOrFailure type; 32 | /** This will be present if and only if `type` is `Success`. */ 33 | @JsonProperty("response") 34 | public final Optional success; 35 | /** This will be present if and only if `type` is `Failure`. */ 36 | @JsonProperty("errors") 37 | public final Optional> errors; 38 | /** Warnings can be produced regardless of whether we have a `Success` or `Failure`. */ 39 | @JsonProperty("warnings") 40 | public final ImmutableList warnings; 41 | 42 | /** 43 | * If `type` is `Success`, `success` should be present and `errors` empty. 44 | * If `type` is `Failure`, `errors` should be present and `success` empty. 45 | */ 46 | @JsonCreator 47 | public AuthorizationResponse( 48 | @JsonProperty("type") SuccessOrFailure type, 49 | @JsonProperty("response") Optional success, 50 | @JsonProperty("errors") Optional> errors, 51 | @JsonProperty("warnings") ArrayList warnings 52 | ) { 53 | this.type = type; 54 | this.success = success; 55 | this.errors = errors.map((list) -> ImmutableList.copyOf(list)); 56 | if (warnings == null) { 57 | this.warnings = ImmutableList.of(); // empty 58 | } else { 59 | this.warnings = ImmutableList.copyOf(warnings); 60 | } 61 | } 62 | 63 | @Override 64 | public String toString() { 65 | final String warningsString = warnings.isEmpty() ? "" : "\nwith warnings: " + warnings.toString(); 66 | if (type == SuccessOrFailure.Success) { 67 | return "SUCCESS: " + success.get().toString() + warningsString; 68 | } else { 69 | return "FAILURE: " + errors.get().toString() + warningsString; 70 | } 71 | } 72 | 73 | public enum SuccessOrFailure { 74 | @JsonProperty("success") 75 | Success, 76 | @JsonProperty("failure") 77 | Failure, 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/Context.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model; 18 | 19 | import java.util.HashMap; 20 | import java.util.Collections; 21 | import java.util.stream.Collectors; 22 | import java.util.stream.StreamSupport; 23 | import java.util.Map; 24 | import com.cedarpolicy.value.Value; 25 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 26 | 27 | public class Context { 28 | 29 | private Map context; 30 | 31 | /** 32 | * Constructs a new empty Context with no key-value pairs. Initializes the internal context map as an empty 33 | * immutable map. 34 | */ 35 | public Context() { 36 | context = Collections.emptyMap(); 37 | } 38 | 39 | public boolean isEmpty() { 40 | return context.isEmpty(); 41 | } 42 | 43 | /** 44 | * Constructs a new Context from an Iterable of key-value pairs. Creates a new HashMap and populates it with the 45 | * provided entries. Equivalent to from_pairs in Cedar Rust. 46 | * 47 | * @param contextList An Iterable containing key-value pairs to initialize this context with 48 | * @throws IllegalStateException if a duplicate key is found within the iterable 49 | * @throws IllegalArgumentException if the contextList parameter is null 50 | */ 51 | @SuppressFBWarnings("CT_CONSTRUCTOR_THROW") 52 | public Context(Iterable> contextList) { 53 | context = new HashMap<>(); 54 | mergeContextFromIterable(contextList); 55 | } 56 | 57 | /** 58 | * Constructs a new Context with the provided map of key-value pairs. Creates a defensive copy of the input map to 59 | * maintain immutability. 60 | * 61 | * @param contextMap The map of key-value pairs to initialize this context with 62 | * @throws IllegalArgumentException if the contextMap parameter is null 63 | */ 64 | public Context(Map contextMap) { 65 | context = new HashMap<>(); 66 | context.putAll(contextMap); 67 | } 68 | 69 | /** 70 | * Returns a defensive copy of the internal context map. 71 | * 72 | * @return A new HashMap containing all key-value pairs from the internal context 73 | */ 74 | public Map getContext() { 75 | return new HashMap<>(context); 76 | } 77 | 78 | /** 79 | * Merges another Context object into the current context. 80 | * 81 | * @param contextToMerge The Context object to merge into this context 82 | * @throws IllegalStateException if a duplicate key is found while merging the context 83 | * @throws IllegalArgumentException if the contextToMerge parameter is null 84 | */ 85 | public void merge(Context contextToMerge) throws IllegalStateException, IllegalArgumentException { 86 | mergeContextFromIterable(contextToMerge.getContext().entrySet()); 87 | } 88 | 89 | /** 90 | * Merges the provided key-value pairs into the current context. 91 | * 92 | * @param contextMaps An Iterable containing key-value pairs to merge into this context 93 | * @throws IllegalStateException if a duplicate key is found in the existing context or duplicate key found 94 | * within the iterable 95 | * @throws IllegalArgumentException if the contextMaps parameter is null 96 | */ 97 | public void merge(Iterable> contextMaps) 98 | throws IllegalStateException, IllegalArgumentException { 99 | mergeContextFromIterable(contextMaps); 100 | } 101 | 102 | /** 103 | * Retrieves the Value associated with the specified key from the context. 104 | * 105 | * @param key The key whose associated Value is to be returned 106 | * @return The Value associated with the specified key, or null if the key is not found replicating Cedar Rust 107 | * behavior 108 | * @throws IllegalArgumentException if the key parameter is null 109 | */ 110 | public Value get(String key) { 111 | if (key == null) { 112 | throw new IllegalArgumentException("Key cannot be null"); 113 | } 114 | return context.getOrDefault(key, null); 115 | } 116 | 117 | /** 118 | * Processes an Iterable of Map entries and adds them to the context. 119 | * 120 | * @param contextIterator The Iterable containing key-value pairs to add to the context 121 | * @throws IllegalStateException if a duplicate key is found in the existing context or duplicate key found 122 | * within the iterable 123 | * @throws IllegalArgumentException if the contextIterator is null 124 | */ 125 | private void mergeContextFromIterable(Iterable> contextIterator) 126 | throws IllegalStateException, IllegalArgumentException { 127 | if (contextIterator == null) { 128 | throw new IllegalArgumentException("Context iterator cannot be null"); 129 | } 130 | 131 | Map newEntries = StreamSupport.stream(contextIterator.spliterator(), false).peek(entry -> { 132 | if (context.containsKey(entry.getKey())) { 133 | throw new IllegalStateException( 134 | String.format("Duplicate key '%s' in existing context", entry.getKey())); 135 | } 136 | }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); 137 | context.putAll(newEntries); 138 | } 139 | 140 | /** Readable string representation. */ 141 | @Override 142 | public String toString() { 143 | return context.toString(); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/DetailedError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model; 18 | 19 | import com.fasterxml.jackson.annotation.JsonCreator; 20 | import com.fasterxml.jackson.annotation.JsonProperty; 21 | import com.google.common.collect.ImmutableList; 22 | import java.util.List; 23 | import java.util.Optional; 24 | 25 | public class DetailedError { 26 | /** Main error message */ 27 | @JsonProperty("message") 28 | public final String message; 29 | /** Help message, providing additional information about the error or help resolving it */ 30 | @JsonProperty("help") 31 | public final Optional help; 32 | /** Error code */ 33 | @JsonProperty("code") 34 | public final Optional code; 35 | /** URL for more information about the error */ 36 | @JsonProperty("url") 37 | public final Optional url; 38 | /** Severity */ 39 | @JsonProperty("severity") 40 | public final Optional severity; 41 | /** Source labels (ranges) */ 42 | @JsonProperty("sourceLocations") 43 | public final ImmutableList sourceLocations; 44 | /** Related errors */ 45 | @JsonProperty("related") 46 | public final ImmutableList related; 47 | 48 | @JsonCreator 49 | public DetailedError( 50 | @JsonProperty("message") String message, 51 | @JsonProperty("help") Optional help, 52 | @JsonProperty("code") Optional code, 53 | @JsonProperty("url") Optional url, 54 | @JsonProperty("severity") Optional severity, 55 | @JsonProperty("sourceLocations") Optional> sourceLocations, 56 | @JsonProperty("related") Optional> related 57 | ) { 58 | this.message = message; 59 | this.help = help; 60 | this.code = code; 61 | this.url = url; 62 | this.severity = severity; 63 | if (sourceLocations.isPresent()) { 64 | this.sourceLocations = ImmutableList.copyOf(sourceLocations.get()); 65 | } else { 66 | this.sourceLocations = ImmutableList.of(); // empty 67 | } 68 | if (related.isPresent()) { 69 | this.related = ImmutableList.copyOf(related.get()); 70 | } else { 71 | this.related = ImmutableList.of(); // empty 72 | } 73 | } 74 | 75 | public enum Severity { 76 | /** Advice (the lowest severity) */ 77 | @JsonProperty("advice") 78 | Advice, 79 | /** Warning */ 80 | @JsonProperty("warning") 81 | Warning, 82 | /** Error (the highest severity) */ 83 | @JsonProperty("error") 84 | Error, 85 | } 86 | 87 | public static final class SourceLabel { 88 | /** Text of the label (if any) */ 89 | @JsonProperty("label") 90 | public final Optional label; 91 | /** Start of the source location (in bytes) */ 92 | @JsonProperty("start") 93 | public final int start; 94 | /** End of the source location (in bytes) */ 95 | @JsonProperty("end") 96 | public final int end; 97 | 98 | @JsonCreator 99 | public SourceLabel( 100 | @JsonProperty("label") Optional label, 101 | @JsonProperty("start") int start, 102 | @JsonProperty("end") int end 103 | ) { 104 | this.label = label; 105 | this.start = start; 106 | this.end = end; 107 | } 108 | 109 | @Override 110 | public String toString() { 111 | return String.format("SourceLabel{label=\"%s\", start=%s, end=%s}", label.orElse(""), start, end); 112 | } 113 | } 114 | 115 | @Override 116 | public String toString() { 117 | return String.format( 118 | "DetailedError{message=\"%s\", help=\"%s\", code=\"%s\", url=\"%s\", severity=%s, sourcelocations=%s, related=%s}", 119 | message, help.orElse(""), code.orElse(""), url.orElse(""), severity.map(Severity::toString).orElse(""), 120 | sourceLocations, related); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/Effect.java: -------------------------------------------------------------------------------- 1 | package com.cedarpolicy.model; 2 | 3 | /** 4 | * Represents the effect of a Cedar policy. 5 | */ 6 | public enum Effect { 7 | PERMIT, 8 | FORBID; 9 | 10 | /** 11 | * Converts a string to an Effect enum value, case-insensitive. 12 | * 13 | * @param effectString the string value to convert 14 | * @return the corresponding Effect enum value 15 | * @throws NullPointerException if the effectString is null 16 | * @throws IllegalArgumentException if the effectString doesn't match any Effect in {permit, forbid} 17 | */ 18 | public static Effect fromString(String effectString) { 19 | 20 | if (effectString == null) { 21 | throw new NullPointerException(); 22 | } 23 | 24 | switch (effectString.toLowerCase()) { 25 | case "permit": 26 | return PERMIT; 27 | case "forbid": 28 | return FORBID; 29 | default: 30 | throw new IllegalArgumentException("Invalid Effect: " + effectString + ". Expected 'permit' or 'forbid'"); 31 | } 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/EntityValidationRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model; 18 | 19 | import java.util.List; 20 | import java.util.Objects; 21 | 22 | import com.cedarpolicy.model.entity.Entity; 23 | import com.cedarpolicy.model.schema.Schema; 24 | import com.fasterxml.jackson.annotation.JsonProperty; 25 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 26 | 27 | /** 28 | * Information passed to Cedar for entities validation. 29 | */ 30 | public final class EntityValidationRequest { 31 | @JsonProperty("schema") 32 | private final Schema schema; 33 | @JsonProperty("entities") 34 | private final List entities; 35 | 36 | /** 37 | * Construct a validation request. 38 | * 39 | * @param schema Schema for the request 40 | * @param entities Map. 41 | */ 42 | @SuppressFBWarnings 43 | public EntityValidationRequest(Schema schema, List entities) { 44 | if (schema == null) { 45 | throw new NullPointerException("schema"); 46 | } 47 | 48 | if (entities == null) { 49 | throw new NullPointerException("entities"); 50 | } 51 | 52 | this.schema = schema; 53 | this.entities = entities; 54 | } 55 | 56 | /** 57 | * Test equality. 58 | */ 59 | @Override 60 | public boolean equals(final Object o) { 61 | if (!(o instanceof EntityValidationRequest)) { 62 | return false; 63 | } 64 | 65 | final EntityValidationRequest other = (EntityValidationRequest) o; 66 | return schema.equals(other.schema) && entities.equals(other.entities); 67 | } 68 | 69 | /** 70 | * Hash. 71 | */ 72 | @Override 73 | public int hashCode() { 74 | return Objects.hash(schema, entities); 75 | } 76 | 77 | /** 78 | * Get readable string representation. 79 | */ 80 | public String toString() { 81 | return "EntityValidationRequest(schema=" + schema + ", entities=" + entities + ")"; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/PartialAuthorizationResponse.java: -------------------------------------------------------------------------------- 1 | package com.cedarpolicy.model; 2 | 3 | import com.cedarpolicy.Experimental; 4 | import com.cedarpolicy.ExperimentalFeature; 5 | import com.fasterxml.jackson.annotation.JsonCreator; 6 | import com.fasterxml.jackson.annotation.JsonProperty; 7 | import com.google.common.collect.ImmutableList; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Optional; 11 | 12 | @Experimental(ExperimentalFeature.PARTIAL_EVALUATION) 13 | public class PartialAuthorizationResponse { 14 | /** 15 | * Is this a success or a failure response 16 | */ 17 | @JsonProperty("type") 18 | public final SuccessOrFailure type; 19 | /** 20 | * This will be present if and only if `type` is `Success`. 21 | */ 22 | @JsonProperty("response") 23 | public final Optional success; 24 | /** 25 | * This will be present if and only if `type` is `Failure`. 26 | */ 27 | @JsonProperty("errors") 28 | public final Optional> errors; 29 | /** 30 | * Warnings can be produced regardless of whether we have a `Success` or `Failure`. 31 | */ 32 | @JsonProperty("warnings") 33 | public final ImmutableList warnings; 34 | 35 | /** 36 | * If `type` is `Success`, `success` should be present and `errors` empty. 37 | * If `type` is `Failure`, `errors` should be present and `success` empty. 38 | */ 39 | @JsonCreator 40 | public PartialAuthorizationResponse( 41 | @JsonProperty("type") SuccessOrFailure type, 42 | @JsonProperty("response") Optional success, 43 | @JsonProperty("errors") Optional> errors, 44 | @JsonProperty("warnings") ArrayList warnings 45 | ) { 46 | this.type = type; 47 | this.success = success; 48 | this.errors = errors.map((list) -> ImmutableList.copyOf(list)); 49 | if (warnings == null) { 50 | this.warnings = ImmutableList.of(); // empty 51 | } else { 52 | this.warnings = ImmutableList.copyOf(warnings); 53 | } 54 | } 55 | 56 | @Override 57 | public String toString() { 58 | final String warningsString = warnings.isEmpty() ? "" : "\nwith warnings: " + warnings; 59 | if (type == SuccessOrFailure.Success) { 60 | return "SUCCESS: " + success.get() + warningsString; 61 | } else { 62 | return "FAILURE: " + errors.get() + warningsString; 63 | } 64 | } 65 | 66 | public enum SuccessOrFailure { 67 | @JsonProperty("residuals") 68 | Success, 69 | @JsonProperty("failure") 70 | Failure, 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/SourceLocation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model; 18 | 19 | import com.fasterxml.jackson.annotation.JsonCreator; 20 | import com.fasterxml.jackson.annotation.JsonProperty; 21 | 22 | /** 23 | * A range of source code denoted by offset and length 24 | */ 25 | public final class SourceLocation { 26 | public final int start; 27 | public final int end; 28 | 29 | 30 | @JsonCreator 31 | public SourceLocation(@JsonProperty("start") int start, @JsonProperty("end") int end) { 32 | this.start = start; 33 | this.end = end; 34 | } 35 | 36 | @Override 37 | public boolean equals(final Object lhs) { 38 | if (!(lhs instanceof SourceLocation)) { 39 | return false; 40 | } 41 | 42 | final SourceLocation sl = (SourceLocation) lhs; 43 | return this.start == sl.start && this.end == sl.end; 44 | } 45 | 46 | @Override 47 | public int hashCode() { 48 | return start ^ end; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/ValidationRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model; 18 | 19 | import com.cedarpolicy.model.schema.Schema; 20 | import com.cedarpolicy.model.policy.PolicySet; 21 | import com.fasterxml.jackson.annotation.JsonProperty; 22 | 23 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 24 | 25 | import java.util.Objects; 26 | 27 | /** Information passed to Cedar for validation. */ 28 | public final class ValidationRequest { 29 | private final Schema schema; 30 | private final PolicySet policies; 31 | 32 | /** 33 | * Construct a validation request. 34 | * 35 | * @param schema Schema for the request 36 | * @param policies Map of Policy ID to policy. 37 | */ 38 | @SuppressFBWarnings 39 | public ValidationRequest(Schema schema, PolicySet policies) { 40 | if (schema == null) { 41 | throw new NullPointerException("schema"); 42 | } 43 | 44 | if (policies == null) { 45 | throw new NullPointerException("policies"); 46 | } 47 | 48 | this.schema = schema; 49 | this.policies = policies; 50 | } 51 | 52 | /** 53 | * Get the schema. 54 | * 55 | * @return The schema. 56 | */ 57 | public Schema getSchema() { 58 | return this.schema; 59 | } 60 | 61 | /** 62 | * Get the policy set. 63 | * 64 | * @return A `PolicySet` object 65 | */ 66 | @JsonProperty("policies") 67 | public PolicySet getPolicySet() { 68 | return this.policies; 69 | } 70 | 71 | /** Test equality. */ 72 | @Override 73 | public boolean equals(final Object o) { 74 | if (!(o instanceof ValidationRequest)) { 75 | return false; 76 | } 77 | 78 | final ValidationRequest other = (ValidationRequest) o; 79 | return schema.equals(other.schema) && policies.equals(other.policies); 80 | } 81 | 82 | /** Hash. */ 83 | @Override 84 | public int hashCode() { 85 | return Objects.hash(schema, policies); 86 | } 87 | 88 | /** Get readable string representation. */ 89 | public String toString() { 90 | return "ValidationRequest(schema=" + schema + ", policies=" + policies + ")"; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/entity/Entities.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model.entity; 18 | 19 | import static com.cedarpolicy.CedarJson.objectReader; 20 | 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.core.type.TypeReference; 23 | 24 | import java.io.IOException; 25 | import java.nio.file.Files; 26 | import java.nio.file.Path; 27 | import java.util.Set; 28 | import java.util.HashSet; 29 | 30 | /** 31 | * A class representing a collection of Cedar policy entities. 32 | */ 33 | public class Entities { 34 | private Set entities; 35 | 36 | /** 37 | * Constructs a new empty Entities collection. Creates a new HashSet to store Entity objects. 38 | */ 39 | public Entities() { 40 | this.entities = new HashSet<>(); 41 | } 42 | 43 | /** 44 | * Constructs a new Entities collection from a given Set of Entity objects. 45 | * 46 | * @param entities The Set of Entity objects to initialize this collection with 47 | */ 48 | public Entities(Set entities) { 49 | this.entities = new HashSet<>(entities); 50 | } 51 | 52 | /** 53 | * Returns a copy of the set of entities in this collection. 54 | * 55 | * @return A new HashSet containing all Entity objects in this collection 56 | */ 57 | public Set getEntities() { 58 | return new HashSet<>(entities); 59 | } 60 | 61 | /** 62 | * Parses a JSON string representation into an Entities collection. 63 | * 64 | * @param jsonString The JSON string containing entity data to parse 65 | * 66 | * @return A new Entities instance containing the parsed entities 67 | * @throws JsonProcessingException If the JSON string cannot be parsed into valid entities 68 | */ 69 | public static Entities parse(String jsonString) throws JsonProcessingException { 70 | return new Entities(objectReader().forType(new TypeReference>() { 71 | }).readValue(jsonString)); 72 | } 73 | 74 | /** 75 | * Parses a JSON file at the specified path into an Entities collection. 76 | * 77 | * @param filePath The path to the JSON file containing entity data to parse 78 | * 79 | * @return A new Entities instance containing the parsed entities 80 | * @throws IOException If there is an error reading the file 81 | * @throws JsonProcessingException If the JSON content cannot be parsed into valid entities 82 | */ 83 | public static Entities parse(Path filePath) throws IOException, JsonProcessingException { 84 | String jsonString = Files.readString(filePath); 85 | return new Entities(objectReader().forType(new TypeReference>() { 86 | }).readValue(jsonString)); 87 | } 88 | 89 | @Override 90 | public String toString() { 91 | return String.join("\n", this.entities.stream().map(Entity::toString).toList()); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/entity/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * This module represents entities passed into Cedar 19 | */ 20 | package com.cedarpolicy.model.entity; 21 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/exception/AuthException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model.exception; 18 | 19 | import java.util.Optional; 20 | 21 | /** 22 | * Exception thrown when errors are encountered that prevent communication with the authorization 23 | * engine. Note that this does not include errors that are generated by the authorization engine 24 | * while evaluating a request. These errors are included in the errors field of the 25 | * AuthorizationResponse. 26 | */ 27 | public class AuthException extends Exception { 28 | /** Generated Error Message. */ 29 | public final Optional message; 30 | 31 | /** Exception that caused the failure. */ 32 | public final Optional cause; 33 | 34 | /** 35 | * Exceptions encountered during authorization. 36 | * 37 | * @param message Error Message 38 | */ 39 | public AuthException(String message) { 40 | super(message); 41 | this.message = Optional.of(message); 42 | this.cause = Optional.empty(); 43 | } 44 | 45 | /** 46 | * Constructor to build an exception with both a Throwable cause and an error message. 47 | * 48 | * @param message useful debugging message 49 | * @param cause parent exception that caused this exception 50 | */ 51 | public AuthException(String message, Throwable cause) { 52 | super(message, cause); 53 | this.message = Optional.of(message); 54 | this.cause = Optional.of(cause); 55 | } 56 | 57 | /** 58 | * Constructor that just takes the Throwable cause. 59 | * 60 | * @param cause parent exception that caused this exception 61 | */ 62 | public AuthException(Throwable cause) { 63 | super("Auth Exception", cause); 64 | this.cause = Optional.of(cause); 65 | this.message = Optional.empty(); 66 | } 67 | 68 | /** Display the error message. */ 69 | public String toString() { 70 | return "Auth Exception: " 71 | + this.message.map(x -> x + ": ").orElse("") 72 | + this.cause.map(Throwable::toString).orElse(""); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/exception/BadRequestException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model.exception; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.Collections; 22 | import java.util.List; 23 | 24 | /** 25 | * An exception which is thrown when Cedar encounters an error in a supplied request which caused it 26 | * to stop processing; for example, a syntax error in a policy string. 27 | */ 28 | public class BadRequestException extends AuthException { 29 | private final List errors; 30 | 31 | /** 32 | * Failure due to bad request. 33 | * 34 | * @param errors List of Errors. 35 | */ 36 | public BadRequestException(String[] errors) { 37 | super("Bad request: " + String.join("\n", errors)); 38 | this.errors = new ArrayList<>(Arrays.asList(errors)); 39 | } 40 | 41 | /** 42 | * Get the errors. 43 | * 44 | * @return the error messages returned by Cedar 45 | */ 46 | public List getErrors() { 47 | return Collections.unmodifiableList(errors); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/exception/DeserializationRecursionDepthException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model.exception; 18 | 19 | import com.fasterxml.jackson.core.exc.StreamConstraintsException; 20 | 21 | /** Error deserializing a value due to passing recursion depth. */ 22 | public class DeserializationRecursionDepthException extends StreamConstraintsException { 23 | /** 24 | * Construct DeserializationRecursionDepthException. 25 | * 26 | * @param errorMessage Error message. 27 | */ 28 | public DeserializationRecursionDepthException(String errorMessage) { 29 | super(errorMessage); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/exception/InternalException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model.exception; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.Collections; 22 | import java.util.List; 23 | 24 | /** An exception which is thrown when Cedar encounters an internal error when processing a request. */ 25 | public class InternalException extends AuthException { 26 | private final List errors; 27 | 28 | public InternalException(String error) { 29 | super("Internal error: " + error); 30 | this.errors = new ArrayList<>(); 31 | this.errors.add(error); 32 | } 33 | 34 | /** 35 | * Internal exception from Rust library. 36 | * 37 | * @param errors List of Errors. 38 | */ 39 | public InternalException(String[] errors) { 40 | super("Internal error: " + String.join("\n", errors)); 41 | this.errors = new ArrayList<>(Arrays.asList(errors)); 42 | } 43 | 44 | /** 45 | * Get errors. 46 | * 47 | * @return the error messages returned by Cedar 48 | */ 49 | public List getErrors() { 50 | return Collections.unmodifiableList(errors); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/exception/InvalidEUIDException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model.exception; 18 | 19 | /** 20 | * Thrown when an invalid EUID is parsed 21 | */ 22 | public class InvalidEUIDException extends Exception { 23 | 24 | public InvalidEUIDException(String message) { 25 | super(message); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/exception/InvalidEscapeSequenceException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model.exception; 18 | 19 | /** Error due to invalid escape sequence (__expr). */ 20 | public class InvalidEscapeSequenceException extends AuthException { 21 | /** 22 | * Construct InvalidEscapeSequenceException. 23 | * 24 | * @param errorMessage Error message. 25 | */ 26 | public InvalidEscapeSequenceException(String errorMessage) { 27 | super(errorMessage); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/exception/InvalidValueDeserializationException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model.exception; 18 | 19 | import com.fasterxml.jackson.core.JsonParser; 20 | import com.fasterxml.jackson.core.JsonToken; 21 | import com.fasterxml.jackson.core.exc.InputCoercionException; 22 | 23 | /** Error deserializing a value. */ 24 | public class InvalidValueDeserializationException extends InputCoercionException { 25 | /** 26 | * Construct InvalidValueDeserializationException. 27 | * 28 | * @param errorMessage Error message. 29 | */ 30 | public InvalidValueDeserializationException(JsonParser parser, String errorMessage, JsonToken token, Class targetType) { 31 | super(parser, errorMessage, token, targetType); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/exception/InvalidValueSerializationException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model.exception; 18 | 19 | /** Error deserializing a value. This will be thrown if you extend the value class and don't 20 | * handle the new Value type in `ValueSerializer.java` */ 21 | public class InvalidValueSerializationException extends RuntimeException { 22 | /** 23 | * Construct InvalidValueSerializationException. 24 | * 25 | * @param errorMessage Error message. 26 | */ 27 | public InvalidValueSerializationException(String errorMessage) { 28 | super(errorMessage); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/exception/MissingExperimentalFeatureException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model.exception; 18 | 19 | import com.cedarpolicy.ExperimentalFeature; 20 | 21 | import java.nio.file.Path; 22 | 23 | public class MissingExperimentalFeatureException extends InternalException { 24 | private ExperimentalFeature experimentalFeature; 25 | 26 | public MissingExperimentalFeatureException(ExperimentalFeature experimentalFeature) { 27 | super("Missing experimental feature. To enable this feature please recompile " 28 | + Path.of(System.getenv("CEDAR_JAVA_FFI_LIB")).getFileName() 29 | + " with \"--features=" + experimentalFeature.getCompileFlag() + "\"."); 30 | this.experimentalFeature = experimentalFeature; 31 | } 32 | 33 | public ExperimentalFeature getExperimentalFeature() { 34 | return this.experimentalFeature; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/exception/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * This module various failure types for Cedar 19 | * 20 | *

Failures can come from Cedar (InternalException) or from the Java interface. 21 | * 22 | * @since 1.2 23 | * @author anmwells 24 | * @version 1.2 25 | */ 26 | package com.cedarpolicy.model.exception; 27 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/formatter/Config.java: -------------------------------------------------------------------------------- 1 | package com.cedarpolicy.model.formatter; 2 | 3 | public class Config { 4 | 5 | private final int lineWidth; 6 | private final int indentWidth; 7 | 8 | public Config(int lineWidth, int indentWidth) { 9 | this.lineWidth = lineWidth; 10 | this.indentWidth = indentWidth; 11 | } 12 | 13 | @SuppressWarnings("unused") 14 | public int getLineWidth() { 15 | return lineWidth; 16 | } 17 | 18 | @SuppressWarnings("unused") 19 | public int getIndentWidth() { 20 | return indentWidth; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * This module holds the interface passed to / received from Cedar 19 | * 20 | *

We query Cedar for authorization or validation. 21 | * 22 | * @since 1.2 23 | * @author anmwells 24 | * @version 1.2 25 | */ 26 | package com.cedarpolicy.model; 27 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/policy/LinkValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model.policy; 18 | import com.cedarpolicy.value.EntityUID; 19 | 20 | 21 | /** Link for policy template. */ 22 | public class LinkValue { 23 | private final String slot; 24 | private final EntityUID value; 25 | 26 | /** 27 | * Link for policy template. 28 | * 29 | * @param slot the slot in the template. 30 | * @param value the value to put in the slot 31 | */ 32 | public LinkValue(String slot, EntityUID value) { 33 | this.slot = slot; 34 | this.value = value; 35 | } 36 | 37 | /** Get the slot in the template. */ 38 | public String getSlot() { 39 | return slot; 40 | } 41 | 42 | /** Get the value to put in the slot. */ 43 | public EntityUID getValue() { 44 | return value; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/policy/PolicySet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model.policy; 18 | 19 | import com.cedarpolicy.loader.LibraryLoader; 20 | import com.cedarpolicy.model.exception.InternalException; 21 | 22 | import java.util.Collections; 23 | import java.util.List; 24 | import java.util.Map; 25 | import java.util.Set; 26 | import java.util.stream.Collectors; 27 | import java.io.IOException; 28 | import java.nio.file.Files; 29 | import java.nio.file.Path; 30 | 31 | /** Policy set containing policies in the Cedar language. */ 32 | public class PolicySet { 33 | static { 34 | LibraryLoader.loadLibrary(); 35 | } 36 | 37 | /** Static policies */ 38 | public Set policies; 39 | 40 | /** Template-linked policies */ 41 | public List templateLinks; 42 | 43 | /** Policy templates */ 44 | public Set templates; 45 | 46 | public PolicySet() { 47 | this.policies = Collections.emptySet(); 48 | this.templates = Collections.emptySet(); 49 | this.templateLinks = Collections.emptyList(); 50 | } 51 | 52 | public PolicySet(Set policies) { 53 | this.policies = policies; 54 | this.templates = Collections.emptySet(); 55 | this.templateLinks = Collections.emptyList(); 56 | } 57 | 58 | public PolicySet(Set policies, Set templates) { 59 | this.policies = policies; 60 | this.templates = templates; 61 | this.templateLinks = Collections.emptyList(); 62 | } 63 | 64 | public PolicySet(Set policies, Set templates, List templateLinks) { 65 | this.policies = policies; 66 | this.templates = templates; 67 | this.templateLinks = templateLinks; 68 | } 69 | 70 | /** 71 | * Get the static policies in the policy set. 72 | * 73 | * @return A map from policy id to `Policy` object 74 | */ 75 | public Map getStaticPolicies() { 76 | return policies.stream().collect(Collectors.toMap(Policy::getID, Policy::getSource)); 77 | } 78 | 79 | /** 80 | * Get the templates in the policy set. 81 | * 82 | * @return A map from policy id to `Policy` object 83 | */ 84 | public Map getTemplates() { 85 | return templates.stream().collect(Collectors.toMap(Policy::getID, Policy::getSource)); 86 | } 87 | 88 | /** 89 | * Gets number of static policies in the Policy Set. 90 | * 91 | * @return number of static policies, returns 0 if policies set is null 92 | */ 93 | public int getNumPolicies() { 94 | return policies != null ? policies.size() : 0; 95 | } 96 | 97 | /** 98 | * Gets number of templates in the Policy Set. 99 | * 100 | * @return number of templates, returns 0 if templates set is null 101 | */ 102 | public int getNumTemplates() { 103 | return templates != null ? templates.size() : 0; 104 | } 105 | 106 | /** 107 | * Parse multiple policies and templates from a file into a PolicySet. 108 | * @param filePath the path to the file containing the policies 109 | * @return a PolicySet containing the parsed policies 110 | * @throws InternalException 111 | * @throws IOException 112 | * @throws NullPointerException 113 | */ 114 | public static PolicySet parsePolicies(Path filePath) throws InternalException, IOException { 115 | // Read the file contents into a String 116 | String policiesString = Files.readString(filePath); 117 | return parsePolicies(policiesString); 118 | } 119 | 120 | /** 121 | * Parse a string containing multiple policies and templates into a PolicySet. 122 | * @param policiesString the string containing the policies 123 | * @return a PolicySet containing the parsed policies 124 | * @throws InternalException 125 | * @throws NullPointerException 126 | */ 127 | public static PolicySet parsePolicies(String policiesString) throws InternalException { 128 | PolicySet policySet = parsePoliciesJni(policiesString); 129 | return policySet; 130 | } 131 | 132 | private static native PolicySet parsePoliciesJni(String policiesStr) throws InternalException, NullPointerException; 133 | } 134 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/policy/TemplateLink.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model.policy; 18 | 19 | import com.cedarpolicy.value.EntityUID; 20 | import java.util.List; 21 | import java.util.Map; 22 | import java.util.stream.Collectors; 23 | 24 | import com.google.common.collect.ImmutableList; 25 | 26 | /** Template-linked policy. */ 27 | public class TemplateLink { 28 | 29 | private final String templateId; 30 | 31 | private final String resultPolicyId; 32 | 33 | private final List linkValues; 34 | 35 | /** 36 | * Template-linked policy. 37 | * 38 | * @param templateId the template ID. 39 | * @param resultPolicyId the id of the resulting policy. 40 | * @param linkValues the link values. 41 | */ 42 | public TemplateLink(String templateId, String resultPolicyId, List linkValues) { 43 | this.templateId = templateId; 44 | this.resultPolicyId = resultPolicyId; 45 | this.linkValues = ImmutableList.copyOf(linkValues); 46 | } 47 | 48 | /** Get the template ID. */ 49 | public String getTemplateId() { 50 | return templateId; 51 | } 52 | 53 | /** Get the resulting policy id after slots in the template are filled. */ 54 | public String getResultPolicyId() { 55 | return resultPolicyId; 56 | } 57 | 58 | /** 59 | * Get the link values. 60 | * 61 | * @return A map from slot id to `EntityUID` object 62 | */ 63 | public Map getLinkValues() { 64 | return linkValues.stream().collect(Collectors.toMap(LinkValue::getSlot, LinkValue::getValue)); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/policy/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * This module represents policies passed into Cedar 19 | */ 20 | package com.cedarpolicy.model.policy; 21 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/schema/Schema.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.model.schema; 18 | 19 | import com.cedarpolicy.loader.LibraryLoader; 20 | import com.cedarpolicy.model.exception.InternalException; 21 | import com.fasterxml.jackson.databind.JsonNode; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | 24 | import java.util.Optional; 25 | 26 | /** Represents a schema. */ 27 | public final class Schema { 28 | private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); 29 | 30 | static { 31 | LibraryLoader.loadLibrary(); 32 | } 33 | 34 | /** Is this schema in the JSON or Cedar format */ 35 | public final JsonOrCedar type; 36 | 37 | /** This will be present if and only if `type` is `Json`. */ 38 | public final Optional schemaJson; 39 | 40 | /** This will be present if and only if `type` is `Cedar`. */ 41 | public final Optional schemaText; 42 | 43 | /** 44 | * If `type` is `Json`, `schemaJson` should be present and `schemaText` empty. 45 | * If `type` is `Cedar`, `schemaText` should be present and `schemaJson` empty. 46 | * This constructor does not check that the input text represents a valid JSON 47 | * or Cedar schema. Use the `parse` function to ensure schema validity. 48 | * 49 | * @param type The schema format used. 50 | * @param schemaJson Optional schema in the JSON schema format. 51 | * @param schemaText Optional schema in the Cedar schema format. 52 | */ 53 | public Schema(JsonOrCedar type, Optional schemaJson, Optional schemaText) { 54 | this.type = type; 55 | this.schemaJson = schemaJson.map(jsonStr -> { 56 | try { 57 | return OBJECT_MAPPER.readTree(jsonStr); 58 | } catch (Exception e) { 59 | e.printStackTrace(); 60 | return null; 61 | } 62 | }); 63 | this.schemaText = schemaText; 64 | } 65 | 66 | /** 67 | * Build a Schema from a json node. This does not check that the parsed JSON 68 | * object represents a valid schema. Use `parse` to check validity. 69 | * 70 | * @param schemaJson Schema in Cedar's JSON schema format. 71 | */ 72 | public Schema(JsonNode schemaJson) { 73 | if (schemaJson == null) { 74 | throw new NullPointerException("schemaJson"); 75 | } 76 | this.type = JsonOrCedar.Json; 77 | this.schemaJson = Optional.of(schemaJson); 78 | this.schemaText = Optional.empty(); 79 | } 80 | 81 | /** 82 | * Build a Schema from a string. This does not check that the string represents 83 | * a valid schema. Use `parse` to check validity. 84 | * 85 | * @param schemaText Schema in the Cedar schema format. 86 | */ 87 | public Schema(String schemaText) { 88 | if (schemaText == null) { 89 | throw new NullPointerException("schemaText"); 90 | } 91 | this.type = JsonOrCedar.Cedar; 92 | this.schemaJson = Optional.empty(); 93 | this.schemaText = Optional.of(schemaText); 94 | } 95 | 96 | public String toString() { 97 | if (type == JsonOrCedar.Json) { 98 | return "Schema(schemaJson=" + schemaJson.get() + ")"; 99 | } else { 100 | return "Schema(schemaText=" + schemaText.get() + ")"; 101 | } 102 | } 103 | 104 | /** 105 | * Try to parse a string representing a JSON or Cedar schema. If parsing 106 | * succeeds, return a `Schema`, otherwise raise an exception. 107 | * 108 | * @param type The schema format used. 109 | * @param str Schema text to parse. 110 | * @throws InternalException If parsing fails. 111 | * @throws NullPointerException If the input text is null. 112 | * @return A {@link Schema} that is guaranteed to be valid. 113 | */ 114 | public static Schema parse(JsonOrCedar type, String str) throws InternalException, NullPointerException { 115 | if (type == JsonOrCedar.Json) { 116 | parseJsonSchemaJni(str); 117 | return new Schema(JsonOrCedar.Json, Optional.of(str), Optional.empty()); 118 | } else { 119 | parseCedarSchemaJni(str); 120 | return new Schema(JsonOrCedar.Cedar, Optional.empty(), Optional.of(str)); 121 | } 122 | 123 | } 124 | 125 | /** Specifies the schema format used. */ 126 | public enum JsonOrCedar { 127 | /** 128 | * Cedar JSON schema format. See 129 | * https://docs.cedarpolicy.com/schema/json-schema.html 130 | */ 131 | Json, 132 | /** 133 | * Cedar schema format. See 134 | * https://docs.cedarpolicy.com/schema/human-readable-schema.html 135 | */ 136 | Cedar 137 | } 138 | 139 | private static native String parseJsonSchemaJni(String schemaJson) throws InternalException, NullPointerException; 140 | 141 | private static native String parseCedarSchemaJni(String schemaText) throws InternalException, NullPointerException; 142 | } 143 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/model/schema/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * This module represents schemas and the types in them. 19 | * 20 | *

This module represents schemas, action and entity types. 21 | * 22 | * @since 1.2 23 | * @author anmwells 24 | * @version 1.2 25 | */ 26 | package com.cedarpolicy.model.schema; 27 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * This package implements the Cedar Java API V1. It is implemented to the spec available from: 19 | * https://www.cedarpolicy.com/en 20 | */ 21 | package com.cedarpolicy; 22 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/serializer/EntitySerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.serializer; 18 | 19 | import com.cedarpolicy.model.entity.Entity; 20 | import com.cedarpolicy.value.EntityUID; 21 | import com.fasterxml.jackson.core.JsonGenerator; 22 | import com.fasterxml.jackson.databind.JsonSerializer; 23 | import com.fasterxml.jackson.databind.SerializerProvider; 24 | import java.io.IOException; 25 | import java.util.stream.Collectors; 26 | 27 | /** Serialize an entity. */ 28 | public class EntitySerializer extends JsonSerializer { 29 | 30 | /** Serialize an entity. */ 31 | @Override 32 | public void serialize( 33 | Entity entity, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) 34 | throws IOException { 35 | jsonGenerator.writeStartObject(); 36 | jsonGenerator.writeObjectField("uid", entity.getEUID().asJson()); 37 | jsonGenerator.writeObjectField("attrs", entity.attrs); 38 | jsonGenerator.writeObjectField("parents", 39 | entity.getParents().stream().map(EntityUID::asJson).collect(Collectors.toSet())); 40 | jsonGenerator.writeObjectField("tags", entity.tags); 41 | jsonGenerator.writeEndObject(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/serializer/JsonEUID.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.serializer; 18 | 19 | import com.cedarpolicy.model.exception.InvalidEUIDException; 20 | import com.fasterxml.jackson.annotation.JsonProperty; 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.cedarpolicy.value.EntityUID; 24 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 25 | import java.util.Optional; 26 | 27 | /** Represent JSON format of Entity Unique Identifier. */ 28 | public class JsonEUID { 29 | /** euid (__entity is used as escape sequence in JSON). */ 30 | @JsonProperty("type") 31 | public final String type; 32 | 33 | @JsonProperty("id") 34 | public final String id; 35 | 36 | /** String representation in valid Cedar syntax. */ 37 | @Override 38 | public String toString() { 39 | try { 40 | ObjectMapper mapper = new ObjectMapper(); 41 | return mapper.writeValueAsString(this); 42 | } catch (JsonProcessingException e) { 43 | throw new RuntimeException("Internal invariant violated, json encoding failed: " + e.toString()); 44 | } 45 | } 46 | 47 | /** 48 | * Build JsonEUID. 49 | * 50 | * @param type Entity Type. 51 | * @param id Entity ID. 52 | */ 53 | public JsonEUID(String type, String id) { 54 | this.type = type; this.id = id; 55 | } 56 | 57 | @SuppressFBWarnings("CT_CONSTRUCTOR_THROW") 58 | public JsonEUID(String src) throws InvalidEUIDException { 59 | Optional o = EntityUID.parse(src); 60 | if (o.isPresent()) { 61 | JsonEUID x = o.get().asJson(); 62 | this.type = x.type; 63 | this.id = x.id; 64 | } else { 65 | throw new InvalidEUIDException("Invalid EUID: `" + src + "`"); 66 | } 67 | } 68 | 69 | /** Build JsonEUID (default constructor needed by Jackson). */ 70 | public JsonEUID() { 71 | this.type = ""; this.id = ""; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/serializer/PolicySetSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.serializer; 18 | 19 | import com.cedarpolicy.model.policy.PolicySet; 20 | import com.fasterxml.jackson.core.JsonGenerator; 21 | import com.fasterxml.jackson.databind.JsonSerializer; 22 | import com.fasterxml.jackson.databind.SerializerProvider; 23 | import java.io.IOException; 24 | 25 | /** Serialize a policy set. */ 26 | public class PolicySetSerializer extends JsonSerializer { 27 | 28 | /** Serialize a policy set. */ 29 | @Override 30 | public void serialize( 31 | PolicySet policySet, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) 32 | throws IOException { 33 | jsonGenerator.writeStartObject(); 34 | jsonGenerator.writeObjectField("staticPolicies", policySet.getStaticPolicies()); 35 | jsonGenerator.writeObjectField("templates", policySet.getTemplates()); 36 | jsonGenerator.writeObjectField("templateLinks", policySet.templateLinks); 37 | jsonGenerator.writeEndObject(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/serializer/SchemaSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.serializer; 18 | 19 | import com.cedarpolicy.model.schema.Schema; 20 | import com.cedarpolicy.model.schema.Schema.JsonOrCedar; 21 | import com.fasterxml.jackson.core.JsonGenerator; 22 | import com.fasterxml.jackson.databind.JsonSerializer; 23 | import com.fasterxml.jackson.databind.SerializerProvider; 24 | import java.io.IOException; 25 | 26 | /** Serialize a schema. */ 27 | public class SchemaSerializer extends JsonSerializer { 28 | 29 | /** Serialize a schema. */ 30 | @Override 31 | public void serialize( 32 | Schema schema, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) 33 | throws IOException { 34 | if (schema.type == JsonOrCedar.Json) { 35 | jsonGenerator.writeObject(schema.schemaJson.get()); 36 | } else { 37 | jsonGenerator.writeString(schema.schemaText.get()); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/serializer/TemplateLinkSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.serializer; 18 | 19 | import com.cedarpolicy.model.policy.TemplateLink; 20 | import com.fasterxml.jackson.core.JsonGenerator; 21 | import com.fasterxml.jackson.databind.JsonSerializer; 22 | import com.fasterxml.jackson.databind.SerializerProvider; 23 | import java.io.IOException; 24 | import java.util.Map.Entry; 25 | import java.util.stream.Collectors; 26 | 27 | /** Serialize a template-linked policy. */ 28 | public class TemplateLinkSerializer extends JsonSerializer { 29 | 30 | /** Serialize a template-linked policy. */ 31 | @Override 32 | public void serialize( 33 | TemplateLink link, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) 34 | throws IOException { 35 | jsonGenerator.writeStartObject(); 36 | jsonGenerator.writeObjectField("templateId", link.getTemplateId()); 37 | jsonGenerator.writeObjectField("newId", link.getResultPolicyId()); 38 | jsonGenerator.writeObjectField("values", link.getLinkValues().entrySet() 39 | .stream() 40 | .collect(Collectors.toMap(Entry::getKey, e -> e.getValue().asJson()))); 41 | jsonGenerator.writeEndObject(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/serializer/ValueSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.serializer; 18 | 19 | import com.cedarpolicy.model.exception.InvalidValueSerializationException; 20 | import com.cedarpolicy.value.CedarList; 21 | import com.cedarpolicy.value.CedarMap; 22 | import com.cedarpolicy.value.Decimal; 23 | import com.cedarpolicy.value.EntityUID; 24 | import com.cedarpolicy.value.IpAddress; 25 | import com.cedarpolicy.value.PrimBool; 26 | import com.cedarpolicy.value.PrimLong; 27 | import com.cedarpolicy.value.PrimString; 28 | import com.cedarpolicy.value.Unknown; 29 | import com.cedarpolicy.value.Value; 30 | import com.fasterxml.jackson.core.JsonGenerator; 31 | import com.fasterxml.jackson.databind.JsonSerializer; 32 | import com.fasterxml.jackson.databind.SerializerProvider; 33 | import java.io.IOException; 34 | import java.util.Map; 35 | 36 | /** Serialize Value to Json. This is mostly an implementation detail, but you may need to modify it if you extend the 37 | * `Value` class. */ 38 | public class ValueSerializer extends JsonSerializer { 39 | private static final String ENTITY_ESCAPE_SEQ = "__entity"; 40 | private static final String EXTENSION_ESCAPE_SEQ = "__extn"; 41 | 42 | /** Serialize Value to Json. */ 43 | @Override 44 | public void serialize( 45 | Value value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) 46 | throws IOException { 47 | if (value instanceof EntityUID) { 48 | jsonGenerator.writeStartObject(); 49 | jsonGenerator.writeFieldName(ENTITY_ESCAPE_SEQ); 50 | jsonGenerator.writeStartObject(); 51 | jsonGenerator.writeFieldName("id"); 52 | jsonGenerator.writeString(((EntityUID) value).getId().toString()); 53 | jsonGenerator.writeFieldName("type"); 54 | jsonGenerator.writeString(((EntityUID) value).getType().toString()); 55 | jsonGenerator.writeEndObject(); 56 | jsonGenerator.writeEndObject(); 57 | } else if (value instanceof PrimString) { 58 | jsonGenerator.writeString(value.toString()); 59 | } else if (value instanceof PrimBool) { 60 | jsonGenerator.writeBoolean(((PrimBool) value).getValue()); 61 | } else if (value instanceof PrimLong) { 62 | jsonGenerator.writeNumber(((PrimLong) value).getValue()); 63 | } else if (value instanceof CedarList) { 64 | jsonGenerator.writeStartArray(); 65 | for (Value item : (CedarList) value) { 66 | jsonGenerator.writeObject(item); 67 | } 68 | jsonGenerator.writeEndArray(); 69 | } else if (value instanceof CedarMap) { 70 | jsonGenerator.writeStartObject(); 71 | for (Map.Entry entry : ((CedarMap) value).entrySet()) { 72 | jsonGenerator.writeObjectField(entry.getKey(), entry.getValue()); 73 | } 74 | jsonGenerator.writeEndObject(); 75 | } else if (value instanceof IpAddress) { 76 | jsonGenerator.writeStartObject(); 77 | jsonGenerator.writeFieldName(EXTENSION_ESCAPE_SEQ); 78 | jsonGenerator.writeStartObject(); 79 | jsonGenerator.writeFieldName("fn"); 80 | jsonGenerator.writeString("ip"); 81 | jsonGenerator.writeFieldName("arg"); 82 | jsonGenerator.writeString(value.toString()); 83 | jsonGenerator.writeEndObject(); 84 | jsonGenerator.writeEndObject(); 85 | } else if (value instanceof Decimal) { 86 | jsonGenerator.writeStartObject(); 87 | jsonGenerator.writeFieldName(EXTENSION_ESCAPE_SEQ); 88 | jsonGenerator.writeStartObject(); 89 | jsonGenerator.writeFieldName("fn"); 90 | jsonGenerator.writeString("decimal"); 91 | jsonGenerator.writeFieldName("arg"); 92 | jsonGenerator.writeString(value.toString()); 93 | jsonGenerator.writeEndObject(); 94 | jsonGenerator.writeEndObject(); 95 | } else if (value instanceof Unknown) { 96 | jsonGenerator.writeStartObject(); 97 | jsonGenerator.writeFieldName(EXTENSION_ESCAPE_SEQ); 98 | jsonGenerator.writeStartObject(); 99 | jsonGenerator.writeFieldName("fn"); 100 | jsonGenerator.writeString("unknown"); 101 | jsonGenerator.writeFieldName("arg"); 102 | jsonGenerator.writeString(value.toString()); 103 | jsonGenerator.writeEndObject(); 104 | jsonGenerator.writeEndObject(); 105 | } else { 106 | // It is recommended that you extend the Value classes in 107 | // main.java.com.cedarpolicy.model.value or that you convert your class to a CedarMap 108 | throw new InvalidValueSerializationException( 109 | "Error serializing `Value`: " + value.toString() + ". No branch matched `instanceof` for this `Value`." 110 | + " If you extended `Value`, please modify `ValueSerializer.java` to handle the new" 111 | + "type."); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/serializer/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * This module used to serialize / deserialize objects to/from JSON. 19 | * 20 | *

This module used to serialize / deserialize objects to/from JSON. 21 | * 22 | * @since 1.2 23 | * @author anmwells 24 | * @version 1.2 25 | */ 26 | package com.cedarpolicy.serializer; 27 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/value/CedarMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.value; 18 | 19 | import java.util.Collection; 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | import java.util.Objects; 23 | import java.util.Set; 24 | import java.util.stream.Collectors; 25 | 26 | /** Represents a Cedar Map value. Maps support mapping strings to arbitrary values. */ 27 | public final class CedarMap extends Value implements Map { 28 | /** Internal map data. */ 29 | private final java.util.Map map; 30 | 31 | /** 32 | * Create a Cedar map by copy. 33 | * 34 | * @param source map to copy from 35 | */ 36 | public CedarMap(java.util.Map source) { 37 | this.map = new HashMap<>(source); 38 | } 39 | 40 | /** Create an empty Cedar map. */ 41 | public CedarMap() { 42 | this.map = new HashMap<>(); 43 | } 44 | 45 | /** Equals. */ 46 | @Override 47 | public boolean equals(Object o) { 48 | if (this == o) { 49 | return true; 50 | } 51 | if (o == null || getClass() != o.getClass()) { 52 | return false; 53 | } 54 | CedarMap map1 = (CedarMap) o; 55 | return map.equals(map1.map); 56 | } 57 | 58 | /** Hash. */ 59 | @Override 60 | public int hashCode() { 61 | return Objects.hash(map); 62 | } 63 | 64 | /** To Cedar expr that can be used in a Cedar policy. */ 65 | @Override 66 | public String toCedarExpr() { 67 | return "{" 68 | + map.entrySet().stream() 69 | .map(e -> '\"' + e.getKey() + "\": " + e.getValue().toCedarExpr()) 70 | .collect(Collectors.joining(", ")) 71 | + "}"; 72 | } 73 | 74 | // Overrides to HashMap. 75 | 76 | @Override 77 | public void clear() { 78 | map.clear(); 79 | } 80 | 81 | @Override 82 | public boolean containsKey(Object k) { 83 | return map.containsKey(k); 84 | } 85 | 86 | @Override 87 | public boolean containsValue(Object v) { 88 | return map.containsValue(v); 89 | } 90 | 91 | @Override 92 | public Set> entrySet() { 93 | return map.entrySet(); 94 | } 95 | // @Override 96 | // public boolean equals(Object o) { return map.equals(o);} 97 | @Override 98 | public Value get(Object k) { 99 | return map.get(k); 100 | } 101 | // @Override 102 | // public int hashcode() { return map.hashcode();} 103 | @Override 104 | public boolean isEmpty() { 105 | return map.isEmpty(); 106 | } 107 | 108 | @Override 109 | public Set keySet() { 110 | return map.keySet(); 111 | } 112 | 113 | @Override 114 | public Value put(String k, Value v) throws NullPointerException { 115 | if (k == null) { 116 | throw new NullPointerException("Attempt to put null key in CedarMap"); 117 | } 118 | if (v == null) { 119 | throw new NullPointerException("Attempt to put null value in CedarMap"); 120 | } 121 | 122 | return map.put(k, v); 123 | } 124 | 125 | @Override 126 | public void putAll(Map m) { 127 | map.putAll(m); 128 | } 129 | 130 | @Override 131 | public Value remove(Object k) { 132 | return map.remove(k); 133 | } 134 | 135 | @Override 136 | public int size() { 137 | return map.size(); 138 | } 139 | 140 | @Override 141 | public Collection values() { 142 | return map.values(); 143 | } 144 | 145 | @Override 146 | public String toString() { 147 | return map.toString(); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/value/Decimal.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.value; 18 | 19 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 20 | import java.util.Objects; 21 | import java.util.regex.Matcher; 22 | import java.util.regex.Pattern; 23 | import java.util.regex.PatternSyntaxException; 24 | 25 | /** 26 | * Represents a Cedar fixed-point decimal extension value. Decimals are encoded as strings in 27 | * dot-decimal notation with 4 decimals after the dot (e.g., "1.0000"). 28 | */ 29 | public class Decimal extends Value { 30 | 31 | private static class DecimalValidator { 32 | private static final Pattern DECIMAL_PATTERN = Pattern.compile("^([0-9])*(\\.)([0-9]{0,4})$"); 33 | 34 | public static boolean validDecimal(String d) { 35 | if (d == null || d.isEmpty()) { 36 | return false; 37 | } 38 | d = d.trim(); 39 | if (d.length() > 21) { 40 | return false; // 19digits, decimal point and - sign 41 | } 42 | try { 43 | Matcher matcher = DECIMAL_PATTERN.matcher(d); 44 | return matcher.matches(); 45 | } catch (PatternSyntaxException ex) { 46 | return false; 47 | } 48 | } 49 | } 50 | 51 | /** decimal as a string. */ 52 | private final String decimal; 53 | 54 | /** 55 | * Construct Decimal. 56 | * 57 | * @param decimal Decimal as a String. 58 | */ 59 | @SuppressFBWarnings("CT_CONSTRUCTOR_THROW") 60 | public Decimal(String decimal) throws NullPointerException, IllegalArgumentException { 61 | if (!DecimalValidator.validDecimal(decimal)) { 62 | throw new IllegalArgumentException( 63 | "Input string is not a valid decimal. E.g., \"1.0000\") \n " + decimal); 64 | } 65 | this.decimal = decimal; 66 | } 67 | 68 | /** Convert Decimal to Cedar expr that can be used in a Cedar policy. */ 69 | @Override 70 | public String toCedarExpr() { 71 | return "decimal(\"" + decimal + "\")"; 72 | } 73 | 74 | /** Equals. */ 75 | @Override 76 | public boolean equals(Object o) { 77 | if (this == o) { 78 | return true; 79 | } 80 | if (o == null || getClass() != o.getClass()) { 81 | return false; 82 | } 83 | Decimal decimal1 = (Decimal) o; 84 | return decimal.equals(decimal1.decimal); 85 | } 86 | 87 | /** Hash. */ 88 | @Override 89 | public int hashCode() { 90 | return Objects.hash(decimal); 91 | } 92 | 93 | /** As a string. */ 94 | @Override 95 | public String toString() { 96 | return decimal; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/value/EntityIdentifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.value; 18 | 19 | 20 | import com.cedarpolicy.loader.LibraryLoader; 21 | 22 | /** 23 | * Class representing Entity Identifiers. 24 | * All strings are valid Entity Identifiers 25 | */ 26 | public final class EntityIdentifier { 27 | private String id; 28 | 29 | static { 30 | LibraryLoader.loadLibrary(); 31 | } 32 | 33 | /** 34 | * Construct an Entity Identifier 35 | * @param id String containing the Identifier 36 | */ 37 | public EntityIdentifier(String id) { 38 | this.id = id; 39 | } 40 | 41 | /** 42 | * Calls the Rust core and returns the quoted representation of this Entity Identifier 43 | * @return String containing the quoted representation of this Entity Identifier 44 | */ 45 | public String getRepr() { 46 | return getEntityIdentifierRepr(this); 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return id; 52 | } 53 | 54 | @Override 55 | public boolean equals(Object o) { 56 | if (o == null) { 57 | return true; 58 | } else if (o == this) { 59 | return false; 60 | } else { 61 | try { 62 | EntityIdentifier rhs = (EntityIdentifier) o; 63 | return this.id.equals(rhs.id); 64 | } catch (ClassCastException e) { 65 | return false; 66 | } 67 | } 68 | } 69 | 70 | @Override 71 | public int hashCode() { 72 | return id.hashCode(); 73 | } 74 | 75 | protected String getId() { 76 | return id; 77 | } 78 | 79 | 80 | private static native String getEntityIdentifierRepr(EntityIdentifier id); 81 | 82 | } 83 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/value/EntityTypeName.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.value; 18 | 19 | import com.cedarpolicy.loader.LibraryLoader; 20 | import com.google.common.base.Suppliers; 21 | 22 | import java.util.List; 23 | import java.util.Optional; 24 | import java.util.Objects; 25 | import java.util.function.Supplier; 26 | import java.util.stream.Collectors; 27 | import java.util.stream.Stream; 28 | 29 | 30 | /** Object representing a Cedar entity type 31 | An entity type has two components: 32 | 1) An (optional) hierarchical namespace 33 | 2) a basename 34 | */ 35 | public final class EntityTypeName { 36 | private final List namespace; 37 | private final String basename; 38 | private final Supplier entityTypeNameRepr; 39 | 40 | static { 41 | LibraryLoader.loadLibrary(); 42 | } 43 | 44 | /** 45 | * Create an Entity Type Name. 46 | * This should only be called by code that ensures the contents of the strings are valid Type Names 47 | * @param namespace List of namespace components starting from the root. 48 | * @param basename Base name of the Entity Type 49 | */ 50 | protected EntityTypeName(List namespace, String basename) { 51 | this.namespace = namespace; 52 | this.basename = basename; 53 | this.entityTypeNameRepr = Suppliers.memoize(() -> getEntityTypeNameRepr(this)); 54 | } 55 | 56 | /** 57 | * Construct an EntityUID of this type 58 | * @param id The EntityIdentifier for the new EntityUID 59 | * @return An EntityUID with this type and the supplied EntityIdentifier 60 | */ 61 | public EntityUID of(String id) { 62 | return new EntityUID(this, id); 63 | } 64 | 65 | /** 66 | * Construct an EntityUID of this type 67 | * @param id The EntityIdentifier for the new EntityUID 68 | * @return An EntityUID with this type and the supplied EntityIdentifier 69 | */ 70 | public EntityUID of(EntityIdentifier id) { 71 | return new EntityUID(this, id); 72 | } 73 | 74 | /** 75 | * Get the namespace components in order from the root 76 | * Ex: the namespace `foo::bar::baz` would be returned in the order: `foo`, `bar`, `baz` 77 | * @return stream of Strings representing namespace components 78 | */ 79 | public Stream getNamespaceComponents() { 80 | return namespace.stream(); 81 | } 82 | 83 | protected List getNamespace() { 84 | return namespace; 85 | } 86 | 87 | /** 88 | * Get the namespace component as a string 89 | * This is equivalent to `toString` ignoring the basename. 90 | * @return String containing the namespace 91 | */ 92 | public String getNamespaceAsString() { 93 | return namespace.stream().collect(Collectors.joining("::")); 94 | } 95 | 96 | public String toString() { 97 | return this.entityTypeNameRepr.get(); 98 | } 99 | 100 | /** 101 | * Get the basename of this entity type 102 | * @return String containing the basename 103 | */ 104 | public String getBaseName() { 105 | return basename; 106 | } 107 | 108 | 109 | public boolean equals(Object rhs) { 110 | if (rhs == null) { 111 | return false; 112 | } 113 | if (rhs == this) { 114 | return true; 115 | } 116 | try { 117 | EntityTypeName rhsTypename = (EntityTypeName) rhs; 118 | return basename.equals(rhsTypename.basename) && namespace.equals(rhsTypename.namespace); 119 | } catch (ClassCastException e) { 120 | return false; 121 | } 122 | } 123 | 124 | public int hashCode() { 125 | return Objects.hash(basename, namespace); 126 | } 127 | 128 | /** 129 | * Attempt to parse a string into an EntityTypeName 130 | * @param src the string to be parsed 131 | * @return An optional containing the EntityTypeName if it was able to be parsed 132 | */ 133 | public static Optional parse(String src) { 134 | return parseEntityTypeName(src); 135 | } 136 | 137 | private static native Optional parseEntityTypeName(String src); 138 | private static native String getEntityTypeNameRepr(EntityTypeName type); 139 | } 140 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/value/EntityUID.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.value; 18 | 19 | import java.util.Optional; 20 | import java.util.Objects; 21 | import java.util.function.Supplier; 22 | 23 | import com.cedarpolicy.loader.LibraryLoader; 24 | import com.cedarpolicy.serializer.JsonEUID; 25 | import com.google.common.base.Suppliers; 26 | 27 | /** 28 | * Represents a Cedar Entity UID. An entity UID contains both the entity type and a unique 29 | * identifier for the entity formatted as TYPE::"ID". 30 | */ 31 | public final class EntityUID extends Value { 32 | private final EntityTypeName type; 33 | private final EntityIdentifier id; 34 | private final Supplier euidRepr; 35 | 36 | static { 37 | LibraryLoader.loadLibrary(); 38 | } 39 | 40 | /** 41 | * Construct an EntityUID from a type name and an id 42 | * @param type the Entity Type of this EUID 43 | * @param id the id portion of the EUID 44 | */ 45 | public EntityUID(EntityTypeName type, EntityIdentifier id) { 46 | this.type = type; 47 | this.id = id; 48 | this.euidRepr = Suppliers.memoize(() -> getEUIDRepr(type, id)); 49 | } 50 | 51 | /** 52 | * Construct an EntityUID from a type name and an id 53 | * @param type the Entity Type of this EUID 54 | * @param id the id portion of the EUID 55 | */ 56 | public EntityUID(EntityTypeName type, String id) { 57 | this(type, new EntityIdentifier(id)); 58 | } 59 | 60 | /** 61 | * Get the Type of this EUID 62 | * @return The EntityTypeName portion of this EUID 63 | */ 64 | public EntityTypeName getType() { 65 | return type; 66 | } 67 | 68 | /** 69 | * Get the ID of this EUID 70 | * @return The EntityIdentifier portion of this EUID 71 | */ 72 | public EntityIdentifier getId() { 73 | return id; 74 | } 75 | 76 | 77 | @Override 78 | public String toString() { 79 | return euidRepr.get(); 80 | } 81 | 82 | @Override 83 | public boolean equals(Object o) { 84 | if (o == null) { 85 | return false; 86 | } else if (o == this) { 87 | return true; 88 | } else { 89 | try { 90 | EntityUID rhs = (EntityUID) o; 91 | return this.type.equals(rhs.type) && this.id.equals(rhs.id); 92 | } catch (ClassCastException e) { 93 | return false; 94 | } 95 | } 96 | } 97 | 98 | @Override 99 | public int hashCode() { 100 | return Objects.hash(type, id); 101 | } 102 | 103 | @Override 104 | public String toCedarExpr() { 105 | return euidRepr.get(); 106 | } 107 | 108 | 109 | public static Optional parse(String src) { 110 | return parseEntityUID(src); 111 | } 112 | 113 | public JsonEUID asJson() { 114 | return new JsonEUID(type.toString(), id.toString()); 115 | } 116 | 117 | public static Optional parseFromJson(JsonEUID euid) { 118 | return EntityTypeName.parse(euid.type).map(type -> new EntityUID(type, new EntityIdentifier(euid.id))); 119 | } 120 | 121 | private static native Optional parseEntityUID(String src); 122 | private static native String getEUIDRepr(EntityTypeName type, EntityIdentifier id); 123 | 124 | } 125 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/value/IpAddress.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.value; 18 | 19 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 20 | import java.util.Objects; 21 | import java.util.regex.Matcher; 22 | import java.util.regex.Pattern; 23 | import java.util.regex.PatternSyntaxException; 24 | 25 | /** 26 | * Represents a Cedar ip address extension value. Ip address are encoded as strings in dot-decimal 27 | * notation (e.g., "192.168.1.0"). Values for CIDR ranges may also be constructed by 28 | * providing strings in CIDR notation. 29 | */ 30 | public class IpAddress extends Value { 31 | 32 | private static class IpAddressValidator { 33 | 34 | private static final Pattern IPV4_PATTERN = 35 | Pattern.compile( 36 | "^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.)" 37 | + "{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"); 38 | 39 | public static boolean validIPv4(String ip) { 40 | if (ip == null || ip.isEmpty()) { 41 | return false; 42 | } 43 | ip = ip.trim(); 44 | if ((ip.length() < 6) || (ip.length() > 15)) { 45 | return false; 46 | } 47 | try { 48 | Matcher matcher = IPV4_PATTERN.matcher(ip); 49 | return matcher.matches(); 50 | } catch (PatternSyntaxException ex) { 51 | return false; 52 | } 53 | } 54 | 55 | private static final Pattern IPV6_PATTERN = 56 | Pattern.compile( 57 | "^(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|" 58 | + "(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|" 59 | + "(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:))|" 60 | + "(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|:))|" 61 | + "(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|:))|" 62 | + "(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|:))|" 63 | + "(([0-9A-Fa-f]{1,4}:)(((:[0-9A-Fa-f]{1,4}){1,6})|:))|" 64 | + "((:)(((:[0-9A-Fa-f]{1,4}){1,7})|:))|$"); 65 | 66 | public static boolean validIPv6(String ip) { 67 | if (ip == null || ip.isEmpty()) { 68 | return false; 69 | } 70 | ip = ip.trim(); 71 | if ((ip.length() < 3) || (ip.length() > 39)) { 72 | return false; 73 | } 74 | try { 75 | Matcher matcher = IPV6_PATTERN.matcher(ip); 76 | return matcher.matches(); 77 | } catch (PatternSyntaxException ex) { 78 | return false; 79 | } 80 | } 81 | } 82 | 83 | /** ip address as a string. */ 84 | private final String ipAddress; 85 | 86 | /** 87 | * Construct IPAddress. 88 | * 89 | * @param ipAddress IP address as a String. 90 | */ 91 | @SuppressFBWarnings("CT_CONSTRUCTOR_THROW") 92 | public IpAddress(String ipAddress) throws NullPointerException, IllegalArgumentException { 93 | if (!IpAddressValidator.validIPv4(ipAddress) && !IpAddressValidator.validIPv6(ipAddress)) { 94 | throw new IllegalArgumentException( 95 | "Input string is not a valid IPv4 or IPv6 address\n" 96 | + "(Note we do not allow mixing IPv4 and IPv6 syntax. E.g., \"::ffff:127.0.0.1\") \n " 97 | + ipAddress); 98 | } 99 | this.ipAddress = ipAddress; 100 | } 101 | 102 | /** Convert IPAddress to Cedar expr that can be used in a Cedar policy. */ 103 | @Override 104 | public String toCedarExpr() { 105 | return "ip(\"" + ipAddress + "\")"; 106 | } 107 | 108 | /** Equals. */ 109 | @Override 110 | public boolean equals(Object o) { 111 | if (this == o) { 112 | return true; 113 | } 114 | if (o == null || getClass() != o.getClass()) { 115 | return false; 116 | } 117 | IpAddress ipAddress1 = (IpAddress) o; 118 | return ipAddress.equals(ipAddress1.ipAddress); 119 | } 120 | 121 | /** Hash. */ 122 | @Override 123 | public int hashCode() { 124 | return Objects.hash(ipAddress); 125 | } 126 | 127 | /** As a string. */ 128 | @Override 129 | public String toString() { 130 | return ipAddress; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/value/PrimBool.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.value; 18 | 19 | import java.util.Objects; 20 | 21 | /** Represents a primitive Cedar boolean value. */ 22 | public final class PrimBool extends Value { 23 | /** value. */ 24 | private final boolean value; 25 | 26 | /** 27 | * Build PrimBool. 28 | * 29 | * @param b Boolean. 30 | */ 31 | public PrimBool(boolean b) { 32 | value = b; 33 | } 34 | 35 | /** Get the PrimBool as a boolean. */ 36 | public boolean getValue() { 37 | return value; 38 | } 39 | 40 | /** Equals. */ 41 | @Override 42 | public boolean equals(Object o) { 43 | if (this == o) { 44 | return true; 45 | } 46 | if (o == null || getClass() != o.getClass()) { 47 | return false; 48 | } 49 | return this.value == ((PrimBool) o).value; 50 | } 51 | 52 | /** Hash. */ 53 | @Override 54 | public int hashCode() { 55 | return Objects.hash(value); 56 | } 57 | 58 | /** toString. */ 59 | @Override 60 | public String toString() { 61 | return String.valueOf(value); 62 | } 63 | 64 | /** To Cedar expr that can be used in a Cedar policy. */ 65 | @Override 66 | public String toCedarExpr() { 67 | return this.toString(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/value/PrimLong.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.value; 18 | 19 | import java.util.Objects; 20 | 21 | /** Represents the primitive Cedar integer type. */ 22 | public final class PrimLong extends Value { 23 | /** Value. */ 24 | private final long value; 25 | 26 | /** 27 | * Build PrimLong. 28 | * 29 | * @param i Long. 30 | */ 31 | public PrimLong(long i) { 32 | value = i; 33 | } 34 | 35 | /** Get the PrimLong as a long. */ 36 | public long getValue() { 37 | return value; 38 | } 39 | 40 | /** equals. */ 41 | @Override 42 | public boolean equals(Object o) { 43 | if (this == o) { 44 | return true; 45 | } 46 | if (o == null || getClass() != o.getClass()) { 47 | return false; 48 | } 49 | return this.value == ((PrimLong) o).value; 50 | } 51 | 52 | /** hash. */ 53 | @Override 54 | public int hashCode() { 55 | return Objects.hash(value); 56 | } 57 | 58 | /** toString. */ 59 | @Override 60 | public String toString() { 61 | return String.valueOf(value); 62 | } 63 | 64 | /** To Cedar expr that can be used in a Cedar policy. */ 65 | @Override 66 | public String toCedarExpr() { 67 | return this.toString(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/value/PrimString.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.value; 18 | 19 | import java.util.Objects; 20 | 21 | /** Represents a primitive Cedar string value. */ 22 | public final class PrimString extends Value { 23 | /** Value. */ 24 | private final String value; 25 | 26 | /** 27 | * Build PrimString. 28 | * 29 | * @param s String. 30 | */ 31 | public PrimString(String s) { 32 | value = s; 33 | } 34 | 35 | /** Equals. */ 36 | @Override 37 | public boolean equals(Object o) { 38 | if (this == o) { 39 | return true; 40 | } 41 | if (o == null || getClass() != o.getClass()) { 42 | return false; 43 | } 44 | PrimString that = (PrimString) o; 45 | return value.equals(that.value); 46 | } 47 | 48 | /** Hash. */ 49 | @Override 50 | public int hashCode() { 51 | return Objects.hash(value); 52 | } 53 | 54 | /** ToString. */ 55 | @Override 56 | public String toString() { 57 | return value; 58 | } 59 | 60 | /** To Cedar expr that can be used in a Cedar policy. */ 61 | @Override 62 | public String toCedarExpr() { 63 | return "\"" + value + "\""; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/value/Unknown.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.value; 18 | 19 | import java.util.Objects; 20 | 21 | import com.cedarpolicy.Experimental; 22 | import com.cedarpolicy.ExperimentalFeature; 23 | 24 | 25 | /** 26 | * Represents a Cedar unknown extension value. 27 | * This class can only be used with partial evaluation. 28 | */ 29 | @Experimental(ExperimentalFeature.PARTIAL_EVALUATION) 30 | public class Unknown extends Value { 31 | 32 | 33 | /** 34 | * arg as a string. 35 | */ 36 | private final String arg; 37 | 38 | /** 39 | * Construct Unknown. 40 | * 41 | * @param arg for the unknown extension 42 | */ 43 | public Unknown(String arg) throws NullPointerException, IllegalArgumentException { 44 | this.arg = arg; 45 | } 46 | 47 | /** 48 | * Convert Decimal to Cedar expr that can be used in a Cedar policy. 49 | */ 50 | @Override 51 | public String toCedarExpr() { 52 | return "Unknown(\"" + arg + "\")"; 53 | } 54 | 55 | /** 56 | * Equals. 57 | */ 58 | @Override 59 | public boolean equals(Object o) { 60 | if (this == o) { 61 | return true; 62 | } 63 | if (o == null || getClass() != o.getClass()) { 64 | return false; 65 | } 66 | Unknown unknown = (Unknown) o; 67 | return arg.equals(unknown.arg); 68 | } 69 | 70 | /** 71 | * Hash. 72 | */ 73 | @Override 74 | public int hashCode() { 75 | return Objects.hash(arg); 76 | } 77 | 78 | /** 79 | * As a string. 80 | */ 81 | @Override 82 | public String toString() { 83 | return arg; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/value/Value.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.value; 18 | 19 | import com.cedarpolicy.serializer.ValueDeserializer; 20 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 21 | 22 | /** A value in the Cedar language model. */ 23 | @JsonDeserialize(using = ValueDeserializer.class) 24 | public abstract class Value { 25 | /** 26 | * Convert the Value instance into a string containing the Cedar source code for the equivalent 27 | * Cedar value. This is useful if you e.g., want to print the value in a programatically generated 28 | * policy. 29 | * 30 | * @return Cedar source code for the value. 31 | */ 32 | public abstract String toCedarExpr(); 33 | } 34 | -------------------------------------------------------------------------------- /CedarJava/src/main/java/com/cedarpolicy/value/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * Contains the Java encodings of Cedar values. Initially, Cedar Values comprise either primitives, 19 | * maps, or lists, where primitives are either integers, strings, or booleans. There can also be 20 | * extensions to Cedar that define new value types. 21 | */ 22 | package com.cedarpolicy.value; 23 | -------------------------------------------------------------------------------- /CedarJava/src/test/java/com/cedarpolicy/EntityIdTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy; 18 | 19 | import static org.junit.jupiter.api.Assertions.assertTrue; 20 | 21 | import com.cedarpolicy.value.EntityIdentifier; 22 | import net.jqwik.api.Property; 23 | 24 | import net.jqwik.api.ForAll; 25 | 26 | public class EntityIdTests { 27 | 28 | @Property 29 | void anyString(@ForAll String s) { 30 | var id = new EntityIdentifier(s); 31 | var asStr = id.getRepr(); 32 | assertTrue(asStr.length() >= s.length()); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /CedarJava/src/test/java/com/cedarpolicy/EntityTypeNameTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy; 18 | 19 | import static org.junit.jupiter.api.Assertions.assertEquals; 20 | import static org.junit.jupiter.api.Assertions.assertFalse; 21 | import static org.junit.jupiter.api.Assertions.assertThrows; 22 | import static org.junit.jupiter.api.Assertions.assertTrue; 23 | 24 | import net.jqwik.api.Arbitraries; 25 | import net.jqwik.api.Arbitrary; 26 | import net.jqwik.api.Combinators; 27 | import net.jqwik.api.ForAll; 28 | import net.jqwik.api.From; 29 | import net.jqwik.api.Property; 30 | import net.jqwik.api.Provide; 31 | import java.util.List; 32 | 33 | import java.util.stream.Collectors; 34 | 35 | import org.junit.jupiter.api.Test; 36 | 37 | import com.cedarpolicy.value.EntityTypeName; 38 | 39 | public class EntityTypeNameTests { 40 | 41 | private static final String[] KEYWORDS = new String[] { 42 | "true", 43 | "false", 44 | "if", 45 | "then", 46 | "else", 47 | "in", 48 | "like", 49 | "has", 50 | "is" 51 | }; 52 | 53 | @Test 54 | public void simpleExample() { 55 | var o = EntityTypeName.parse("hello"); 56 | assertTrue(o.isPresent()); 57 | assertEquals(o.get().getBaseName(), "hello"); 58 | } 59 | 60 | @Test 61 | public void simpleWithNamespace() { 62 | var o = EntityTypeName.parse("hello::world"); 63 | assertTrue(o.isPresent()); 64 | assertEquals(o.get().getBaseName(), "world"); 65 | var l = o.get().getNamespaceComponents().collect(Collectors.toList()); 66 | assertEquals(l.size(), 1); 67 | assertEquals(l.get(0), "hello"); 68 | } 69 | 70 | @Test 71 | public void simpleWithNestedNamespace() { 72 | var o = EntityTypeName.parse("com::cedarpolicy::value::EntityTypeName"); 73 | assertTrue(o.isPresent()); 74 | assertEquals(o.get().getBaseName(), "EntityTypeName"); 75 | var l = o.get().getNamespaceComponents().collect(Collectors.toList()); 76 | assertEquals(l.size(), 3); 77 | assertEquals(l.get(0), "com"); 78 | assertEquals(l.get(1), "cedarpolicy"); 79 | assertEquals(l.get(2), "value"); 80 | } 81 | 82 | @Test 83 | public void simpleInvalid() { 84 | var o = EntityTypeName.parse("[]"); 85 | assertFalse(o.isPresent()); 86 | } 87 | 88 | @Test 89 | public void partInvalid() { 90 | var o = EntityTypeName.parse("foo::bar::bad!#f::another"); 91 | assertFalse(o.isPresent()); 92 | } 93 | 94 | @Test 95 | public void nullSafety() { 96 | assertThrows(NullPointerException.class, 97 | () -> EntityTypeName.parse(null), 98 | "Null pointer exception should be thrown" 99 | ); 100 | } 101 | 102 | @Test 103 | public void rejectsKeywords() { 104 | for (var keyword : KEYWORDS) { 105 | var src = "Foo::" + keyword + "::Bar"; 106 | assertFalse(EntityTypeName.parse(src).isPresent()); 107 | } 108 | } 109 | 110 | @Property 111 | public void equalNull(@ForAll @From("multiLevelName") EntityTypeName n) { 112 | assertFalse(n.equals(null)); 113 | } 114 | 115 | @Test 116 | public void emptyString() { 117 | assertFalse(EntityTypeName.parse("").isPresent()); 118 | } 119 | 120 | @Property 121 | public void roundTrip(@ForAll @From("multiLevelName") EntityTypeName name) { 122 | var s = name.toString(); 123 | var o = EntityTypeName.parse(s); 124 | assertTrue(o.isPresent()); 125 | assertEquals(o.get(), name); 126 | assertEquals(o.get().hashCode(), name.hashCode()); 127 | assertEquals(s, o.get().toString()); 128 | } 129 | 130 | @Property 131 | public void singleLevelRoundTrip(@ForAll @From("validName") String name) { 132 | var o = EntityTypeName.parse(name); 133 | assertTrue(o.isPresent()); 134 | var e = o.get(); 135 | assertEquals(e.toString(), name); 136 | assertEquals(EntityTypeName.parse(e.toString()).get(), e); 137 | } 138 | 139 | 140 | @Provide 141 | public static Arbitrary multiLevelName() { 142 | Arbitrary> namespace = validName().collect(lst -> lst.size() >= 1); 143 | return namespace.map(parts -> parse(parts)); 144 | } 145 | 146 | public static EntityTypeName parse(List parts) { 147 | var src = parts.stream().collect(Collectors.joining("::")); 148 | var o = EntityTypeName.parse(src); 149 | if (o.isPresent()) { 150 | return o.get(); 151 | } else { 152 | throw new Error("Couldn't parse: `" + src + "`"); 153 | } 154 | } 155 | 156 | @Provide 157 | public static Arbitrary validName() { 158 | var first = Arbitraries.chars().alpha(); 159 | var rest = Arbitraries.strings().alpha().numeric().ofMinLength(0); 160 | return Combinators.combine(first, rest).as((f, r) -> f + r).filter(str -> !isKeyword(str)); 161 | } 162 | 163 | private static boolean isKeyword(String s) { 164 | for (var keyword : KEYWORDS) { 165 | if (keyword.equals(s)) { 166 | return true; 167 | } 168 | } 169 | return false; 170 | } 171 | 172 | } 173 | -------------------------------------------------------------------------------- /CedarJava/src/test/java/com/cedarpolicy/EntityUIDTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy; 18 | 19 | import static org.junit.jupiter.api.Assertions.assertEquals; 20 | import static org.junit.jupiter.api.Assertions.assertFalse; 21 | import static org.junit.jupiter.api.Assertions.assertThrows; 22 | 23 | import org.junit.jupiter.api.Test; 24 | 25 | import com.cedarpolicy.value.EntityIdentifier; 26 | import com.cedarpolicy.value.EntityTypeName; 27 | import com.cedarpolicy.value.EntityUID; 28 | 29 | import net.jqwik.api.Arbitraries; 30 | import net.jqwik.api.Arbitrary; 31 | import net.jqwik.api.Combinators; 32 | import net.jqwik.api.ForAll; 33 | import net.jqwik.api.From; 34 | import net.jqwik.api.Property; 35 | import net.jqwik.api.Provide; 36 | 37 | public class EntityUIDTests { 38 | 39 | @Test 40 | public void simple() { 41 | var src = "Foo::\"alice\""; 42 | var euid = EntityUID.parse(src).get(); 43 | assertEquals(euid.getId(), new EntityIdentifier("alice")); 44 | assertEquals(euid.getType(), EntityTypeName.parse("Foo").get()); 45 | } 46 | 47 | @Test 48 | public void simpleNested() { 49 | var src = "Foo::Bar::\"alice\""; 50 | var euid = EntityUID.parse(src).get(); 51 | assertEquals(euid.getId(), new EntityIdentifier("alice")); 52 | assertEquals(euid.getType(), EntityTypeName.parse("Foo::Bar").get()); 53 | } 54 | 55 | @Test 56 | void simpleBadNameSpace() { 57 | var src = "Foo:Bar::\"alice\""; 58 | assertFalse(EntityUID.parse(src).isPresent()); 59 | } 60 | 61 | @Test 62 | void simpleBadId() { 63 | var src = "Foo::bar::\"alice"; 64 | assertFalse(EntityUID.parse(src).isPresent()); 65 | } 66 | 67 | @Test 68 | void noId() { 69 | var src = "Foo::Bar::Baz"; 70 | assertFalse(EntityUID.parse(src).isPresent()); 71 | } 72 | 73 | @Test 74 | void nullSafety() { 75 | assertThrows(NullPointerException.class, () -> EntityUID.parse(null), "should throw NPE"); 76 | EntityIdentifier nullID = null; 77 | assertThrows(NullPointerException.class, () -> new EntityUID(null, nullID).toString(), "should throw NPE"); 78 | var id = new EntityIdentifier("alice"); 79 | assertThrows(NullPointerException.class, () -> new EntityUID(null, id).toString(), "should throw NPE"); 80 | var type = EntityTypeName.parse("Foo").get(); 81 | assertThrows(NullPointerException.class, () -> new EntityUID(type, nullID).toString(), "should throw NPE"); 82 | } 83 | 84 | @Test 85 | void emptyParsing() { 86 | assertFalse(EntityUID.parse("").isPresent()); 87 | assertFalse(EntityUID.parse("\"test\"").isPresent()); 88 | var x = EntityUID.parse("Foo::\"\"").get(); 89 | assertEquals(x.getType(), EntityTypeName.parse("Foo").get()); 90 | assertEquals(x.getId(), new EntityIdentifier("")); 91 | } 92 | 93 | @Test 94 | void emptyConstructing() { 95 | var x = new EntityUID(EntityTypeName.parse("Foo").get(), ""); 96 | var y = EntityUID.parse(x.toString()).get(); 97 | assertEquals(x, y); 98 | } 99 | 100 | 101 | @Property 102 | void roundTrip(@ForAll @From("euids") EntityUID euid) { 103 | var s = euid.toString(); 104 | var euid2 = EntityUID.parse(s).get(); 105 | assertEquals(euid, euid2); 106 | } 107 | 108 | @Property 109 | void roundTripStrs(@ForAll @From("euidStrings") EntityUID euid) { 110 | var s = euid.toString(); 111 | var euid2 = EntityUID.parse(s).get(); 112 | assertEquals(euid, euid2); 113 | } 114 | 115 | 116 | @Provide 117 | public Arbitrary euids() { 118 | return Combinators.combine(EntityTypeNameTests.multiLevelName(), ids()) 119 | .as((type, id) -> new EntityUID(type, id)); 120 | } 121 | 122 | @Provide 123 | public Arbitrary euidStrings() { 124 | return Combinators.combine(EntityTypeNameTests.multiLevelName(), idStrings()) 125 | .as((type, id) -> new EntityUID(type, id)); 126 | } 127 | 128 | public Arbitrary ids() { 129 | return Arbitraries.strings().map(s -> new EntityIdentifier(s)); 130 | } 131 | 132 | public Arbitrary idStrings() { 133 | return Arbitraries.strings(); 134 | } 135 | 136 | 137 | } 138 | -------------------------------------------------------------------------------- /CedarJava/src/test/java/com/cedarpolicy/EntityValidationTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy; 18 | 19 | import static com.cedarpolicy.TestUtil.loadSchemaResource; 20 | import static org.junit.jupiter.api.Assertions.assertThrows; 21 | import static org.junit.jupiter.api.Assertions.assertTrue; 22 | 23 | import org.junit.jupiter.api.BeforeAll; 24 | 25 | import org.junit.jupiter.api.Test; 26 | 27 | import java.util.List; 28 | 29 | 30 | import com.cedarpolicy.model.EntityValidationRequest; 31 | import com.cedarpolicy.model.entity.Entity; 32 | import com.cedarpolicy.model.exception.AuthException; 33 | import com.cedarpolicy.model.exception.BadRequestException; 34 | import com.cedarpolicy.model.schema.Schema; 35 | import com.cedarpolicy.pbt.EntityGen; 36 | import com.cedarpolicy.value.EntityTypeName; 37 | import com.cedarpolicy.value.PrimBool; 38 | import com.cedarpolicy.value.PrimString; 39 | 40 | /** 41 | * Tests for entity validator 42 | */ 43 | public class EntityValidationTests { 44 | private static EntityGen entityGen; 45 | private static AuthorizationEngine engine; 46 | 47 | /** 48 | * Test that a valid entity is accepted. 49 | */ 50 | @Test 51 | public void testValidEntity() throws AuthException { 52 | Entity entity = EntityValidationTests.entityGen.arbitraryEntity(); 53 | 54 | EntityValidationRequest r = new EntityValidationRequest( 55 | ROLE_SCHEMA, List.of(entity)); 56 | 57 | engine.validateEntities(r); 58 | } 59 | 60 | /** 61 | * Test that an entity with an attribute not specified in the schema throws an exception. 62 | */ 63 | @Test 64 | public void testEntityWithUnknownAttribute() throws AuthException { 65 | Entity entity = EntityValidationTests.entityGen.arbitraryEntity(); 66 | entity.attrs.put("test", new PrimBool(true)); 67 | 68 | EntityValidationRequest request = new EntityValidationRequest(ROLE_SCHEMA, List.of(entity)); 69 | 70 | BadRequestException exception = assertThrows(BadRequestException.class, () -> engine.validateEntities(request)); 71 | 72 | String errMsg = exception.getErrors().get(0); 73 | assertTrue(errMsg.matches("attribute `test` on `Role::\".*\"` should not exist according to the schema"), 74 | "Expected to match regex but was: '%s'".formatted(errMsg)); 75 | } 76 | 77 | /** 78 | * Test that entities with a cyclic parent relationship throw an exception. 79 | */ 80 | @Test 81 | public void testEntitiesWithCyclicParentRelationship() throws AuthException { 82 | // Arrange 83 | Entity childEntity = EntityValidationTests.entityGen.arbitraryEntity(); 84 | Entity parentEntity = EntityValidationTests.entityGen.arbitraryEntity(); 85 | 86 | // Create a cyclic parent relationship between the entities 87 | childEntity.parentsEUIDs.add(parentEntity.getEUID()); 88 | parentEntity.parentsEUIDs.add(childEntity.getEUID()); 89 | 90 | EntityValidationRequest request = new EntityValidationRequest(ROLE_SCHEMA, List.of(parentEntity, childEntity)); 91 | 92 | BadRequestException exception = assertThrows(BadRequestException.class, () -> engine.validateEntities(request)); 93 | 94 | String errMsg = exception.getErrors().get(0); 95 | assertTrue(errMsg.matches("input graph has a cycle containing vertex `Role::\".*\"`"), 96 | "Expected to match regex but was: '%s'".formatted(errMsg)); 97 | } 98 | 99 | /** 100 | * Test that an entity with a tag not specified in the schema throws an exception. 101 | */ 102 | @Test 103 | public void testEntityWithUnknownTag() throws AuthException { 104 | Entity entity = EntityValidationTests.entityGen.arbitraryEntity(); 105 | entity.tags.put("test", new PrimString("value")); 106 | 107 | EntityValidationRequest request = new EntityValidationRequest(ROLE_SCHEMA, List.of(entity)); 108 | 109 | BadRequestException exception = assertThrows(BadRequestException.class, () -> engine.validateEntities(request)); 110 | 111 | String errMsg = exception.getErrors().get(0); 112 | assertTrue(errMsg.matches("found a tag `test` on `Role::\".*\"`, " 113 | + "but no tags should exist on `Role::\".*\"` according to the schema"), 114 | "Expected to match regex but was: '%s'".formatted(errMsg)); 115 | } 116 | 117 | @BeforeAll 118 | public static void setUp() { 119 | 120 | engine = new BasicAuthorizationEngine(); 121 | EntityTypeName user = EntityTypeName.parse("Role").get(); 122 | 123 | EntityValidationTests.entityGen = new EntityGen(user); 124 | } 125 | 126 | private static final Schema ROLE_SCHEMA = loadSchemaResource("/role_schema.json"); 127 | } 128 | -------------------------------------------------------------------------------- /CedarJava/src/test/java/com/cedarpolicy/PolicyFormatterTests.java: -------------------------------------------------------------------------------- 1 | package com.cedarpolicy; 2 | 3 | import com.cedarpolicy.formatter.PolicyFormatter; 4 | import com.cedarpolicy.model.exception.InternalException; 5 | import com.cedarpolicy.model.formatter.Config; 6 | import java.nio.file.Files; 7 | import java.nio.file.Path; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.junit.jupiter.api.Assertions.assertEquals; 11 | import static org.junit.jupiter.api.Assertions.assertThrows; 12 | 13 | public class PolicyFormatterTests { 14 | 15 | private static final String TEST_RESOURCES_DIR = "src/test/resources/"; 16 | 17 | @Test 18 | public void testPoliciesStrToPretty() throws Exception { 19 | String unformattedCedarPolicy = Files.readString( 20 | Path.of(TEST_RESOURCES_DIR + "unformatted_policy.cedar")); 21 | 22 | String formattedCedarPolicy = Files.readString( 23 | Path.of(TEST_RESOURCES_DIR + "formatted_policy.cedar")); 24 | 25 | assertEquals(formattedCedarPolicy, PolicyFormatter.policiesStrToPretty(unformattedCedarPolicy)); 26 | } 27 | 28 | @Test 29 | public void testPoliciesStrToPrettyMalformedCedarPolicy() throws Exception { 30 | String malformedCedarPolicy = Files.readString( 31 | Path.of(TEST_RESOURCES_DIR + "malformed_policy_set.cedar")); 32 | 33 | assertThrows(InternalException.class, 34 | () -> PolicyFormatter.policiesStrToPretty(malformedCedarPolicy)); 35 | } 36 | 37 | @Test 38 | public void testPoliciesStrToPrettyNullSafety() { 39 | assertThrows(NullPointerException.class, () -> PolicyFormatter.policiesStrToPretty(null)); 40 | } 41 | 42 | @Test 43 | public void testPoliciesStrToPrettyWithConfigNullSafety() throws Exception { 44 | String cedarPolicy = Files.readString(Path.of(TEST_RESOURCES_DIR + "formatted_policy.cedar")); 45 | 46 | assertThrows(NullPointerException.class, 47 | () -> PolicyFormatter.policiesStrToPrettyWithConfig(null, null)); 48 | 49 | assertThrows(NullPointerException.class, 50 | () -> PolicyFormatter.policiesStrToPrettyWithConfig(cedarPolicy, null)); 51 | 52 | assertThrows(NullPointerException.class, 53 | () -> PolicyFormatter.policiesStrToPrettyWithConfig(null, new Config(120, 4))); 54 | } 55 | 56 | @Test 57 | public void testPoliciesStrToPrettyWithConfig() throws Exception { 58 | String unformattedCedarPolicy = Files.readString( 59 | Path.of(TEST_RESOURCES_DIR + "unformatted_policy.cedar")); 60 | 61 | String formattedCedarPolicyWithCustomConfig = Files.readString( 62 | Path.of(TEST_RESOURCES_DIR + "formatted_policy_custom_config.cedar")); 63 | 64 | assertEquals(formattedCedarPolicyWithCustomConfig, 65 | PolicyFormatter.policiesStrToPrettyWithConfig(unformattedCedarPolicy, new Config(120, 4))); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /CedarJava/src/test/java/com/cedarpolicy/PolicySetTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy; 18 | 19 | import com.cedarpolicy.model.exception.InternalException; 20 | import com.cedarpolicy.model.policy.Policy; 21 | import com.cedarpolicy.model.policy.PolicySet; 22 | import org.junit.jupiter.api.Test; 23 | 24 | import java.io.IOException; 25 | import java.nio.file.Path; 26 | 27 | import static org.junit.jupiter.api.Assertions.assertThrows; 28 | import static org.junit.jupiter.api.Assertions.assertNotNull; 29 | import static org.junit.jupiter.api.Assertions.assertEquals; 30 | 31 | public class PolicySetTests { 32 | private static final String TEST_RESOURCES_DIR = "src/test/resources/"; 33 | 34 | @Test 35 | public void parsePoliciesTests() throws InternalException, IOException { 36 | PolicySet policySet = PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "policies.cedar")); 37 | for (Policy p: policySet.policies) { 38 | assertNotNull(p.policySrc); 39 | } 40 | // Make sure the policy IDs are unique as Policies are made 41 | assertEquals(2, policySet.policies.stream().map(p -> p.policyID).distinct().count()); 42 | assertEquals(2, policySet.policies.size()); 43 | assertEquals(0, policySet.templates.size()); 44 | } 45 | 46 | @Test 47 | public void parsePoliciesStringTests() throws InternalException { 48 | PolicySet policySet = PolicySet.parsePolicies("permit(principal, action, resource);"); 49 | PolicySet policySet2 = PolicySet.parsePolicies("permit(principal, action, resource) when { principal has x && principal.x == 5};"); 50 | for (Policy p: policySet.policies) { 51 | assertNotNull(p.policySrc); 52 | } 53 | assertEquals(1, policySet.policies.size()); 54 | assertEquals(0, policySet.templates.size()); 55 | for (Policy p: policySet2.policies) { 56 | assertNotNull(p.policySrc); 57 | } 58 | assertEquals(1, policySet2.policies.size()); 59 | assertEquals(0, policySet2.templates.size()); 60 | } 61 | 62 | @Test 63 | public void parseTemplatesTests() throws InternalException, IOException { 64 | PolicySet policySet = PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "template.cedar")); 65 | for (Policy p: policySet.policies) { 66 | assertNotNull(p.policySrc); 67 | } 68 | assertEquals(2, policySet.policies.size()); 69 | 70 | for (Policy p: policySet.templates) { 71 | assertNotNull(p.policySrc); 72 | } 73 | assertEquals(1, policySet.templates.size()); 74 | } 75 | 76 | @Test 77 | public void parsePoliciesExceptionTests() throws InternalException, IOException { 78 | assertThrows(IOException.class, () -> { 79 | PolicySet.parsePolicies(Path.of("nonExistentFilePath.cedar")); 80 | }); 81 | assertThrows(InternalException.class, () -> { 82 | PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "malformed_policy_set.cedar")); 83 | }); 84 | } 85 | 86 | @Test 87 | public void getNumTests() throws InternalException, IOException { 88 | // Null policy set 89 | PolicySet nullPolicySet = new PolicySet(null, null, null); 90 | assertEquals(0, nullPolicySet.getNumPolicies()); 91 | assertEquals(0, nullPolicySet.getNumTemplates()); 92 | 93 | // Empty policy set 94 | PolicySet emptyPolicySet = new PolicySet(); 95 | assertEquals(0, emptyPolicySet.getNumPolicies()); 96 | assertEquals(0, emptyPolicySet.getNumTemplates()); 97 | 98 | // Non-empty policy set 99 | PolicySet policySet = PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "template.cedar")); 100 | assertEquals(2, policySet.getNumPolicies()); 101 | assertEquals(1, policySet.getNumTemplates()); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /CedarJava/src/test/java/com/cedarpolicy/SchemaTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy; 18 | 19 | import com.cedarpolicy.model.schema.Schema; 20 | import com.cedarpolicy.model.schema.Schema.JsonOrCedar; 21 | 22 | import org.junit.jupiter.api.Test; 23 | 24 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; 25 | import static org.junit.jupiter.api.Assertions.assertThrows; 26 | 27 | public class SchemaTests { 28 | @Test 29 | public void parseJsonSchema() { 30 | assertDoesNotThrow(() -> { 31 | Schema.parse(JsonOrCedar.Json, "{}"); 32 | Schema.parse(JsonOrCedar.Json, """ 33 | { 34 | "Foo::Bar": { 35 | "entityTypes": {}, 36 | "actions": {} 37 | } 38 | } 39 | """); 40 | Schema.parse(JsonOrCedar.Json, """ 41 | { 42 | "": { 43 | "entityTypes": { 44 | "User": { 45 | "shape": { 46 | "type": "Record", 47 | "attributes": { 48 | "name": { 49 | "type": "String", 50 | "required": true 51 | }, 52 | "age": { 53 | "type": "Long", 54 | "required": false 55 | } 56 | } 57 | } 58 | }, 59 | "Photo": { 60 | "memberOfTypes": [ "Album" ] 61 | }, 62 | "Album": {} 63 | }, 64 | "actions": { 65 | "view": { 66 | "appliesTo": { 67 | "principalTypes": ["User"], 68 | "resourceTypes": ["Photo", "Album"] 69 | } 70 | } 71 | } 72 | } 73 | } 74 | """); 75 | }); 76 | assertThrows(Exception.class, () -> { 77 | Schema.parse(JsonOrCedar.Json, "{\"foo\": \"bar\"}"); 78 | Schema.parse(JsonOrCedar.Json, "namespace Foo::Bar;"); 79 | }); 80 | } 81 | 82 | @Test 83 | public void parseCedarSchema() { 84 | assertDoesNotThrow(() -> { 85 | Schema.parse(JsonOrCedar.Cedar, ""); 86 | Schema.parse(JsonOrCedar.Cedar, "namespace Foo::Bar {}"); 87 | Schema.parse(JsonOrCedar.Cedar, """ 88 | entity User = { 89 | name: String, 90 | age?: Long, 91 | }; 92 | entity Photo in Album; 93 | entity Album; 94 | action view 95 | appliesTo { principal: [User], resource: [Album, Photo] }; 96 | """); 97 | }); 98 | assertThrows(Exception.class, () -> { 99 | Schema.parse(JsonOrCedar.Cedar, """ 100 | { 101 | "Foo::Bar": { 102 | "entityTypes" {}, 103 | "actions": {} 104 | } 105 | } 106 | """); 107 | Schema.parse(JsonOrCedar.Cedar, "namspace Foo::Bar;"); 108 | }); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /CedarJava/src/test/java/com/cedarpolicy/TestUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy; 18 | 19 | import com.cedarpolicy.model.schema.Schema; 20 | import com.cedarpolicy.model.schema.Schema.JsonOrCedar; 21 | 22 | import java.nio.charset.StandardCharsets; 23 | import java.nio.file.Files; 24 | import java.nio.file.Paths; 25 | import java.util.Optional; 26 | 27 | /** Utils to help with tests. */ 28 | public final class TestUtil { 29 | private TestUtil() { 30 | } 31 | 32 | /** 33 | * Load schema file. 34 | * 35 | * @param schemaFile Schema file name 36 | */ 37 | public static Schema loadSchemaResource(String schemaFile) { 38 | try { 39 | String text = new String(Files.readAllBytes( 40 | Paths.get( 41 | ValidationTests.class.getResource(schemaFile).toURI())), 42 | StandardCharsets.UTF_8); 43 | return new Schema(JsonOrCedar.Json, Optional.of(text), Optional.empty()); 44 | } catch (Exception e) { 45 | throw new RuntimeException("Failed to load test schema file " + schemaFile, e); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /CedarJava/src/test/java/com/cedarpolicy/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * This module used to serialize / deserialize objects to/from JSON. 19 | * 20 | *

This module used to serialize / deserialize objects to/from JSON. 21 | * 22 | * @since 1.2 23 | * @author anmwells 24 | * @version 1.2 25 | */ 26 | package com.cedarpolicy; 27 | -------------------------------------------------------------------------------- /CedarJava/src/test/java/com/cedarpolicy/pbt/EntityGen.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.pbt; 18 | 19 | import com.cedarpolicy.model.entity.Entity; 20 | import com.cedarpolicy.value.EntityIdentifier; 21 | import com.cedarpolicy.value.EntityTypeName; 22 | import com.cedarpolicy.value.EntityUID; 23 | import java.util.ArrayList; 24 | import java.util.HashMap; 25 | import java.util.HashSet; 26 | import java.util.List; 27 | 28 | import net.jqwik.api.Arbitraries; 29 | 30 | /** Generate random actions for testing. */ 31 | public final class EntityGen { 32 | 33 | private List ids; 34 | private EntityTypeName type; 35 | 36 | public EntityGen(EntityTypeName type) { 37 | this.type = type; 38 | ids = new ArrayList<>(); 39 | } 40 | 41 | private EntityUID arbitraryEntityId() { 42 | // Generate Id's until we find one not in the generated set 43 | EntityIdentifier id; 44 | while (true) { 45 | id = new EntityIdentifier(Utils.strings()); 46 | if (isUnique(id)) { 47 | break; 48 | } 49 | } 50 | this.ids.add(id); 51 | return new EntityUID(type, id); 52 | } 53 | 54 | private boolean isUnique(EntityIdentifier id) { 55 | return !ids.contains(id); 56 | } 57 | 58 | // Return an arbitrary action w/ no attributes or parents 59 | public Entity arbitraryEntity() { 60 | return new Entity(arbitraryEntityId(), new HashMap<>(), new HashSet<>()); 61 | } 62 | 63 | public List arbitraryEntities() { 64 | List actions = new ArrayList<>(); 65 | actions.add(arbitraryEntity()); 66 | 67 | var count = Arbitraries.integers().between(10, 100).sample(); 68 | 69 | for (int i = 0; i < count; i++) { 70 | actions.add(arbitraryEntity()); 71 | } 72 | 73 | 74 | return actions; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /CedarJava/src/test/java/com/cedarpolicy/pbt/Utils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.cedarpolicy.pbt; 18 | 19 | import com.cedarpolicy.value.PrimString; 20 | import java.util.Arrays; 21 | import java.util.HashSet; 22 | import java.util.Set; 23 | import net.jqwik.api.Arbitraries; 24 | 25 | /** Utils for generating arbitrary primitives for testing. */ 26 | public final class Utils { 27 | private static final Set CEDAR_RESERVED = 28 | new HashSet<>( 29 | Arrays.asList( 30 | "true", 31 | "false", 32 | "permit", 33 | "forbid", 34 | "where", 35 | "when", 36 | "unless", 37 | "advice", 38 | "in", 39 | "is", 40 | "has", 41 | "if", 42 | "then", 43 | "else", 44 | "for", 45 | "let", 46 | "def", 47 | "principal", 48 | "action", 49 | "resource", 50 | "context")); 51 | 52 | /** Arbitrary strings. */ 53 | public static String strings() { 54 | return Arbitraries.strings() 55 | .numeric() 56 | .alpha() 57 | .ofMinLength(2) 58 | .filter(s -> Character.isLowerCase(s.charAt(0)) && !CEDAR_RESERVED.contains(s)) 59 | .sample(); 60 | } 61 | 62 | /** Arbitrary string as PrimString. */ 63 | public static PrimString primStrings() { 64 | return new PrimString(strings()); 65 | } 66 | 67 | /** Random int in range [min, max]. */ 68 | public static int intInRange(int min, int max) { 69 | return Arbitraries.integers().between(min, max).sample(); 70 | } 71 | 72 | private Utils() { 73 | throw new IllegalStateException("Utility class"); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /CedarJava/src/test/java/com/cedarpolicy/pbt/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * This module holds property based tests. 19 | * 20 | *

Property based tests. 21 | * 22 | * @since 1.2 23 | * @author anmwells 24 | * @version 1.2 25 | */ 26 | package com.cedarpolicy.pbt; 27 | -------------------------------------------------------------------------------- /CedarJava/src/test/resources/empty_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "": { 3 | "entityTypes": {}, 4 | "actions": {} 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /CedarJava/src/test/resources/formatted_policy.cedar: -------------------------------------------------------------------------------- 1 | permit ( 2 | principal, 3 | action == Action::"update", 4 | resource 5 | ) 6 | when { resource.owner == principal }; 7 | -------------------------------------------------------------------------------- /CedarJava/src/test/resources/formatted_policy_custom_config.cedar: -------------------------------------------------------------------------------- 1 | permit ( 2 | principal, 3 | action == Action::"update", 4 | resource 5 | ) 6 | when { resource.owner == principal }; 7 | -------------------------------------------------------------------------------- /CedarJava/src/test/resources/invalid_entities.json: -------------------------------------------------------------------------------- 1 | {"uid":{"type":"Photo","id":"pic01"}} 2 | -------------------------------------------------------------------------------- /CedarJava/src/test/resources/invalid_entity.json: -------------------------------------------------------------------------------- 1 | {"uid":{"type":"Photo","id":"pic01"}} 2 | -------------------------------------------------------------------------------- /CedarJava/src/test/resources/library_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "Library": { 3 | "entityTypes": { 4 | "User": {}, 5 | "Book": {}, 6 | "Page": { 7 | "memberOfTypes": [ 8 | "Book" 9 | ] 10 | } 11 | }, 12 | "actions": { 13 | "read": { 14 | "appliesTo": { 15 | "resourceTypes": [ 16 | "Page" 17 | ], 18 | "principalTypes": [ 19 | "User" 20 | ] 21 | } 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /CedarJava/src/test/resources/malformed_policy_set.cedar: -------------------------------------------------------------------------------- 1 | @id("Proper Policy") 2 | permit ( 3 | principal == User::"Matt", 4 | action == Action::"view", 5 | resource == Photo::"Husky.jpg" 6 | ); 7 | 8 | @id("Malformed Policy") 9 | forbid ( 10 | principal == User::"Liam", 11 | action, 12 | resource = Photo::"Husky.jpg" 13 | ); 14 | -------------------------------------------------------------------------------- /CedarJava/src/test/resources/photoflash_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "": { 3 | "entityTypes": { 4 | "User": { 5 | "memberOfTypes": [ 6 | "UserGroup" 7 | ] 8 | }, 9 | "Photo": { 10 | "memberOfTypes": [ 11 | "Album", 12 | "Account" 13 | ] 14 | }, 15 | "Album": {}, 16 | "UserGroup": {}, 17 | "Account": {} 18 | }, 19 | "actions": { 20 | "readOnly": {}, 21 | "readWrite": {}, 22 | "createAlbum": { 23 | "appliesTo": { 24 | "resourceTypes": [ 25 | "Account", 26 | "Album" 27 | ], 28 | "principalTypes": [ 29 | "User" 30 | ] 31 | } 32 | }, 33 | "addPhotoToAlbum": { 34 | "appliesTo": { 35 | "principalTypes": [ 36 | "User" 37 | ], 38 | "resourceTypes": [ 39 | "Album" 40 | ] 41 | } 42 | }, 43 | "viewPhoto": { 44 | "appliesTo": { 45 | "principalTypes": [ 46 | "User" 47 | ], 48 | "resourceTypes": [ 49 | "Photo" 50 | ] 51 | } 52 | }, 53 | "viewComments": { 54 | "appliesTo": { 55 | "principalTypes": [ 56 | "User" 57 | ], 58 | "resourceTypes": [ 59 | "Photo" 60 | ] 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /CedarJava/src/test/resources/policies.cedar: -------------------------------------------------------------------------------- 1 | @id("Policy #1") 2 | permit ( 3 | principal in UserGroup::"friends", 4 | action == Action::"view", 5 | resource == Photo::"Husky.jpg" 6 | ); 7 | 8 | @id("Policy #2") 9 | forbid ( 10 | principal == User::"Matt", 11 | action, 12 | resource == Photo::"Husky.jpg" 13 | ); -------------------------------------------------------------------------------- /CedarJava/src/test/resources/role_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "": { 3 | "entityTypes": { 4 | "Role": { 5 | "memberOfTypes": [ 6 | "Role" 7 | ] 8 | } 9 | }, 10 | "actions": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /CedarJava/src/test/resources/schema_parsing_allow_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "": { 3 | "entityTypes": { 4 | "User": { 5 | "shape": { 6 | "type": "Record", 7 | "attributes": { 8 | "foo": {"type": "String"} 9 | } 10 | } 11 | }, 12 | "Resource": { 13 | "shape": { 14 | "type": "Record", 15 | "attributes": { 16 | "owner": { 17 | "type": "Entity", 18 | "name": "User" 19 | } 20 | } 21 | } 22 | } 23 | }, 24 | "actions": { 25 | "view": { 26 | "appliesTo": { 27 | "principalTypes": [ "User" ], 28 | "resourceTypes": ["Resource"] 29 | } 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /CedarJava/src/test/resources/schema_parsing_deny_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "": { 3 | "entityTypes": { 4 | "User": { 5 | "shape": { 6 | "type": "Record", 7 | "attributes": { 8 | "foo": {"type": "String"} 9 | } 10 | } 11 | }, 12 | "Resource": { 13 | "shape": { 14 | "type": "Record", 15 | "attributes": { 16 | "owner": {"type": "Boolean"} 17 | } 18 | } 19 | } 20 | }, 21 | "actions": { 22 | "view": { 23 | "appliesTo": { 24 | "principalTypes": [ "User" ], 25 | "resourceTypes": ["Resource"] 26 | } 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /CedarJava/src/test/resources/template.cedar: -------------------------------------------------------------------------------- 1 | @id("Policy #1") 2 | permit ( 3 | principal == User::"Aaron", 4 | action == Action::"view", 5 | resource == Photo::"SomePhoto.jpg" 6 | ); 7 | 8 | @id("Policy #2") 9 | permit (principal == User::"Josh", action == Action::"comment", resource == Photo::"SomePhoto.jpg"); 10 | 11 | @id("Template #1") 12 | permit ( 13 | principal in ?principal, 14 | action in [Action::"view", Action::"comment"], 15 | resource in ?resource 16 | ) 17 | unless { 18 | resource.tag == "private" 19 | }; -------------------------------------------------------------------------------- /CedarJava/src/test/resources/unformatted_policy.cedar: -------------------------------------------------------------------------------- 1 | permit( 2 | principal, 3 | action 4 | == Action::"update", 5 | resource 6 | ) when {resource.owner == principal}; 7 | -------------------------------------------------------------------------------- /CedarJava/src/test/resources/valid_entities.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"uid":{"type":"Photo","id":"pic02"},"parents":[{"type":"PhotoParent","id":"picParent"}], 3 | "attrs":{"dummyIP": {"__extn":{"fn":"ip","arg":"199.168.1.130"}}}}, 4 | {"uid":{"type":"Photo","id":"pic01"},"parents":[{"type":"Photo","id":"pic02"}],"attrs":{}} 5 | ] 6 | -------------------------------------------------------------------------------- /CedarJava/src/test/resources/valid_entity.json: -------------------------------------------------------------------------------- 1 | {"uid":{"type":"Photo","id":"pic01"}, 2 | "attrs":{ 3 | "dummyIP": {"__extn":{"fn":"ip","arg":"192.168.1.100"}}, 4 | "dummyUser": {"__entity":{"type":"User","id":"Alice"}}, 5 | "nestedAttr":{ 6 | "managerName": "Someone", 7 | "skip":{ 8 | "name": "something", 9 | "who": {"__entity":{"type":"User","id":"Alice"}} 10 | } 11 | } 12 | }, 13 | "parents":[{"type":"Photo","id":"pic01"}], 14 | "tags": { 15 | "dummyTagIP": {"__extn":{"fn":"ip","arg":"192.168.1.100"}}, 16 | "dummyTagUser": {"__entity":{"type":"User::Tag","id":"Alice"}}, 17 | "nestedTagAttr":{ 18 | "managerTagName": "Someone", 19 | "skipTag":{ 20 | "name": "somethingTag", 21 | "who": {"__entity":{"type":"UserFromStringTag","id":"AliceTag"}} 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CedarJavaFFI/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | Cargo.lock 3 | 4 | target/ 5 | 6 | # Don't check in the local rustup toolchain override. 7 | /rust-toolchain.toml 8 | 9 | # Don't check in the local metadata file. 10 | .DS_Store 11 | .idea 12 | 13 | # Don't check in the Emacs temp files 14 | *~ 15 | 16 | # Don't check in test framework files 17 | .attach_pid* 18 | 19 | # Don't check IntelliJ module files 20 | *.iml -------------------------------------------------------------------------------- /CedarJavaFFI/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "cedar-java-ffi" 4 | license = "Apache-2.0" 5 | description = "Java FFI for Cedar (from the cedar-policy crate)." 6 | edition = "2021" 7 | 8 | 9 | version = "4.0.0" 10 | 11 | [dependencies] 12 | serde = { version = "1.0", features = ["derive", "rc"] } 13 | serde_json = "1.0" 14 | thiserror = "2.0" 15 | itertools = "0.14" 16 | 17 | # JNI Support 18 | jni = "0.21.1" 19 | jni_fn = "0.1.0" 20 | 21 | [features] 22 | partial-eval = ["cedar-policy/partial-eval"] 23 | 24 | [dev-dependencies] 25 | cool_asserts = "2.0" 26 | jni = { version = "0.21.1", features = ["invocation"] } 27 | 28 | # Dynamic linked library, used for linked to java process at runtime. 29 | [lib] 30 | crate_type = ["cdylib"] 31 | 32 | [dependencies.cedar-policy] 33 | version = "4.0.0" 34 | git = "https://github.com/cedar-policy/cedar" 35 | branch = "main" 36 | 37 | [dependencies.cedar-policy-formatter] 38 | version = "4.0.0" 39 | git = "https://github.com/cedar-policy/cedar" 40 | branch = "main" 41 | -------------------------------------------------------------------------------- /CedarJavaFFI/README.md: -------------------------------------------------------------------------------- 1 | # CedarJavaFFI 2 | 3 | Bindings to allow calling the core Cedar functions (`is_authorized` and `validate`) from Java. 4 | 5 | ## Usage 6 | 7 | ### Build 8 | 9 | You can build the code with 10 | 11 | ```shell 12 | cargo build 13 | ``` 14 | 15 | Note that the `main` branch expects that the [cedar](https://github.com/cedar-policy/cedar) repository is cloned locally in the top-level directory (`..`). `release/x.x.x` branches use a version of `cedar-policy` available on [crates.io](https://crates.io/crates/cedar-policy). 16 | 17 | ### Run 18 | 19 | You can test the code with 20 | 21 | ```shell 22 | cargo test 23 | ``` 24 | 25 | To test methods in `interface.rs`, the code creates a JVM instance. If you encounter errors indicating that Java cannot be found, verify that the `JAVA_HOME` environment variable is properly set on your system. For more details about JVM initialization from Rust, see the [jni crate documentation](https://docs.rs/jni/latest/jni/struct.JavaVM.html#launching-jvm-from-rust). 26 | 27 | Typically you will want to use `../CedarJava` in your project and won't care about `CedarJavaFFI`. 28 | 29 | ## Security 30 | 31 | See [CONTRIBUTING](../CONTRIBUTING.md#security-issue-notifications) for more information. 32 | 33 | ## License 34 | 35 | This project is licensed under the Apache-2.0 License. 36 | -------------------------------------------------------------------------------- /CedarJavaFFI/src/answer.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | use serde::{Deserialize, Serialize}; 18 | 19 | #[derive(Debug, Serialize, Deserialize)] 20 | #[serde(tag = "success")] 21 | /// Generic Answer type designed for serialization. 22 | pub enum Answer { 23 | /// The call succeeded 24 | #[serde(rename = "true")] 25 | Success { 26 | /// JSON containing the result of the call 27 | result: String, 28 | }, 29 | #[serde(rename = "false")] 30 | /// The call failed 31 | Failure { 32 | /// Whether the failure is "internal". 33 | /// 34 | /// An "internal failure" is returned when there is a fault in the 35 | /// Cedar Rust code, or when there is a problem with the request in 36 | /// the parts which the Java library is responsible for (e.g. an 37 | /// unsupported operation). 38 | /// 39 | /// By contrast, a "bad request" is returned when there is an issue in the 40 | /// part of the request supplied by the ultimate user of the library, e.g. a 41 | /// syntax error in a policy. 42 | #[serde(rename = "isInternal")] 43 | is_internal: bool, 44 | /// String description of the error(s) that led to the failure 45 | errors: Vec, 46 | }, 47 | } 48 | 49 | impl Answer { 50 | /// An "internal failure" result; see docs on [`Answer::Failure`] 51 | pub fn fail_internally(message: String) -> Self { 52 | Self::Failure { 53 | is_internal: true, 54 | errors: vec![message], 55 | } 56 | } 57 | 58 | /// A failure result that isn't internal; see docs on 59 | /// `Answer::Failure` 60 | pub fn fail_bad_request(errors: Vec) -> Self { 61 | Self::Failure { 62 | is_internal: false, 63 | errors, 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /CedarJavaFFI/src/jlist.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | use std::marker::PhantomData; 18 | 19 | use crate::{ 20 | objects::Object, 21 | utils::{get_object_ref, value_type, InternalJNIError, Result}, 22 | }; 23 | use jni::{ 24 | objects::{JObject, JString, JValueGen}, 25 | JNIEnv, 26 | }; 27 | 28 | /// Typed wrapper for Java lists 29 | /// (java.util.List) 30 | #[derive(Debug)] 31 | pub struct List<'a, T> { 32 | /// Underlying Java object 33 | obj: JObject<'a>, 34 | /// ZST for tracking type info 35 | marker: PhantomData, 36 | /// The length of this list 37 | size: i32, 38 | } 39 | 40 | impl<'a, T: Object<'a>> List<'a, T> { 41 | /// Construct an empty array list, which will serve as a list 42 | pub fn new(env: &mut JNIEnv<'a>) -> Result { 43 | let obj = env.new_object("java/util/ArrayList", "()V", &[])?; 44 | Ok(Self { 45 | obj, 46 | marker: PhantomData, 47 | size: 0, 48 | }) 49 | } 50 | 51 | /// Add an item to the back of the list 52 | pub fn add(&mut self, env: &mut JNIEnv<'a>, v: T) -> Result<()> { 53 | let value = JValueGen::Object(v.as_ref()); 54 | env.call_method(&self.obj, "add", "(Ljava/lang/Object;)Z", &[value])?; 55 | self.size += 1; 56 | Ok(()) 57 | } 58 | 59 | /// Cast from an untyped java object to this wrapper 60 | /// We can't check this as I don't see a way to list a class's interfaces 61 | pub fn cast_unchecked(obj: JObject<'a>, env: &mut JNIEnv<'a>) -> Result { 62 | let mut list = Self { 63 | obj, 64 | marker: PhantomData, 65 | size: 0, 66 | }; 67 | list.size = list.size(env)?; 68 | Ok(list) 69 | } 70 | 71 | /// Get the object at position `i`, throws an exception if out-of-bounds 72 | pub fn get(&self, env: &mut JNIEnv<'a>, i: i32) -> Result { 73 | let v = env.call_method( 74 | &self.obj, 75 | "get", 76 | "(I)Ljava/lang/Object;", 77 | &[JValueGen::Int(i)], 78 | )?; 79 | // `.get()` throws on index out of bounds 80 | if env.exception_check()? { 81 | Err(Box::new(InternalJNIError::IndexOutOfBounds { 82 | len: self.size, 83 | idx: i, 84 | })) 85 | } else { 86 | T::cast(env, get_object_ref(v)?) 87 | } 88 | } 89 | 90 | /// Iterate over the elements in the list 91 | pub fn iter(&self, env: &mut JNIEnv<'a>) -> Result> { 92 | let max = self.size(env)?; 93 | let mut v = vec![]; 94 | for i in 0..max { 95 | v.push(self.get(env, i)?); 96 | } 97 | Ok(v.into_iter()) 98 | } 99 | 100 | pub fn size(&self, env: &mut JNIEnv<'a>) -> Result { 101 | match env.call_method(&self.obj, "size", "()I", &[])? { 102 | JValueGen::Int(x) => Ok(x), 103 | v => Err(Box::new(InternalJNIError::BadMemberType { 104 | expected: "int", 105 | got: value_type(v), 106 | })), 107 | } 108 | } 109 | } 110 | 111 | impl<'a, T> AsRef> for List<'a, T> { 112 | fn as_ref(&self) -> &JObject<'a> { 113 | &self.obj 114 | } 115 | } 116 | 117 | pub fn jstr_list_to_rust_vec<'a>( 118 | env: &mut JNIEnv<'a>, 119 | jlist: &List<'a, JString<'a>>, 120 | ) -> Result> { 121 | let mut rust_vec = Vec::new(); 122 | 123 | for i in 0..jlist.size { 124 | let element: JString<'a> = jlist.get(env, i)?; 125 | let j_str = env.get_string(&element)?; 126 | rust_vec.push(String::from(j_str)); 127 | } 128 | 129 | Ok(rust_vec) 130 | } 131 | -------------------------------------------------------------------------------- /CedarJavaFFI/src/jmap.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | use std::marker::PhantomData; 18 | 19 | use crate::{objects::Object, utils::Result}; 20 | use jni::{ 21 | objects::{JObject, JValueGen}, 22 | JNIEnv, 23 | }; 24 | 25 | /// Typed wrapper for Java maps 26 | /// (java.util.Map) 27 | #[derive(Debug)] 28 | pub struct Map<'a, T, U> { 29 | /// Underlying Java object 30 | obj: JObject<'a>, 31 | /// ZST for tracking key type info 32 | key_marker: PhantomData, 33 | /// ZST for tracking value type info 34 | value_marker: PhantomData, 35 | } 36 | 37 | impl<'a, T: Object<'a>, U: Object<'a>> Map<'a, T, U> { 38 | /// Construct an empty hash map, which will serve as a map 39 | pub fn new(env: &mut JNIEnv<'a>) -> Result { 40 | let obj = env.new_object("java/util/HashMap", "()V", &[])?; 41 | 42 | Ok(Self { 43 | obj, 44 | key_marker: PhantomData, 45 | value_marker: PhantomData, 46 | }) 47 | } 48 | 49 | /// Get a value mapped to a key 50 | pub fn get(&mut self, env: &mut JNIEnv<'a>, k: T) -> Result> { 51 | let key = JValueGen::Object(k.as_ref()); 52 | let value = env 53 | .call_method( 54 | &self.obj, 55 | "get", 56 | "(Ljava/lang/Object;)Ljava/lang/Object;", 57 | &[key], 58 | )? 59 | .l()?; 60 | Ok(value) 61 | } 62 | 63 | /// Put a key-value pair into the map 64 | pub fn put(&mut self, env: &mut JNIEnv<'a>, k: T, v: U) -> Result> { 65 | let key = JValueGen::Object(k.as_ref()); 66 | let value = JValueGen::Object(v.as_ref()); 67 | let value = env 68 | .call_method( 69 | &self.obj, 70 | "put", 71 | "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 72 | &[key, value], 73 | )? 74 | .l()?; 75 | Ok(value) 76 | } 77 | 78 | /// Consumes the Map and returns the underlying JObject 79 | pub fn into_inner(self) -> JObject<'a> { 80 | self.obj 81 | } 82 | } 83 | 84 | impl<'a, T, U> AsRef> for Map<'a, T, U> { 85 | fn as_ref(&self) -> &JObject<'a> { 86 | &self.obj 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /CedarJavaFFI/src/jset.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | use std::marker::PhantomData; 18 | 19 | use crate::{objects::Object, utils::Result}; 20 | use jni::{ 21 | objects::{JObject, JValueGen}, 22 | JNIEnv, 23 | }; 24 | 25 | /// Typed wrapper for Java sets 26 | /// (java.util.Set) 27 | #[derive(Debug)] 28 | pub struct Set<'a, T> { 29 | /// Underlying Java object 30 | obj: JObject<'a>, 31 | /// ZST for tracking type info 32 | marker: PhantomData, 33 | /// The size of this set 34 | size: i32, 35 | } 36 | 37 | impl<'a, T: Object<'a>> Set<'a, T> { 38 | /// Construct an empty hash set, which will serve as a set 39 | pub fn new(env: &mut JNIEnv<'a>) -> Result { 40 | let obj = env.new_object("java/util/HashSet", "()V", &[])?; 41 | 42 | Ok(Self { 43 | obj, 44 | marker: PhantomData, 45 | size: 0, 46 | }) 47 | } 48 | 49 | /// Add an item to the set 50 | pub fn add(&mut self, env: &mut JNIEnv<'a>, v: T) -> Result<()> { 51 | let value = JValueGen::Object(v.as_ref()); 52 | env.call_method(&self.obj, "add", "(Ljava/lang/Object;)Z", &[value])?; 53 | self.size += 1; 54 | Ok(()) 55 | } 56 | } 57 | 58 | impl<'a, T> AsRef> for Set<'a, T> { 59 | fn as_ref(&self) -> &JObject<'a> { 60 | &self.obj 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /CedarJavaFFI/src/jvm_test_utils.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #![cfg(test)] 17 | 18 | use jni::{InitArgsBuilder, JavaVM}; 19 | 20 | /// Creates a new Java Virtual Machine (JVM) instance with basic configuration for tests 21 | /// 22 | /// # Returns 23 | /// * `Result` - A Result containing either: 24 | /// * `JavaVM` - The successfully created JVM instance 25 | /// * `StartJvmError` - Error that occurred during JVM creation 26 | /// 27 | pub(crate) fn create_jvm() -> Result { 28 | let jvm_args = InitArgsBuilder::new() 29 | .option("-Xcheck:jni") 30 | .build() 31 | .unwrap(); 32 | 33 | let jvm = JavaVM::new(jvm_args)?; 34 | Ok(jvm) 35 | } 36 | -------------------------------------------------------------------------------- /CedarJavaFFI/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #![forbid(unsafe_code)] 18 | mod answer; 19 | mod interface; 20 | mod jlist; 21 | mod jmap; 22 | mod jset; 23 | mod jvm_test_utils; 24 | mod objects; 25 | mod tests; 26 | mod utils; 27 | 28 | pub use interface::*; 29 | -------------------------------------------------------------------------------- /CedarJavaFFI/src/utils.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Cedar Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | use jni::{ 18 | objects::{JClass, JObject, JValueGen, JValueOwned}, 19 | JNIEnv, 20 | }; 21 | use thiserror::Error; 22 | 23 | pub type Result = std::result::Result>; 24 | 25 | /// Queries the environment to check if `obj` belongs to the `name` class 26 | /// Errors if it does not 27 | pub fn assert_is_class<'a>(env: &mut JNIEnv<'a>, obj: &JObject<'a>, name: &str) -> Result<()> { 28 | if obj.is_null() { 29 | raise_npe(env)?; 30 | return Err(Box::new(InternalJNIError::NullPointer)); 31 | } 32 | let expected_class = env.find_class(name)?; 33 | let class = env.get_object_class(obj)?; 34 | if env.is_same_object(&expected_class, &class)? { 35 | Ok(()) 36 | } else { 37 | let class_name = get_class_name(env, class)?; 38 | let expected_class_name = get_class_name(env, expected_class)?; 39 | env.throw_new( 40 | "java/lang/ClassCastException", 41 | format!("{class_name} cannot be cast to {expected_class_name}"), 42 | )?; 43 | Err(Box::new(InternalJNIError::TypeError { 44 | expected: expected_class_name, 45 | got: class_name, 46 | })) 47 | } 48 | } 49 | 50 | /// Get the name of a class as a String 51 | pub fn get_class_name<'a>(env: &mut JNIEnv<'a>, class: JClass<'a>) -> Result { 52 | let result = env.call_method(class, "toString", "()Ljava/lang/String;", &[])?; 53 | let obj = get_object_ref(result)?.into(); 54 | let jstring = env.get_string(&obj)?; 55 | Ok(jstring.into()) 56 | } 57 | 58 | /// JNI Errors and internal invariant violations 59 | #[derive(Debug, Error)] 60 | pub enum InternalJNIError { 61 | #[error("Internal invariant violated, expected member of type `{expected}`, got `{got}`")] 62 | BadMemberType { 63 | expected: &'static str, 64 | got: &'static str, 65 | }, 66 | #[error("Internal invariant violated. Object passed to jni function was of the wrong class. Expected: `{expected}`, got: `{got}`")] 67 | TypeError { expected: String, got: String }, 68 | #[error("Null pointer")] 69 | NullPointer, 70 | #[error("Index `{idx}` out of bounds for List of length `{len}`")] 71 | IndexOutOfBounds { len: i32, idx: i32 }, 72 | } 73 | 74 | /// Given a Java value, extracts the object reference if it exists, otherwise errors 75 | pub fn get_object_ref(v: JValueGen>) -> Result> { 76 | match v { 77 | JValueGen::Object(o) => Ok(o), 78 | _ => Err(Box::new(InternalJNIError::BadMemberType { 79 | expected: "object", 80 | got: value_type(v), 81 | })), 82 | } 83 | } 84 | 85 | pub fn value_type(v: JValueGen) -> &'static str { 86 | match v { 87 | JValueGen::Object(_) => "object", 88 | JValueGen::Byte(_) => "byte", 89 | JValueGen::Char(_) => "char", 90 | JValueGen::Short(_) => "short", 91 | JValueGen::Int(_) => "int", 92 | JValueGen::Long(_) => "long", 93 | JValueGen::Bool(_) => "bool", 94 | JValueGen::Float(_) => "float", 95 | JValueGen::Double(_) => "double", 96 | JValueGen::Void => "void", 97 | } 98 | } 99 | 100 | /// Raises a null-pointer exception (java.lang.NullPointerException) 101 | pub fn raise_npe<'a>(env: &mut JNIEnv<'a>) -> Result> { 102 | env.throw_new("java/lang/NullPointerException", "Null Pointer Exception")?; 103 | Ok(JValueGen::Object(JObject::null())) 104 | } 105 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright Cedar Contributors 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cedar-java 2 | ![Cedar Logo](https://github.com/cedar-policy/cedar/blob/main/logo.svg) 3 | 4 | This repository contains the source code for a Java package `CedarJava` that supports using the [Cedar](https://www.cedarpolicy.com) policy language. It also contains source code for a Rust crate `CedarJavaFFI` that enables calling Cedar library functions (written in Rust) from Java. 5 | 6 | Cedar is a language for writing and enforcing authorization policies in your applications. Using Cedar, you can write policies that specify your applications' fine-grained permissions. Your applications then authorize access requests by calling Cedar's authorization engine. Because Cedar policies are separate from application code, they can be independently authored, updated, analyzed, and audited. You can use Cedar's validator to check that Cedar policies are consistent with a declared schema which defines your application's authorization model. 7 | 8 | 9 | ## Getting Started 10 | 11 | ### Import `CedarJava` to your application 12 | #### Maven Package 13 | CedarJava is available as a maven package. You can add `CedarJava` as a dependency to your build file. 14 | 15 | Example (Gradle): 16 | ``` 17 | dependencies{ 18 | implementation 'com.cedarpolicy:cedar-java:4.2.3:uber' 19 | } 20 | ``` 21 | We highly recommend using the `*-uber.jar` as it also contains the shared library from `CedarJavaFFI`. 22 | 23 | See [https://central.sonatype.com/artifact/com.cedarpolicy/cedar-java](https://central.sonatype.com/artifact/com.cedarpolicy/cedar-java) for more details. 24 | 25 | #### Build from Source 26 | 27 | The [CedarJavaFFI](https://github.com/cedar-policy/cedar-java/blob/main/CedarJavaFFI/README.md) and [CedarJava](https://github.com/cedar-policy/cedar-java/blob/main/CedarJava/README.md) directories contain detailed instructions on building the individual modules. 28 | 29 | The `CedarJava` module uses Gradle to build both modules and run integration tests. It stores the shared library from `CedarJavaFFI` in the `-uber.jar`. The following commands provide general usage for getting started. 30 | 31 | ```shell 32 | cd CedarJava 33 | ./gradlew build 34 | ``` 35 | 36 | ### Perform an Authorization Request 37 | Here is a small snippet on how to perform `isAuthorized()` call using `CedarJava` 38 | ```java 39 | package com.mypackage; 40 | 41 | import com.cedarpolicy.AuthorizationEngine; 42 | import com.cedarpolicy.BasicAuthorizationEngine; 43 | import com.cedarpolicy.model.AuthorizationRequest; 44 | import com.cedarpolicy.model.AuthorizationResponse; 45 | import com.cedarpolicy.model.Context; 46 | import com.cedarpolicy.model.entity.Entities; 47 | import com.cedarpolicy.model.entity.Entity; 48 | import com.cedarpolicy.model.policy.PolicySet; 49 | import com.cedarpolicy.value.EntityUID; 50 | 51 | public class SimpleAuthorization { 52 | public static void main(String[] args) throws Exception { 53 | 54 | // Build entities 55 | Entity principal = new Entity(EntityUID.parse("User::\"Alice\"").get()); 56 | Entity action = new Entity(EntityUID.parse("Action::\"view\"").get()); 57 | Entity resource = new Entity(EntityUID.parse("Photo::\"alice_photo\"").get()); 58 | 59 | // Build policies 60 | PolicySet policySet = PolicySet.parsePolicies(""" 61 | permit( 62 | principal == User::"Alice", 63 | action == Action::"view", 64 | resource == Photo::"alice_photo" 65 | ); 66 | 67 | forbid( 68 | principal == User::"Alice", 69 | action == Action::"view", 70 | resource == Photo::"bob_photo" 71 | ); 72 | """); 73 | 74 | // Authorization request 75 | AuthorizationEngine ae = new BasicAuthorizationEngine(); 76 | Entities entities = new Entities(); 77 | Context context = new Context(); 78 | AuthorizationRequest request = new AuthorizationRequest(principal, action, resource, context); 79 | AuthorizationResponse authorizationResponse = ae.isAuthorized(request, policySet, entities); 80 | } 81 | } 82 | ``` 83 | 84 | ## Examples 85 | Explore our sample applications in [cedar-examples](https://github.com/cedar-policy/cedar-examples/tree/main): 86 | * [**cedar-java-hello-world**](https://github.com/cedar-policy/cedar-examples/tree/main/cedar-java-hello-world): Demonstrates basic authorization calls using Cedar-Java 87 | * [**cedar-java-partial-evaluation**](https://github.com/cedar-policy/cedar-examples/tree/main/cedar-java-partial-evaluation): Illustrates partial evaluation capabilities in Cedar-Java 88 | 89 | ## Changelog 90 | For a list of changes and version updates, see [CHANGELOG.md](CedarJava/CHANGELOG.md). 91 | 92 | ## Notes 93 | 94 | `CedarJava` requires JDK 17 or later. 95 | 96 | Cedar is primarily developed in Rust (in the [cedar](https://github.com/cedar-policy/cedar) repository). As such, `CedarJava` typically lags behind the newest Cedar features. 97 | 98 | The `main` branch of this repository is kept up-to-date with the development version of the Rust code (available in the `main` branch of [cedar](https://github.com/cedar-policy/cedar)). Unless you plan to build the Rust code locally, please use the latest `release/x.x.x` branch instead. 99 | 100 | ## Security 101 | 102 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. 103 | 104 | ## License 105 | 106 | This project is licensed under the Apache-2.0 License. 107 | -------------------------------------------------------------------------------- /configure_ci_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cargo_file=CedarJavaFFI/Cargo.toml 4 | 5 | 6 | sed -i -e '/\[dependencies.cedar-policy\]/,+4d' $cargo_file 7 | 8 | echo "" >> $cargo_file 9 | echo "[dependencies.cedar-policy]" >> $cargo_file 10 | echo "path = \"../cedar/cedar-policy\"" >> $cargo_file 11 | 12 | sed -i -e '/\[dependencies.cedar-policy-formatter\]/,+4d' $cargo_file 13 | 14 | echo "" >> $cargo_file 15 | echo "[dependencies.cedar-policy-formatter]" >> $cargo_file 16 | echo "path = \"../cedar/cedar-policy-formatter\"" >> $cargo_file 17 | --------------------------------------------------------------------------------