diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..0a2e983b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,22 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is, especially the error stack trace and/or error log (if in doubt, include the whole thing; often exceptions get wrapped in other exceptions and the exception right near the bottom explains the actual error, not the first few lines at the top.) + +**To Reproduce** +Steps to reproduce the behavior, especially Policy(Set) details, Request details, PDP configuration, code... + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Software environment (please complete the following information):** + - AuthzForce Core version [e.g. ] + - Java (JRE) version [e.g. 11] + - OS: [e.g. Ubuntu 22.04 LTS, Windows 11] diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..11fc491e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/CHANGELOG.md b/CHANGELOG.md index 82f714eb..32bd863e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ All notable changes to this project are documented in this file following the [K - Issues reported on [OW2's GitLab](https://gitlab.ow2.org/authzforce/core/issues) are referenced in the form of `[GL-N]`, where N is the issue number. +## 20.3.2 +### Fixed +- GH-83: `NoSuchElementException` thrown when the rule combining algorithm is `permit-unless-deny` and there is no Deny rule but at least one Permit rule with Obligation/Advice. + + ## 20.3.1 ### Fixed - CVEs by upgrading: diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md deleted file mode 100644 index ea028fb5..00000000 --- a/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,11 +0,0 @@ -# Software version (AuthzForce Core) - -# Platform JRE - -# Platform OS - -# Error stack trace or logs (if any) -*If in doubt include the whole thing; often exceptions get wrapped in other exceptions and the exception right near the bottom explains the actual error, not the first few lines at the top.* - -# Your code and/or AuthzForce-specific configuration file(s) - diff --git a/README.md b/README.md index 4055d1e0..276907d5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9c9812d7b09549e59edb99f3948bca4a)](https://www.codacy.com/gh/authzforce/core/dashboard?utm_source=github.com&utm_medium=referral&utm_content=authzforce/core&utm_campaign=Badge_Grade) +[![](https://img.shields.io/badge/tag-authzforce-orange.svg?logo=stackoverflow)](http://stackoverflow.com/questions/tagged/authzforce) +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9c9812d7b09549e59edb99f3948bca4a)](https://app.codacy.com/gh/authzforce/core/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/389/badge)](https://bestpractices.coreinfrastructure.org/projects/389) [![Build Status](https://github.com/authzforce/core/actions/workflows/maven.yml/badge.svg?branch=develop)](https://github.com/authzforce/core/actions/workflows/maven.yml) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fauthzforce%2Fcore.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fauthzforce%2Fcore?ref=badge_shield) diff --git a/pdp-cli/pom.xml b/pdp-cli/pom.xml index e0c5141c..be0071c6 100644 --- a/pdp-cli/pom.xml +++ b/pdp-cli/pom.xml @@ -3,7 +3,7 @@ org.ow2.authzforce authzforce-ce-core - 20.3.1 + 20.3.2 ../pom.xml authzforce-ce-core-pdp-cli @@ -30,12 +30,12 @@ org.ow2.authzforce authzforce-ce-core-pdp-engine - 20.3.1 + 20.3.2 org.ow2.authzforce authzforce-ce-core-pdp-io-xacml-json - 20.3.1 + 20.3.2 org.testng @@ -49,7 +49,7 @@ org.ow2.authzforce authzforce-ce-core-pdp-testutils - 20.3.1 + 20.3.2 test diff --git a/pdp-engine/pom.xml b/pdp-engine/pom.xml index ce1bac32..62957f7f 100644 --- a/pdp-engine/pom.xml +++ b/pdp-engine/pom.xml @@ -3,7 +3,7 @@ org.ow2.authzforce authzforce-ce-core - 20.3.1 + 20.3.2 ../pom.xml authzforce-ce-core-pdp-engine diff --git a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/combining/DPUnlessPDCombiningAlg.java b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/combining/DPUnlessPDCombiningAlg.java index 55ceec6b..27ec4d7a 100644 --- a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/combining/DPUnlessPDCombiningAlg.java +++ b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/combining/DPUnlessPDCombiningAlg.java @@ -41,6 +41,9 @@ final class DPUnlessPDCombiningAlg extends BaseCombiningAlg private static final class Evaluator extends BaseCombiningAlg.Evaluator { + /* + In the "permit-unless-deny" (resp. deny-unless-permit) algorithm, Deny (resp. Permit) is called the "overriding" Effect and Permit (resp. Deny) is called the "overridden" Effect. + */ private final DecisionType overridingEffectAsDecision; private final ExtendedDecision overridingEffectAsExtDecision; private final DecisionType overriddenEffectAsDecision; @@ -131,6 +134,7 @@ private static final class OverridingEffectFirstRuleCombiningAlgEvaluator implem { private static boolean verifyRuleEffectsAndPepActions(final EffectType expectedEffect, final Collection rules, final boolean mustHavePepAction) { + assert rules != null; for (final RuleEvaluator rule : rules) { if (rule.getEffect() != expectedEffect || mustHavePepAction && !rule.hasAnyPepAction()) @@ -142,54 +146,67 @@ private static boolean verifyRuleEffectsAndPepActions(final EffectType expectedE return true; } + /* + In the "permit-unless-deny" (resp. deny-unless-permit) algorithm, Deny (resp. Permit) is called the "overriding" Effect and Permit (resp. Deny) is called the "overridden" Effect. + */ private final ImmutableList rulesWithOverridingEffect; private final DecisionType overridingEffectAsDecision; - private final ImmutableList otherRulesWithPepActions; + private final ImmutableList rulesWithOverriddenEffectAndPepActions; private final DecisionType overriddenEffectAsDecision; private final ExtendedDecision overriddenEffectAsExtDecision; /** - * Constructor + * Constructor. Either {@code nonEmptyRulesWithOverridingEffect} OR {@code rulesWithOverriddenEffectAndPepActions} must be non-empty (at least one Rule). * * @param rulesWithOverridingEffect * combined Rules with overriding Effect. Must be non-null and non-empty. - * @param otherRulesWithPepActions + * @param rulesWithOverriddenEffectAndPepActions * combined Rules with opposite/overridden Effect and PEP actions. Must be non-null and non-empty. */ - OverridingEffectFirstRuleCombiningAlgEvaluator(final Collection rulesWithOverridingEffect, final Collection otherRulesWithPepActions) + OverridingEffectFirstRuleCombiningAlgEvaluator(final Collection rulesWithOverridingEffect, final Collection rulesWithOverriddenEffectAndPepActions) { - assert rulesWithOverridingEffect != null && !rulesWithOverridingEffect.isEmpty() && otherRulesWithPepActions != null; + assert rulesWithOverridingEffect != null && rulesWithOverriddenEffectAndPepActions != null && (!rulesWithOverridingEffect.isEmpty() || !rulesWithOverriddenEffectAndPepActions.isEmpty()); + // Either nonEmptyRulesWithOverridingEffect OR rulesWithOverriddenEffectAndPepActions is non-empty (at least one Rule). + final EffectType overridingEffect; + final EffectType overriddenEffect; + // first rule's effect assumed the same for all rulesWithOverridingEffect + if(rulesWithOverridingEffect.isEmpty()) + { + // rulesWithOverridingEffect is empty, so rulesWithOverriddenEffectAndPepActions is not + overriddenEffect = rulesWithOverriddenEffectAndPepActions.iterator().next().getEffect(); + overridingEffect = overriddenEffect == EffectType.PERMIT ? EffectType.DENY: EffectType.PERMIT; + } else { + // rulesWithOverridingEffect is not empty + overridingEffect = rulesWithOverridingEffect.iterator().next().getEffect(); + overriddenEffect = overridingEffect == EffectType.PERMIT ? EffectType.DENY: EffectType.PERMIT; + } - // first rule's effect assumed the same for all - final EffectType overridingEffect = rulesWithOverridingEffect.iterator().next().getEffect(); assert verifyRuleEffectsAndPepActions(overridingEffect, rulesWithOverridingEffect, false); + assert verifyRuleEffectsAndPepActions(overriddenEffect, rulesWithOverriddenEffectAndPepActions, true); - final EffectType overriddenEffect; if (overridingEffect == EffectType.DENY) { - overriddenEffect = EffectType.PERMIT; this.overridingEffectAsDecision = DecisionType.DENY; this.overriddenEffectAsDecision = DecisionType.PERMIT; this.overriddenEffectAsExtDecision = ExtendedDecisions.SIMPLE_PERMIT; } else { - overriddenEffect = EffectType.DENY; this.overridingEffectAsDecision = DecisionType.PERMIT; this.overriddenEffectAsDecision = DecisionType.DENY; this.overriddenEffectAsExtDecision = ExtendedDecisions.SIMPLE_DENY; - } - assert verifyRuleEffectsAndPepActions(overriddenEffect, otherRulesWithPepActions, true); - this.rulesWithOverridingEffect = ImmutableList.copyOf(rulesWithOverridingEffect); - this.otherRulesWithPepActions = ImmutableList.copyOf(otherRulesWithPepActions); + this.rulesWithOverriddenEffectAndPepActions = ImmutableList.copyOf(rulesWithOverriddenEffectAndPepActions); } @Override public ExtendedDecision evaluate(final EvaluationContext context, final Optional mdpContext, final UpdatableList updatablePepActions, final UpdatableList updatableApplicablePolicyIdList) { + /* + In the "permit-unless-deny" (resp. deny-unless-permit) algorithm, Deny (resp. Permit) is called the "overriding" Effect and Permit (resp. Deny) is called the "overridden" Effect. + */ for (final RuleEvaluator rule : rulesWithOverridingEffect) { final DecisionResult evalResult = rule.evaluate(context, mdpContext); @@ -206,7 +223,7 @@ public ExtendedDecision evaluate(final EvaluationContext context, final Optional /* * Decision is not the overriding Effect -> final decision will be the opposite/overridden Effect. Before returning the final result, we need to collect PEP actions */ - for (final RuleEvaluator rule : otherRulesWithPepActions) + for (final RuleEvaluator rule : rulesWithOverriddenEffectAndPepActions) { final DecisionResult evalResult = rule.evaluate(context, mdpContext); final DecisionType decision = evalResult.getDecision(); @@ -289,6 +306,8 @@ public CombiningAlg.Evaluator getInstance(final Iterable ignore other rules. If there are non-empty * rules with overriding Effect, for optimization, we separate them from others. If the overriding Effect is not returned as decision, the overridden Effect is always returned as decision, * therefore the other rules (with overridden Effect) affect the decision result only if they have PEP action(s). @@ -355,10 +374,10 @@ public CombiningAlg.Evaluator getInstance(final Iterable rulesWithOverriddenEffectAndPepActions). */ LOGGER.debug( - "{}: 'children may be processed in any order' (XACML). This implementation will process Rules with overriding Effect first, then the others (with PEP actions only, others without are ignored)", + "{}: 'children may be processed in any order' (XACML). Rules with overriding Effect will be processed first, then the others (with PEP actions only, others without are ignored)", this); return new OverridingEffectFirstRuleCombiningAlgEvaluator(nonEmptyRulesWithOverridingEffect, rulesWithOverriddenEffectAndPepActions); } diff --git a/pdp-io-xacml-json/pom.xml b/pdp-io-xacml-json/pom.xml index 9e88c16b..08fc5e85 100644 --- a/pdp-io-xacml-json/pom.xml +++ b/pdp-io-xacml-json/pom.xml @@ -3,7 +3,7 @@ org.ow2.authzforce authzforce-ce-core - 20.3.1 + 20.3.2 ../pom.xml authzforce-ce-core-pdp-io-xacml-json diff --git a/pdp-testutils/pom.xml b/pdp-testutils/pom.xml index 4c401c59..404b9094 100644 --- a/pdp-testutils/pom.xml +++ b/pdp-testutils/pom.xml @@ -3,7 +3,7 @@ org.ow2.authzforce authzforce-ce-core - 20.3.1 + 20.3.2 ../pom.xml authzforce-ce-core-pdp-testutils @@ -43,12 +43,12 @@ ${project.groupId} ${artifactId.prefix}-core-pdp-engine - 20.3.1 + 20.3.2 org.ow2.authzforce authzforce-ce-core-pdp-io-xacml-json - 20.3.1 + 20.3.2 compile diff --git a/pom.xml b/pom.xml index 11e3db69..5278cab4 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ 8.5.0 authzforce-ce-core - 20.3.1 + 20.3.2 pom ${project.groupId}:${project.artifactId} AuthzForce - XACML-compliant Core PDP Engine and associated test modules