Skip to content

Commit

Permalink
Merge pull request #45 from CleverCloud/authZCheckForSubscriptionName…
Browse files Browse the repository at this point in the history
…OnConsume

consume authZ check has now subscription($subscription) support
  • Loading branch information
KannarFr authored Jun 10, 2024
2 parents dd08815 + f617c36 commit 9e7537e
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,23 @@ public CompletableFuture<Boolean> allowTopicOperationAsync(TopicName topicName,
facts.add(topicOperationFact(TopicOperation.PRODUCE));
facts.add(topicOperationFact(TopicOperation.CONSUME));
}
Set<String> rules = Set.of("right($tenant, $namespace, $topic, $operation) <- topic($tenant, $namespace, $topic), topic_operation($operation)," + topicOperations + ".contains($operation)");
Set<String> checks = Set.of("check if right(" + topicFragment(topicName) + "," + topicOperationFragment(operation) + ")");
return authorize(() -> defaultProvider.allowTopicOperationAsync(topicName, role, operation, authData), true, "allowTopicOperationAsync(" + operation + " -> " + topicName + ")", role, authData, facts, rules, checks);

Set<String> rules = new HashSet<>();
Set<String> checks = new HashSet<>();
String actionLog;

if (authData == null || !authData.hasSubscription() || authData.getSubscription().isEmpty()) {
rules.add("right($tenant, $namespace, $topic, $operation) <- topic($tenant, $namespace, $topic), topic_operation($operation)," + topicOperations + ".contains($operation)");
checks.add("check if right(" + topicFragment(topicName) + "," + topicOperationFragment(operation) + ")");
actionLog = "allowTopicOperationAsync(" + operation + " -> " + topicName + ")";
} else {
String subscription = authData.getSubscription();
facts.add(topicSubscriptionFact(subscription));
rules.add("right($tenant, $namespace, $topic, $operation, $subscription) <- topic($tenant, $namespace, $topic), topic_operation($operation)," + topicOperations + ".contains($operation), subscription($subscription)");
checks.add("check if right(" + topicFragment(topicName) + "," + topicOperationFragment(operation) + "," + topicSubscriptionFragment(subscription) + ")");
actionLog = "allowTopicOperationAsync(" + operation + "-> " + topicName + " using subscription " + subscription + ")";
}
return authorize(() -> defaultProvider.allowTopicOperationAsync(topicName, role, operation, authData), true, actionLog, role, authData, facts, rules, checks);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ public static String topicOperationFact(TopicOperation operation) {
return "topic_operation(" + topicOperationFragment(operation) + ")";
}

public static String topicSubscriptionFragment(String subscription) {
return "\"" + subscription + "\"";
}

public static String topicSubscriptionFact(String subscription) {
return "subscription(" + topicSubscriptionFragment(subscription) + ")";
}

public static String topicPolicyOperationFact(PolicyName policy, PolicyOperation operation) {
return "topic_operation(\"" + policy.toString().toLowerCase() + "_" + operation.toString().toLowerCase() + "\")";
}
Expand Down Expand Up @@ -124,10 +132,18 @@ public static String topicOperation(TopicName topic, TopicOperation operation) {
return topicFact(topic) + "," + topicOperationFact(operation);
}

public static String topicOperation(TopicName topic, TopicOperation operation, String subscription) {
return topicFact(topic) + "," + topicOperationFact(operation) + "," + topicSubscriptionFact(subscription);
}

public static String topicOperationCheck(TopicName topic, TopicOperation operation) {
return "check if " + topicOperation(topic, operation);
}

public static String topicOperationCheck(TopicName topic, TopicOperation operation, String subscription) {
return "check if " + topicOperation(topic, operation, subscription);
}

public static String adminFact = "right(\"admin\")";

public static String adminCheck = "check if " + adminFact;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -618,4 +618,71 @@ public void testAuthorizeConsumptionOnSpecifiedTopicPartioned() throws IOExcepti
assertFalse(authorizationProvider.allowTopicOperationAsync(TopicName.get("tenantForbidden/" + namespace + "/" +topicWithPartitionTail), authedBiscuit, TopicOperation.PRODUCE, null).get());
}

@Test
public void testConsumeOnTopicWithAuthorizedSubscription() throws Exception {
SecureRandom rng = new SecureRandom();
KeyPair root = new KeyPair(rng);
SymbolTable symbols = Biscuit.default_symbol_table();

String tenant = "tenantTest";
String namespace = "namespaceTest";
String topic = "topicTest";
String subscription = "subNameTest";

Block block0 = new Block(0, symbols);
block0.add_fact(adminFact);
block0.add_check(topicOperationCheck(TopicName.get(tenant + "/" + namespace + "/" + topic), TopicOperation.CONSUME, subscription));
Biscuit biscuit = Biscuit.make(rng, root, symbols, block0.build());

String authedBiscuit = authedBiscuit(root, biscuit);
AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit();
log.debug(biscuit.print());
AuthenticationDataSource authenticationDataSource = new AuthenticationDataSource() {
@Override
public boolean hasSubscription() {
return true;
}

@Override
public String getSubscription() {
return subscription;
}
};
assertFalse(authorizationProvider.allowTopicOperationAsync(TopicName.get(tenant + "/" + namespace + "/" + topic), authedBiscuit, TopicOperation.PRODUCE, authenticationDataSource).get());
assertTrue(authorizationProvider.allowTopicOperationAsync(TopicName.get(tenant + "/" + namespace + "/" + topic), authedBiscuit, TopicOperation.CONSUME, authenticationDataSource).get());
}

@Test
public void testConsumeOnTopicWithUnauthorizedSubscription() throws Exception {
SecureRandom rng = new SecureRandom();
KeyPair root = new KeyPair(rng);
SymbolTable symbols = Biscuit.default_symbol_table();

String tenant = "tenantTest";
String namespace = "namespaceTest";
String topic = "topicTest";
String subscription = "subNameTest";

Block block0 = new Block(0, symbols);
block0.add_fact(adminFact);
block0.add_check(topicOperationCheck(TopicName.get(tenant + "/" + namespace + "/" + topic), TopicOperation.CONSUME, subscription));
Biscuit biscuit = Biscuit.make(rng, root, symbols, block0.build());

String authedBiscuit = authedBiscuit(root, biscuit);
AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit();
log.debug(biscuit.print());
AuthenticationDataSource authenticationDataSource = new AuthenticationDataSource() {
@Override
public boolean hasSubscription() {
return true;
}

@Override
public String getSubscription() {
return "wrongSubscriptionName";
}
};
assertFalse(authorizationProvider.allowTopicOperationAsync(TopicName.get(tenant + "/" + namespace + "/" + topic), authedBiscuit, TopicOperation.PRODUCE, authenticationDataSource).get());
assertFalse(authorizationProvider.allowTopicOperationAsync(TopicName.get(tenant + "/" + namespace + "/" + topic), authedBiscuit, TopicOperation.CONSUME, authenticationDataSource).get());
}
}

0 comments on commit 9e7537e

Please sign in to comment.