Skip to content

Commit

Permalink
feat(ConnectorRestrictedPolicy): Accepting a list of connectors and I…
Browse files Browse the repository at this point in the history
…N operator
  • Loading branch information
tmberthold committed Jul 12, 2023
1 parent f9c4b8f commit a174fd6
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public class ReferringConnectorValidationExtension implements ServiceExtension {
/**
* The key for referring connector constraints.
* Must be used as left operand when declaring constraints.
* rightOperand can be a string-URL or a comma separated list of string-URLs.
* Also supports the IN Operator with a list of string-URLs as right operand.
*
* <p>Example:
*
Expand All @@ -51,7 +53,7 @@ public class ReferringConnectorValidationExtension implements ServiceExtension {
* "constraint": {
* "leftOperand": "REFERRING_CONNECTOR",
* "operator": "EQ",
* "rightOperand": "http://example.org"
* "rightOperand": "http://example.org,http://example.org"
* }
* }
* </pre>
Expand Down Expand Up @@ -108,4 +110,4 @@ public void initialize(ServiceExtensionContext context) {
policyEngine.registerFunction(ALL_SCOPES, Permission.class, REFERRING_CONNECTOR_CONSTRAINT_KEY, permissionFunction);
policyEngine.registerFunction(ALL_SCOPES, Prohibition.class, REFERRING_CONNECTOR_CONSTRAINT_KEY, prohibitionFunction);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.edc.policy.model.Operator;
import org.eclipse.edc.spi.monitor.Monitor;

import java.util.List;
import java.util.Objects;

/**
Expand All @@ -38,7 +39,7 @@ public abstract class AbstractReferringConnectorValidation {
private static final String FAIL_EVALUATION_BECAUSE_RIGHT_VALUE_NOT_STRING =
"Failing evaluation because of invalid referring connector constraint. For operator 'EQ' right value must be of type 'String'. Unsupported type: '%s'";
private static final String FAIL_EVALUATION_BECAUSE_UNSUPPORTED_OPERATOR =
"Failing evaluation because of invalid referring connector constraint. As operator only 'EQ' is supported. Unsupported operator: '%s'";
"Failing evaluation because of invalid referring connector constraint. Unsupported operator: '%s'";

private final Monitor monitor;

Expand Down Expand Up @@ -84,8 +85,8 @@ protected boolean evaluate(final Operator operator, final Object rightValue, fin
return false;
}

if (operator == Operator.EQ) {
return isReferringConnector(referringConnectorClaim, rightValue, policyContext);
if (operator == Operator.EQ || operator == Operator.IN) {
return isReferringConnector(referringConnectorClaim, rightValue, policyContext, operator);
} else {
final var message = String.format(FAIL_EVALUATION_BECAUSE_UNSUPPORTED_OPERATOR, operator);
monitor.warning(message);
Expand All @@ -102,7 +103,7 @@ protected boolean evaluate(final Operator operator, final Object rightValue, fin
* @return true if object is string and successfully evaluated against the claim
*/
private boolean isReferringConnector(
String referringConnectorClaim, Object referringConnector, PolicyContext policyContext) {
String referringConnectorClaim, Object referringConnector, PolicyContext policyContext, Operator operator) {
//no right value set in policy
if (referringConnector == null) {
final var message = String.format(FAIL_EVALUATION_BECAUSE_RIGHT_VALUE_NOT_STRING, "null");
Expand All @@ -111,19 +112,8 @@ private boolean isReferringConnector(
return false;
}

//right value set but not interpretable
if (!(referringConnector instanceof String)) {
final var message =
String.format(
FAIL_EVALUATION_BECAUSE_RIGHT_VALUE_NOT_STRING,
referringConnector.getClass().getName());
monitor.warning(message);
policyContext.reportProblem(message);
return false;
}

//evaluate
return isAllowedReferringConnector(referringConnectorClaim, (String) referringConnector);
return isAllowedReferringConnector(referringConnectorClaim, referringConnector, operator);
}

/**
Expand All @@ -134,7 +124,22 @@ private boolean isReferringConnector(
* @return true if claim equals the referringConnector
*/
private static boolean isAllowedReferringConnector(
String referringConnectorClaim, String referringConnector) {
return referringConnectorClaim.equals(referringConnector);
String referringConnectorClaim, Object referringConnector, Operator operator) {
if (operator == Operator.IN) {
var referringConnectorList = (List<?>) referringConnector;
return referringConnectorList.contains(referringConnectorClaim);
} else if (operator == Operator.EQ){
//support comma separated lists here as well
if (referringConnector instanceof String string) {
var referringConnectorList = string.split(",");
for (var connector : referringConnectorList) {
if (referringConnectorClaim.equals(connector)) {
return true;
}
}
return false;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void beforeEach() {
@EnumSource(Operator.class)
void testFailsOnUnsupportedOperations(Operator operator) {

if (operator == Operator.EQ) { // only allowed operator
if (operator == Operator.EQ || operator == Operator.IN) {
return;
}

Expand Down Expand Up @@ -117,6 +117,25 @@ void testValidationWhenClaimContainsValue() {
Assertions.assertFalse(isContainedTrue);
}

@Test
void testValidationWhenClaimContainsValueAsCommaList() {

// prepare
prepareContextProblems(null);

// prepare equals
prepareReferringConnectorClaim("http://example.org");
final boolean isEqualsTrue = validation.evaluate(Operator.EQ, "http://example2.org,http://example.org", policyContext);

// prepare contains
prepareReferringConnectorClaim("http://example.com/http://example.org");
final boolean isContainedTrue = validation.evaluate(Operator.EQ, "http://example.org", policyContext);

// assert
Assertions.assertTrue(isEqualsTrue);
Assertions.assertFalse(isContainedTrue);
}

@Test
void testValidationWhenParticipantHasProblems() {

Expand Down Expand Up @@ -145,21 +164,16 @@ void testValidationWhenSingleParticipantIsValid() {
Assertions.assertTrue(isContainedTrue);
}

// In the past it was possible to use the 'IN' constraint
// with multiple referringConnector as
// a list. This is no longer supported.
// The EDC must now always decline this kind of referringConnector format.
@Test
void testValidationForMultipleParticipants() {

// prepare
prepareContextProblems(null);
prepareReferringConnectorClaim("http://example.org");

// invoke & verify
Assertions.assertFalse(validation.evaluate(Operator.IN, List.of("http://example.org", "http://example.com"), policyContext));
Assertions.assertFalse(validation.evaluate(Operator.IN, List.of(1, "http://example.org"), policyContext));
Assertions.assertFalse(validation.evaluate(Operator.IN, List.of("http://example.org", "http://example.org"), policyContext));
Assertions.assertTrue(validation.evaluate(Operator.IN, List.of("http://example.org", "http://example.com"), policyContext));
Assertions.assertTrue(validation.evaluate(Operator.IN, List.of(1, "http://example.org"), policyContext));
Assertions.assertTrue(validation.evaluate(Operator.IN, List.of("http://example.org", "http://example.org"), policyContext));
}

private void prepareContextProblems(List<String> problems) {
Expand All @@ -176,4 +190,4 @@ private void prepareReferringConnectorClaim(String referringConnector) {
Mockito.when(participantAgent.getClaims())
.thenReturn(Collections.singletonMap("referringConnector", referringConnector));
}
}
}

0 comments on commit a174fd6

Please sign in to comment.