From 95583e3fce5cbcba3f139970965862f3d12aa277 Mon Sep 17 00:00:00 2001 From: "Alexandre DUVAL - @kannarfr" <kannarfr@gmail.com> Date: Tue, 1 Feb 2022 16:07:31 +0100 Subject: [PATCH 1/8] format --- .../clevercloud/biscuitpulsar/AuthorizationProviderBiscuit.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/clevercloud/biscuitpulsar/AuthorizationProviderBiscuit.java b/src/main/java/com/clevercloud/biscuitpulsar/AuthorizationProviderBiscuit.java index cafb6ab..8c026f4 100644 --- a/src/main/java/com/clevercloud/biscuitpulsar/AuthorizationProviderBiscuit.java +++ b/src/main/java/com/clevercloud/biscuitpulsar/AuthorizationProviderBiscuit.java @@ -289,7 +289,6 @@ public CompletableFuture<Boolean> allowNamespacePolicyOperationAsync(NamespaceNa Verifier verifier = res.get(); verifier.set_time(); - verifier.add_fact(namespaceFact(namespaceName)).get(); verifier.add_fact(namespacePolicyOperationFact(namespaceName, policy, operation)).get(); verifier.add_rule("right(#authority, $tenant, $namespace, $operation) <- right(#authority, #admin), namespace_operation(#ambient, $tenant, $namespace, $operation), " + policiesOperations + ".contains($operation)").get(); From c1384349c96c1adcceaacc54b1adefb3c78c33cf Mon Sep 17 00:00:00 2001 From: "Alexandre DUVAL - @kannarfr" <kannarfr@gmail.com> Date: Tue, 1 Mar 2022 13:08:22 +0100 Subject: [PATCH 2/8] biscuit-java 2.0.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 224b81c..7618d99 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ <nexus-staging-maven.version>1.6.7</nexus-staging-maven.version> <!-- dependencies --> - <biscuit-java.version>1.1.4</biscuit-java.version> + <biscuit-java.version>2.0.0-SNAPSHOT</biscuit-java.version> <logback-classic.version>1.2.10</logback-classic.version> <protobuf.version>3.16.1</protobuf.version> <pulsar.version>2.9.1</pulsar.version> From 8bfc9795486cd8c9052cda896b45c240a1572275 Mon Sep 17 00:00:00 2001 From: "Alexandre DUVAL - @kannarfr" <kannarfr@gmail.com> Date: Tue, 1 Mar 2022 13:08:43 +0100 Subject: [PATCH 3/8] bump to biscuit 2.0 --- pom.xml | 6 - .../AuthenticationProviderBiscuit.java | 46 +- .../AuthorizationProviderBiscuit.java | 362 +++------ .../formatter/BiscuitFormatter.java | 79 +- src/main/java/resources/log4j2.xml | 13 - src/main/resources/logback.xml | 20 + .../AuthenticationProviderBiscuitTest.java | 9 +- .../AuthorizationProviderBiscuitTest.java | 685 ++++-------------- .../formatter/BiscuitFormatterTest.java | 15 +- src/test/java/resources/log4j2.xml | 13 - src/test/resources/logback-test.xml | 14 + 11 files changed, 341 insertions(+), 921 deletions(-) delete mode 100644 src/main/java/resources/log4j2.xml create mode 100644 src/main/resources/logback.xml delete mode 100644 src/test/java/resources/log4j2.xml create mode 100644 src/test/resources/logback-test.xml diff --git a/pom.xml b/pom.xml index 7618d99..4545a61 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,6 @@ <logback-classic.version>1.2.10</logback-classic.version> <protobuf.version>3.16.1</protobuf.version> <pulsar.version>2.9.1</pulsar.version> - <slf4j-api.version>1.7.32</slf4j-api.version> <vavr.version>0.10.2</vavr.version> <!-- test dependencies --> @@ -196,11 +195,6 @@ </exclusions> </dependency> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-api</artifactId> - <version>${slf4j-api.version}</version> - </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> diff --git a/src/main/java/com/clevercloud/biscuitpulsar/AuthenticationProviderBiscuit.java b/src/main/java/com/clevercloud/biscuitpulsar/AuthenticationProviderBiscuit.java index 8ef98e3..fcae746 100644 --- a/src/main/java/com/clevercloud/biscuitpulsar/AuthenticationProviderBiscuit.java +++ b/src/main/java/com/clevercloud/biscuitpulsar/AuthenticationProviderBiscuit.java @@ -1,9 +1,9 @@ package com.clevercloud.biscuitpulsar; +import biscuit.format.schema.Schema; import com.clevercloud.biscuit.crypto.PublicKey; import com.clevercloud.biscuit.error.Error; import com.clevercloud.biscuit.token.Biscuit; -import io.vavr.control.Either; import org.apache.commons.lang3.StringUtils; import org.apache.pulsar.broker.ServiceConfiguration; import org.apache.pulsar.broker.authentication.AuthenticationDataSource; @@ -14,6 +14,9 @@ import javax.naming.AuthenticationException; import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SignatureException; import java.util.Base64; public class AuthenticationProviderBiscuit implements AuthenticationProvider { @@ -24,12 +27,10 @@ public class AuthenticationProviderBiscuit implements AuthenticationProvider { final static String BISCUIT = "token"; - final static String CONF_BISCUIT_SEALING_KEY = "biscuitSealingKey"; final static String CONF_BISCUIT_PUBLIC_ROOT_KEY = "biscuitPublicRootKey"; final static String CONF_BISCUIT_SUPPORT_JWT = "biscuitSupportJWT"; - private PublicKey rootKey; - static String SEALING_KEY; + static PublicKey rootKey; private AuthenticationProviderToken jwtAuthenticator; private Boolean isJWTSupported; @@ -39,8 +40,7 @@ public void close() throws IOException { } public void initialize(ServiceConfiguration serviceConfiguration) throws IOException { - log.info("Initialize Pulsar Biscuit Authentication plugin..."); - + log.info("Initializing Pulsar Biscuit Authentication plugin..."); log.info("With JWT authentication support?"); isJWTSupported = Boolean.parseBoolean((String) serviceConfiguration.getProperty(CONF_BISCUIT_SUPPORT_JWT)); if (isJWTSupported) { @@ -55,13 +55,11 @@ public void initialize(ServiceConfiguration serviceConfiguration) throws IOExcep log.info("Biscuit authentication configuration..."); String key = (String) serviceConfiguration.getProperty(CONF_BISCUIT_PUBLIC_ROOT_KEY); log.debug("Got biscuit root public key: {}", key); - SEALING_KEY = (String) serviceConfiguration.getProperty(CONF_BISCUIT_SEALING_KEY); - log.debug("Got biscuit sealing key: {}", SEALING_KEY); try { - rootKey = new PublicKey(hexStringToByteArray(key)); + rootKey = new PublicKey(Schema.PublicKey.Algorithm.Ed25519, hexStringToByteArray(key)); log.info("Biscuit authentication initialized."); - } catch (Exception e) { - log.error("Could not decode Biscuit root public key: {}", e); + } catch (Exception ex) { + log.error("Could not decode Biscuit root public key", ex); throw new IOException(); } } @@ -113,27 +111,13 @@ private static String validateBearer(final String bearer) throws AuthenticationE } } - private String parseBiscuit(final String biscuit) throws AuthenticationException { - log.debug("Biscuit to parse: {}", biscuit); + private String parseBiscuit(final String biscuitB64Url) throws AuthenticationException { + log.debug("Biscuit to parse: {}", biscuitB64Url); try { - Either<Error, Biscuit> deser = Biscuit.from_b64(biscuit); - - if (deser.isLeft()) { - throw new AuthenticationException("Could not deserialize biscuit"); - } else { - Biscuit realBiscuit = deser.get(); - log.debug("Deserialized biscuit"); - - if (realBiscuit.check_root_key(rootKey).isLeft()) { - throw new AuthenticationException("This biscuit was not generated with the expected root key"); - } - log.debug("Root key is valid"); - - byte[] sealed = realBiscuit.seal(SEALING_KEY.getBytes()).get(); - log.debug("Biscuit deserialized and sealed"); - return "biscuit:" + Base64.getUrlEncoder().encodeToString(sealed); - } - } catch (IllegalArgumentException e) { + Biscuit.from_b64url(biscuitB64Url, rootKey); + log.debug("Deserialized biscuit"); + return "biscuit:" + biscuitB64Url; + } catch (IllegalArgumentException | NoSuchAlgorithmException | SignatureException | InvalidKeyException | Error e) { throw new AuthenticationException(e.getMessage()); } } diff --git a/src/main/java/com/clevercloud/biscuitpulsar/AuthorizationProviderBiscuit.java b/src/main/java/com/clevercloud/biscuitpulsar/AuthorizationProviderBiscuit.java index 8c026f4..849ab78 100644 --- a/src/main/java/com/clevercloud/biscuitpulsar/AuthorizationProviderBiscuit.java +++ b/src/main/java/com/clevercloud/biscuitpulsar/AuthorizationProviderBiscuit.java @@ -2,8 +2,8 @@ import com.clevercloud.biscuit.datalog.RunLimits; import com.clevercloud.biscuit.error.Error; +import com.clevercloud.biscuit.token.Authorizer; import com.clevercloud.biscuit.token.Biscuit; -import com.clevercloud.biscuit.token.Verifier; import io.vavr.control.Either; import org.apache.pulsar.broker.ServiceConfiguration; import org.apache.pulsar.broker.authentication.AuthenticationDataSource; @@ -17,13 +17,16 @@ import org.slf4j.LoggerFactory; import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SignatureException; import java.time.Duration; -import java.util.Base64; +import java.util.HashSet; import java.util.Set; +import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; import static com.clevercloud.biscuitpulsar.formatter.BiscuitFormatter.*; -import static io.vavr.API.Left; public class AuthorizationProviderBiscuit implements AuthorizationProvider { private static final Logger log = LoggerFactory.getLogger(AuthorizationProviderBiscuit.class); @@ -38,7 +41,8 @@ public class AuthorizationProviderBiscuit implements AuthorizationProvider { private RunLimits runLimits; public AuthorizationProviderBiscuit() { - runLimits = new RunLimits(); + // TODO: we increase the timeout duration due to JVM warmup, need to find a fix + runLimits = new RunLimits(1000, 100, Duration.ofMillis(20)); } public AuthorizationProviderBiscuit(ServiceConfiguration conf, PulsarResources pulsarResources) @@ -51,21 +55,6 @@ public AuthorizationProviderBiscuit(ServiceConfiguration conf, PulsarResources p ); } - public Either<Error, Verifier> verifierFromBiscuit(String role) { - Either<Error, Biscuit> deser = Biscuit.from_sealed( - Base64.getUrlDecoder().decode(role.substring("biscuit:".length())), - AuthenticationProviderBiscuit.SEALING_KEY.getBytes() - ); - if (deser.isLeft()) { - Error e = deser.getLeft(); - log.error("Failed to deserialize Biscuit from sealed [{}] due to [{}].", role, e.toString()); - return Left(e); - } - - Biscuit token = deser.get(); - return token.verify_sealed(); - } - @Override public void initialize(ServiceConfiguration conf, PulsarResources pulsarResources) throws IOException { this.conf = conf; @@ -73,129 +62,77 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource defaultProvider = new PulsarAuthorizationProvider(conf, pulsarResources); } - @Override - public CompletableFuture<Boolean> canProduceAsync(TopicName topicName, String role, AuthenticationDataSource authenticationData) { - if (!role.startsWith("biscuit:")) { - return defaultProvider.canProduceAsync(topicName, role, authenticationData); + private Either<Exception, Authorizer> authorizerFromBiscuitB64Url(String role) { + try { + Biscuit sealedBiscuit = Biscuit.from_b64url(role.substring("biscuit:".length()), AuthenticationProviderBiscuit.rootKey); + Authorizer authorizer = sealedBiscuit.authorizer(); + return Either.right(authorizer); + } catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException | Error ex) { + log.error("Failed to deserialize Biscuit from sealed [{}] due to [{}].", role, ex); + return Either.left(ex); } + } - Either<Error, Verifier> res = verifierFromBiscuit(role); - if (res.isLeft()) { - return CompletableFuture.failedFuture(new Exception(res.getLeft().toString())); - } - - Verifier verifier = res.get(); - verifier.set_time(); - verifier.add_fact(topicFact(topicName)).get(); - verifier.add_fact(topicOperationFact(topicName, TopicOperation.PRODUCE)).get(); - verifier.add_rule("right(#authority, $tenant, $namespace, $topic, #produce) <- right(#authority, #admin), topic_operation(#ambient, $tenant, $namespace, $topic, #produce)").get(); - verifier.add_check("check if right(#authority," + topicFactFragment(topicName) + "," + topicOperationSymbol(TopicOperation.PRODUCE)).get(); - verifier.allow(); - - Either verifierResult = verifier.verify(runLimits); - log.debug(verifier.print_world()); + private CompletableFuture<Boolean> authorize(Callable<CompletableFuture<Boolean>> notBiscuitFallback, Boolean withSuperUserFallback, + String action, String role, AuthenticationDataSource authenticationData, + Set<String> facts, Set<String> rules, Set<String> checks) { + if (!role.startsWith("biscuit:")) { + try { + return notBiscuitFallback.call(); + } catch (Exception ex) { + log.error("Error during notBiscuitFallback call", ex); + return CompletableFuture.failedFuture(ex); + } + } + + return authorizerFromBiscuitB64Url(role) + .fold(CompletableFuture::failedFuture, + authorizer -> { + try { + authorizer.set_time(); + authorizer.add_check(adminCheck); + for (String fact : facts) authorizer.add_fact(fact); + for (String rule : rules) authorizer.add_rule(rule); + for (String check : checks) authorizer.add_check(check); + authorizer.allow(); + log.debug(authorizer.print_world()); + authorizer.authorize(runLimits); + } catch (Error ex) { + log.debug("BiscuitAuthorization [{}] unauthorized role -> [{}]", action, role, ex); + if (withSuperUserFallback) { + log.debug("Will fallback with isSuperUser check"); + return isSuperUser(role, authenticationData, this.conf); + } else { + log.debug("No isSuperUSer fallback, returning unauthorized."); + return CompletableFuture.completedFuture(false); + } + } + log.debug("BiscuitAuthorization [{}] authorized.", action); + return CompletableFuture.completedFuture(true); + }); + } - if (verifierResult.isLeft()) { - log.debug("Biscuit canProduceAsync on [{}] NOT authorized for role [{}]: {}", topicName, role, verifierResult.getLeft()); - return isSuperUser(role, authenticationData, this.conf); - } else { - log.debug("Biscuit canProductAsync on [{}] authorized.", topicName); - return CompletableFuture.completedFuture(true); - } + @Override + public CompletableFuture<Boolean> canProduceAsync(TopicName topicName, String role, AuthenticationDataSource authenticationData) { + return allowTopicOperationAsync(topicName, role, TopicOperation.PRODUCE, authenticationData); } @Override public CompletableFuture<Boolean> canConsumeAsync(TopicName topicName, String role, AuthenticationDataSource authenticationData, String subscription) { - if (!role.startsWith("biscuit:")) { - return defaultProvider.canConsumeAsync(topicName, role, authenticationData, subscription); - } - - Either<Error, Verifier> res = verifierFromBiscuit(role); - if (res.isLeft()) { - return CompletableFuture.failedFuture(new Exception(res.getLeft().toString())); - } - - Verifier verifier = res.get(); - verifier.set_time(); - verifier.add_fact(topicFact(topicName)).get(); - verifier.add_fact(topicOperationFact(topicName, TopicOperation.CONSUME)).get(); - verifier.add_rule("right(#authority, $tenant, $namespace, $topic, #consume) <- right(#authority, #admin), topic_operation(#ambient, $tenant, $namespace, $topic, #consume)").get(); - verifier.add_check("check if right(#authority," + topicFactFragment(topicName) + "," + topicOperationSymbol(TopicOperation.CONSUME)).get(); - verifier.allow(); - - Either verifierResult = verifier.verify(runLimits); - log.debug(verifier.print_world()); - - if (verifierResult.isLeft()) { - log.debug("Biscuit canConsumeAsync on [{}] NOT authorized for role [{}]: {}", topicName, role, verifierResult.getLeft()); - return isSuperUser(role, authenticationData, this.conf); - } else { - log.debug("Biscuit canConsumeAsync on [{}] authorized.", topicName); - return CompletableFuture.completedFuture(true); - } + return allowTopicOperationAsync(topicName, role, TopicOperation.CONSUME, authenticationData); } @Override public CompletableFuture<Boolean> canLookupAsync(TopicName topicName, String role, AuthenticationDataSource authenticationData) { - if (!role.startsWith("biscuit:")) { - return defaultProvider.canLookupAsync(topicName, role, authenticationData); - } - - Either<Error, Verifier> res = verifierFromBiscuit(role); - if (res.isLeft()) { - return CompletableFuture.failedFuture(new Exception(res.getLeft().toString())); - } - - Verifier verifier = res.get(); - verifier.set_time(); - verifier.add_fact(topicFact(topicName)).get(); - verifier.add_fact(topicOperationFact(topicName, TopicOperation.LOOKUP)).get(); - verifier.add_rule("right(#authority, $tenant, $namespace, $topic, #lookup) <- right(#authority, #admin), topic_operation(#ambient, $tenant, $namespace, $topic, #lookup)").get(); - verifier.add_check("check if right(#authority," + topicFactFragment(topicName) + "," + topicOperationSymbol(TopicOperation.LOOKUP)).get(); - verifier.allow(); - - Either verifierResult = verifier.verify(runLimits); - log.debug(verifier.print_world()); - - if (verifierResult.isLeft()) { - log.debug("Biscuit canLookupAsync on [{}] NOT authorized for role [{}]: {}", topicName, role, verifierResult.getLeft()); - return isSuperUser(role, authenticationData, this.conf); - } else { - log.debug("Biscuit canLookupAsync on [{}] authorized.", topicName); - return CompletableFuture.completedFuture(true); - } + return allowTopicOperationAsync(topicName, role, TopicOperation.LOOKUP, authenticationData); } @Override - //FIXME: should be reworked public CompletableFuture<Boolean> allowFunctionOpsAsync(NamespaceName namespaceName, String role, AuthenticationDataSource authenticationData) { if (!role.startsWith("biscuit:")) { return defaultProvider.allowFunctionOpsAsync(namespaceName, role, authenticationData); } - - Either<Error, Verifier> res = verifierFromBiscuit(role); - if (res.isLeft()) { - return CompletableFuture.failedFuture(new Exception(res.getLeft().toString())); - } - - Verifier verifier = res.get(); - verifier.set_time(); - verifier.add_fact(namespaceFact(namespaceName)).get(); - verifier.add_operation("functions"); - // should we have #namespace here? why not have #topic for topic rights to be coherent? - verifier.add_check("check if right(#authority, #namespace," + namespaceFactFragment(namespaceName) + ",#functions)").get(); - verifier.allow(); - - Either verifierResult = verifier.verify(runLimits); - log.debug(verifier.print_world()); - - if (verifierResult.isLeft()) { - log.debug("Biscuit allowFunctionOpsAsync on [{}] NOT authorized for role [{}]: {}", namespaceName, role, verifierResult.getLeft()); - return isSuperUser(role, authenticationData, this.conf); - } else { - log.debug("Biscuit allowFunctionOpsAsync on [{}] authorized.", namespaceName); - return CompletableFuture.completedFuture(true); - } + return isSuperUser(role, authenticationData, this.conf); } @Override @@ -210,172 +147,61 @@ public CompletableFuture<Boolean> allowSinkOpsAsync(NamespaceName namespaceName, @Override public CompletableFuture<Boolean> isSuperUser(String role, AuthenticationDataSource authenticationData, ServiceConfiguration serviceConfiguration) { - if (!role.startsWith("biscuit:")) { - return defaultProvider.isSuperUser(role, authenticationData, serviceConfiguration); - } - - Either<Error, Verifier> res = verifierFromBiscuit(role); - if (res.isLeft()) { - return CompletableFuture.failedFuture(new Exception(res.getLeft().toString())); - } - - Verifier verifier = res.get(); - verifier.set_time(); - verifier.add_check("check if right(#authority, #admin)").get(); - verifier.allow(); - - Either verifierResult = verifier.verify(runLimits); - log.debug(verifier.print_world()); - - if (verifierResult.isLeft()) { - log.debug("Biscuit isSuperUser NOT authorized for role [{}]: {}", role, verifierResult.getLeft()); - return CompletableFuture.completedFuture(false); - } else { - log.debug("Biscuit isSuperUser authorized."); - return CompletableFuture.completedFuture(true); - } + return authorize(() -> defaultProvider.isSuperUser(role, authenticationData, serviceConfiguration), false, "isSuperUser", role, authenticationData, Set.of(), Set.of(), Set.of()); } @Override public CompletableFuture<Boolean> allowTenantOperationAsync(String tenantName, String role, TenantOperation operation, AuthenticationDataSource authData) { - if (!role.startsWith("biscuit:")) { - return defaultProvider.allowTenantOperationAsync(tenantName, role, operation, authData); - } - return isSuperUser(role, authData, this.conf); } @Override public CompletableFuture<Boolean> allowNamespaceOperationAsync(NamespaceName namespaceName, String role, NamespaceOperation operation, AuthenticationDataSource authData) { - if (!role.startsWith("biscuit:")) { - return defaultProvider.allowNamespaceOperationAsync(namespaceName, role, operation, authData); - } - - Either<Error, Verifier> res = verifierFromBiscuit(role); - if (res.isLeft()) { - return CompletableFuture.failedFuture(new Exception(res.getLeft().toString())); - } - - Verifier verifier = res.get(); - verifier.set_time(); - verifier.add_fact(namespaceFact(namespaceName)).get(); - verifier.add_fact(namespaceOperationFact(namespaceName, operation)).get(); - verifier.add_rule("right(#authority, $tenant, $namespace, $operation) <- right(#authority, #admin), namespace_operation(#ambient, $tenant, $namespace, $operation), " + namespaceOperations + ".contains($operation)").get(); - verifier.add_check("check if right(#authority," + namespaceFactFragment(namespaceName) + "," + namespaceOperationSymbol(operation) + ")").get(); - verifier.allow(); - - Either verifierResult = verifier.verify(runLimits); - log.debug(verifier.print_world()); - - if (verifierResult.isLeft()) { - log.debug("Biscuit allowNamespaceOperationAsync [{}] on [{}] NOT authorized for role [{}]: {}", operation, namespaceName, role, verifierResult.getLeft()); - return isSuperUser(role, authData, this.conf); - } else { - log.debug("Biscuit allowNamespaceOperationAsync [{}] on [{}] authorized.", operation, namespaceName); - return CompletableFuture.completedFuture(true); - } + Set<String> facts = Set.of( + namespaceFact(namespaceName), + namespaceOperationFact(operation) + ); + Set<String> rules = Set.of("right($tenant, $namespace, $operation) <- namespace($tenant, $namespace), namespace_operation($operation), " + namespaceOperations + ".contains($operation)"); + Set<String> checks = Set.of("check if right(" + namespaceFragment(namespaceName) + "," + namespaceOperationFragment(operation) + ")"); + return authorize(() -> defaultProvider.allowNamespaceOperationAsync(namespaceName, role, operation, authData), true, "allowNamespaceOperationAsync(" + operation + " -> " + namespaceName + ")", role, authData, facts, rules, checks); } @Override public CompletableFuture<Boolean> allowNamespacePolicyOperationAsync(NamespaceName namespaceName, PolicyName policy, PolicyOperation operation, String role, AuthenticationDataSource authData) { - if (!role.startsWith("biscuit:")) { - return defaultProvider.allowNamespacePolicyOperationAsync(namespaceName, policy, operation, role, authData); - } - - Either<Error, Verifier> res = verifierFromBiscuit(role); - if (res.isLeft()) { - return CompletableFuture.failedFuture(new Exception(res.getLeft().toString())); - } - - Verifier verifier = res.get(); - verifier.set_time(); - verifier.add_fact(namespaceFact(namespaceName)).get(); - verifier.add_fact(namespacePolicyOperationFact(namespaceName, policy, operation)).get(); - verifier.add_rule("right(#authority, $tenant, $namespace, $operation) <- right(#authority, #admin), namespace_operation(#ambient, $tenant, $namespace, $operation), " + policiesOperations + ".contains($operation)").get(); - verifier.add_check("check if right(#authority," + namespaceFactFragment(namespaceName) + "," + policyOperationFact(policy, operation) + ")").get(); - verifier.allow(); - - Either verifierResult = verifier.verify(runLimits); - log.debug(verifier.print_world()); - - if (verifierResult.isLeft()) { - log.debug("Biscuit allowNamespacePolicyOperationAsync [{}]:[{}] on [{}] NOT authorized for role [{}]: {}", policy, operation, namespaceName, role, verifierResult.getLeft()); - return isSuperUser(role, authData, this.conf); - } else { - log.debug("Biscuit allowNamespacePolicyOperationAsync [{}]:[{}] on [{}] authorized.", policy, operation, namespaceName); - return CompletableFuture.completedFuture(true); - } + Set<String> facts = Set.of( + namespaceFact(namespaceName), + namespacePolicyOperationFact(policy, operation) + ); + Set<String> rules = Set.of("right($tenant, $namespace, $operation) <- namespace($tenant, $namespace), namespace_operation($operation), " + policiesOperations + ".contains($operation)"); + Set<String> checks = Set.of("check if right(" + namespaceFragment(namespaceName) + "," + namespacePolicyOperationFragment(policy, operation) + ")"); + return authorize(() -> defaultProvider.allowNamespacePolicyOperationAsync(namespaceName, policy, operation, role, authData), true, "allowNamespacePolicyOperationAsync(" + policy + "." + operation + " -> " + namespaceName + ")", role, authData, facts, rules, checks); } @Override - public CompletableFuture<Boolean> allowTopicOperationAsync(TopicName topicName, String role, - TopicOperation operation, - AuthenticationDataSource authData) { - if (!role.startsWith("biscuit:")) { - return defaultProvider.allowTopicOperationAsync(topicName, role, operation, authData); - } - - Either<Error, Verifier> res = verifierFromBiscuit(role); - if (res.isLeft()) { - return CompletableFuture.failedFuture(new Exception(res.getLeft().toString())); - } - - Verifier verifier = res.get(); - verifier.set_time(); - verifier.add_fact(topicFact(topicName)).get(); - verifier.add_fact(topicOperationFact(topicName, operation)).get(); - - // if produce|consume right is authorized then we authorize lookup + public CompletableFuture<Boolean> allowTopicOperationAsync(TopicName topicName, String role, TopicOperation operation, AuthenticationDataSource authData) { + Set<String> facts = new HashSet<>(Set.of( + topicFact(topicName), + topicOperationFact(operation) + )); if (operation.equals(TopicOperation.LOOKUP)) { - verifier.add_fact(topicOperationFact(topicName, TopicOperation.PRODUCE)).get(); - verifier.add_fact(topicOperationFact(topicName, TopicOperation.CONSUME)).get(); - } - - verifier.add_rule("right(#authority, $tenant, $namespace, $topic, $operation) <- right(#authority, #admin), topic_operation(#ambient, $tenant, $namespace, $topic, $operation)," + topicOperations + ".contains($operation)").get(); - verifier.add_check("check if right( #authority," + topicFactFragment(topicName) + "," + topicOperationSymbol(operation) + ")").get(); - verifier.allow(); - - Either verifierResult = verifier.verify(runLimits); - log.debug(verifier.print_world()); - - if (verifierResult.isLeft()) { - log.debug("Biscuit allowTopicOperationAsync [{}] on [{}] NOT authorized for role [{}]: {}", operation, topicName, role, verifierResult.getLeft()); - return isSuperUser(role, authData, this.conf); - } else { - log.debug("Biscuit allowTopicOperationAsync [{}] on [{}] authorized.", operation, topicName); - return CompletableFuture.completedFuture(true); + // if produce|consume right is authorized then we authorize lookup + 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); } @Override public CompletableFuture<Boolean> allowTopicPolicyOperationAsync(TopicName topicName, String role, PolicyName policy, PolicyOperation operation, AuthenticationDataSource authData) { - if (!role.startsWith("biscuit:")) { - return defaultProvider.allowTopicPolicyOperationAsync(topicName, role, policy, operation, authData); - } - - Either<Error, Verifier> res = verifierFromBiscuit(role); - if (res.isLeft()) { - return CompletableFuture.failedFuture(new Exception(res.getLeft().toString())); - } - - Verifier verifier = res.get(); - verifier.set_time(); - verifier.add_fact(topicFact(topicName)).get(); - verifier.add_fact(topicPolicyOperationFact(topicName, policy, operation)).get(); - verifier.add_rule("right(#authority, $tenant, $namespace, $topic, $operation) <- right(#authority, #admin), topic_operation(#ambient, $tenant, $namespace, $topic, $operation), " + policiesOperations + ".contains($operation)").get(); - verifier.add_check("check if right(#authority," + topicFactFragment(topicName) + "," + policyOperationFact(policy, operation) + ")").get(); - verifier.allow(); - - Either verifierResult = verifier.verify(runLimits); - log.debug(verifier.print_world()); - - if (verifierResult.isLeft()) { - log.debug("Biscuit allowTopicPolicyOperationAsync [{}]:[{}] on [{}] NOT authorized for role [{}]: {}", policy, operation, topicName, role, verifierResult.getLeft()); - return isSuperUser(role, authData, this.conf); - } else { - log.debug("Biscuit allowTopicPolicyOperationAsync [{}]:[{}] on [{}] authorized.", policy, operation, topicName); - return CompletableFuture.completedFuture(true); - } + Set<String> facts = Set.of( + topicFact(topicName), + topicPolicyOperationFact(policy, operation) + ); + Set<String> rules = Set.of("right($tenant, $namespace, $topic, $operation) <- topic($tenant, $namespace, $topic), topic_operation($operation), " + policiesOperations + ".contains($operation)"); + Set<String> checks = Set.of("check if right(" + topicFragment(topicName) + "," + topicPolicyOperationFragment(policy, operation) + ")"); + return authorize(() -> defaultProvider.allowTopicPolicyOperationAsync(topicName, role, policy, operation, authData), true, "allowTopicPolicyOperationAsync(" + policy + "." + operation + " -> " + topicName + ")", role, authData, facts, rules, checks); } // those management functions will be performed outside of the authorization provider diff --git a/src/main/java/com/clevercloud/biscuitpulsar/formatter/BiscuitFormatter.java b/src/main/java/com/clevercloud/biscuitpulsar/formatter/BiscuitFormatter.java index 0e99b94..66096b4 100644 --- a/src/main/java/com/clevercloud/biscuitpulsar/formatter/BiscuitFormatter.java +++ b/src/main/java/com/clevercloud/biscuitpulsar/formatter/BiscuitFormatter.java @@ -14,7 +14,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -public class BiscuitFormatter { +public final class BiscuitFormatter { /** * generates a string of biscuit symbols using the namespace operations * <p> @@ -26,7 +26,7 @@ public class BiscuitFormatter { public static final String namespaceOperations = Arrays.stream(BiscuitNamespaceOperation.values()) .map(namespaceOperation -> namespaceOperation.toString().toLowerCase()) - .collect(Collectors.joining(",#", "[#", "]")); + .collect(Collectors.joining("\",\"", "[\"", "\"]")); /** * generates a string of biscuit symbols using the policies operations * <p> @@ -38,7 +38,7 @@ public class BiscuitFormatter { public static final String policiesOperations = Arrays.stream(BiscuitPolicyOperation.values()) .map(policyOperation -> policyOperation.toString().toLowerCase()) - .collect(Collectors.joining(",#", "[#", "]")); + .collect(Collectors.joining("\",\"", "[\"", "\"]")); /** * generates a string of biscuit symbols using the topics operations @@ -51,52 +51,79 @@ public class BiscuitFormatter { public static final String topicOperations = Arrays.stream(BiscuitTopicOperation.values()) .map(topicOperation -> topicOperation.toString().toLowerCase()) - .collect(Collectors.joining(",#", "[#", "]")); + .collect(Collectors.joining("\",\"", "[\"", "\"]")); - public static String topicFactFragment(TopicName topic) { + public static String namespacePolicyOperationFact(PolicyName policy, PolicyOperation operation) { + return "namespace_operation(\"" + policy.toString().toLowerCase() + "_" + operation.toString().toLowerCase() + "\")"; + } + + public static String namespaceOperationFact(NamespaceOperation operation) { + return "namespace_operation(\"" + operation.toString().toLowerCase() + "\")"; + } + + public static String topicOperationFragment(TopicOperation operation) { + return "\"" + operation.name().toLowerCase() + "\""; + } + + public static String topicOperationFact(TopicOperation operation) { + return "topic_operation(" + topicOperationFragment(operation) + ")"; + } + + public static String topicPolicyOperationFact(PolicyName policy, PolicyOperation operation) { + return "topic_operation(\"" + policy.toString().toLowerCase() + "_" + operation.toString().toLowerCase() + "\")"; + } + + public static String topicPolicyOperationFragment(PolicyName policy, PolicyOperation operation) { + return "\"" + policy.name().toLowerCase() + "_" + operation.name().toLowerCase() + "\""; + } + + public static String topicFragment(TopicName topic) { return Stream.of(topic.getTenant(), topic.getNamespacePortion(), topic.getLocalName()) .collect(Collectors.joining("\",\"", "\"", "\"")); } - public static String namespaceFactFragment(NamespaceName namespace) { + public static String topicVariableFragment(NamespaceName namespace) { + return "\"" + namespace.getTenant() + "\",\"" + namespace.getLocalName() + "\", $topic"; + } + + public static String namespaceFragment(NamespaceName namespace) { return Stream.of(namespace.getTenant(), namespace.getLocalName()) .collect(Collectors.joining("\",\"", "\"", "\"")); } - public static String policyOperationFact(PolicyName policy, PolicyOperation operation) { - return "#" + policy.toString().toLowerCase() + "_" + operation.toString().toLowerCase(); + public static String namespaceOperationFragment(NamespaceOperation operation) { + return "\"" + operation.name().toLowerCase() + "\""; } - public static String topicOperationSymbol(TopicOperation operation) { - return "#" + operation.toString().toLowerCase(); + public static String namespacePolicyOperationFragment(PolicyName policy, PolicyOperation operation) { + return "\"" + policy.name().toLowerCase() + "_" + operation.name().toLowerCase() + "\""; } - public - static String namespaceOperationSymbol(NamespaceOperation operation) { - return "#" + operation.toString().toLowerCase(); + public static String topicFact(TopicName topic) { + return "topic(" + topicFragment(topic) + ")"; } - public static String namespacePolicyOperationFact(NamespaceName namespace, PolicyName policy, PolicyOperation operation) { - return "namespace_operation(#ambient," + namespaceFactFragment(namespace) + "," + policyOperationFact(policy, operation) + ")"; + public static String topicVariableFact(NamespaceName namespace) { + return "topic(" + topicVariableFragment(namespace) + ")"; } - public static String namespaceOperationFact(NamespaceName namespace, NamespaceOperation operation) { - return "namespace_operation(#ambient," + namespaceFactFragment(namespace) + "," + namespaceOperationSymbol(operation) + ")"; + public static String topicVariableFact(String tenant, String namespace) { + return "topic(" + topicVariableFragment(NamespaceName.get(tenant + "/" + namespace)) + ")"; } - public static String topicOperationFact(TopicName topic, TopicOperation operation) { - return "topic_operation(#ambient," + topicFactFragment(topic) + "," + topicOperationSymbol(operation) + ")"; + public static String namespaceFact(NamespaceName namespace) { + return "namespace(\"" + namespace.getTenant() + "\",\"" + namespace.getLocalName() + "\")"; } - public static String topicPolicyOperationFact(TopicName topic, PolicyName policy, PolicyOperation operation) { - return "topic_operation(#ambient," + topicFactFragment(topic) + "," + policyOperationFact(policy, operation) + ")"; + public static String namespaceFact(String tenant, String namespace) { + return namespaceFact(NamespaceName.get(tenant, namespace)); } - public static String topicFact(TopicName topic) { - return "topic(#ambient," + topicFactFragment(topic) + ")"; + public static String topicOperationCheck(TopicName topic, TopicOperation operation) { + return "check if " + topicFact(topic) + "," + topicOperationFact(operation); } - public static String namespaceFact(NamespaceName namespace) { - return "namespace(#ambient," + namespaceFactFragment(namespace) + ")"; - } + public static String adminFact = "right(\"admin\")"; + + public static String adminCheck = "check if " + adminFact; } diff --git a/src/main/java/resources/log4j2.xml b/src/main/java/resources/log4j2.xml deleted file mode 100644 index fc7e008..0000000 --- a/src/main/java/resources/log4j2.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Configuration status="debug"> - <Appenders> - <Console name="Console" target="SYSTEM_OUT"> - <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> - </Console> - </Appenders> - <Loggers> - <Root level="debug"> - <AppenderRef ref="Console"/> - </Root> - </Loggers> -</Configuration> diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..6dc986b --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration> + + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <layout class="ch.qos.logback.classic.PatternLayout"> + <pattern> + %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + </pattern> + </layout> + </appender> + + <logger name="com.clevercloud" level="info" additivity="false"> + <appender-ref ref="STDOUT"/> + </logger> + + <root level="error"> + <appender-ref ref="STDOUT"/> + </root> + +</configuration> \ No newline at end of file diff --git a/src/test/java/com/clevercloud/biscuitpulsar/AuthenticationProviderBiscuitTest.java b/src/test/java/com/clevercloud/biscuitpulsar/AuthenticationProviderBiscuitTest.java index 50ec687..4cc64b5 100644 --- a/src/test/java/com/clevercloud/biscuitpulsar/AuthenticationProviderBiscuitTest.java +++ b/src/test/java/com/clevercloud/biscuitpulsar/AuthenticationProviderBiscuitTest.java @@ -31,7 +31,7 @@ public void testAuthSecretKeyPair() throws Exception { LOGGER.info(root.toHex()); LOGGER.info("ROOT PUBLICKEY"); - LOGGER.info(hex(root.public_key().key.compress().toByteArray())); + LOGGER.info(hex(root.public_key().key.getAbyte())); SymbolTable symbols = Biscuit.default_symbol_table(); @@ -40,19 +40,18 @@ public void testAuthSecretKeyPair() throws Exception { byte[] seed = {0, 0, 0, 0}; SecureRandom rng = new SecureRandom(seed); - Biscuit b = Biscuit.make(rng, root, Biscuit.default_symbol_table(), authority_builder.build()).get(); + Biscuit b = Biscuit.make(rng, root, Biscuit.default_symbol_table(), authority_builder.build()); AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); + properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.getAbyte())); ServiceConfiguration conf = new ServiceConfiguration(); conf.setProperties(properties); provider.initialize(conf); - String biscuit = b.serialize_b64().get(); + String biscuit = b.serialize_b64url(); String subject = provider.authenticate(new AuthenticationDataSource() { @Override diff --git a/src/test/java/com/clevercloud/biscuitpulsar/AuthorizationProviderBiscuitTest.java b/src/test/java/com/clevercloud/biscuitpulsar/AuthorizationProviderBiscuitTest.java index 6b9b468..c67c782 100644 --- a/src/test/java/com/clevercloud/biscuitpulsar/AuthorizationProviderBiscuitTest.java +++ b/src/test/java/com/clevercloud/biscuitpulsar/AuthorizationProviderBiscuitTest.java @@ -2,9 +2,9 @@ import com.clevercloud.biscuit.crypto.KeyPair; import com.clevercloud.biscuit.datalog.SymbolTable; +import com.clevercloud.biscuit.error.Error; import com.clevercloud.biscuit.token.Biscuit; import com.clevercloud.biscuit.token.builder.Block; -import com.clevercloud.biscuit.token.builder.Check; import org.apache.pulsar.broker.ServiceConfiguration; import org.apache.pulsar.broker.authentication.AuthenticationDataSource; import org.apache.pulsar.common.naming.NamespaceName; @@ -19,46 +19,30 @@ import javax.naming.AuthenticationException; import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; -import java.time.Instant; -import java.util.Arrays; -import java.util.Date; +import java.security.SignatureException; import java.util.Properties; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import static com.clevercloud.biscuit.crypto.TokenSignature.hex; -import static com.clevercloud.biscuit.token.builder.Utils.*; -import static org.junit.Assert.*; +import static com.clevercloud.biscuitpulsar.formatter.BiscuitFormatter.*; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class AuthorizationProviderBiscuitTest { - private static final Logger log = LoggerFactory.getLogger(AuthorizationProviderBiscuitTest.class); - - @Test - public void testProduceAndNotConsumeOnTopic() 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"; - - Block authority_builder = new Block(0, symbols); - authority_builder.add_rule(rule("right", - Arrays.asList(s("authority"), string(tenant), string(namespace), string(topic), s("produce")), - Arrays.asList(pred("topic_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), string(topic), s("produce")))))); - Biscuit biscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); + static final Logger log = LoggerFactory.getLogger(AuthorizationProviderBiscuitTest.class); + private String authedBiscuit(KeyPair root, Biscuit biscuit) throws IOException, AuthenticationException { AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); + properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.getAbyte())); ServiceConfiguration conf = new ServiceConfiguration(); conf.setProperties(properties); provider.initialize(conf); - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { + + return provider.authenticate(new AuthenticationDataSource() { @Override public boolean hasDataFromCommand() { return true; @@ -66,10 +50,32 @@ public boolean hasDataFromCommand() { @Override public String getCommandData() { - return biscuit.serialize_b64().get(); + try { + return biscuit.serialize_b64url(); + } catch (Error.FormatError.SerializationError e) { + log.error("Can't deserialize biscuit due to: {}", e.getMessage()); + return ""; + } } }); + } + + @Test + public void testProduceAndNotConsumeOnTopic() 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"; + + Block block0 = new Block(0, symbols); + block0.add_fact(adminFact); + block0.add_check(topicOperationCheck(TopicName.get(tenant + "/" + namespace + "/" + topic), TopicOperation.PRODUCE)); + Biscuit biscuit = Biscuit.make(rng, root, symbols, block0.build()); + + String authedBiscuit = authedBiscuit(root, biscuit); AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); log.debug(biscuit.print()); assertTrue(authorizationProvider.allowTopicOperation(TopicName.get(tenant + "/" + namespace + "/" + topic), authedBiscuit, TopicOperation.PRODUCE, null)); @@ -86,39 +92,15 @@ public void testProduceAndNotConsumeAttenuatedOnTopic() throws Exception { String namespace = "namespaceTest"; String topic = "topicTest"; - Block authority_builder = new Block(0, symbols); - authority_builder.add_fact(fact("revocation_id", Arrays.asList(date(Date.from(Instant.now()))))); - authority_builder.add_fact(fact("right", Arrays.asList(s("authority"), s("admin")))); - Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); + Block block0 = new Block(0, symbols); + block0.add_fact(adminFact); + Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, block0.build()); - Block block = rootBiscuit.create_block(); - block.add_check(new Check(Arrays.asList( - rule("limited_right", - Arrays.asList(string(tenant), string(namespace), string(topic), s("produce")), - Arrays.asList(pred("topic_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), string(topic), s("produce"))))) - ))); - - Biscuit biscuit = rootBiscuit.attenuate(rng, root, block.build()).get(); - - AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); - Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); - ServiceConfiguration conf = new ServiceConfiguration(); - conf.setProperties(properties); - provider.initialize(conf); - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { - @Override - public boolean hasDataFromCommand() { - return true; - } - - @Override - public String getCommandData() { - return biscuit.serialize_b64().get(); - } - }); + Block block1 = rootBiscuit.create_block(); + block1.add_check(topicOperationCheck(TopicName.get(tenant + "/" + namespace + "/" + topic), TopicOperation.PRODUCE)); + Biscuit biscuit = rootBiscuit.attenuate(rng, root, block1.build()); + String authedBiscuit = authedBiscuit(root, biscuit); AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); log.debug(biscuit.print()); assertTrue(authorizationProvider.allowTopicOperation(TopicName.get(tenant + "/" + namespace + "/" + topic), authedBiscuit, TopicOperation.PRODUCE, null)); @@ -135,31 +117,12 @@ public void testConsumeAndNotProduceOnTopic() throws Exception { String namespace = "namespaceTest"; String topic = "topicTest"; - Block authority_builder = new Block(0, symbols); - authority_builder.add_rule(rule("right", - Arrays.asList(s("authority"), string(tenant), string(namespace), string(topic), s("consume")), - Arrays.asList(pred("topic_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), string(topic), s("consume")))))); - Biscuit biscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); - - AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); - Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); - ServiceConfiguration conf = new ServiceConfiguration(); - conf.setProperties(properties); - provider.initialize(conf); - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { - @Override - public boolean hasDataFromCommand() { - return true; - } - - @Override - public String getCommandData() { - return biscuit.serialize_b64().get(); - } - }); + Block block0 = new Block(0, symbols); + block0.add_fact(adminFact); + block0.add_check(topicOperationCheck(TopicName.get(tenant + "/" + namespace + "/" + topic), TopicOperation.CONSUME)); + Biscuit biscuit = Biscuit.make(rng, root, symbols, block0.build()); + String authedBiscuit = authedBiscuit(root, biscuit); AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); log.debug(biscuit.print()); assertFalse(authorizationProvider.allowTopicOperation(TopicName.get(tenant + "/" + namespace + "/" + topic), authedBiscuit, TopicOperation.PRODUCE, null)); @@ -176,41 +139,16 @@ public void testConsumerAndNotProduceAttenuatedOnTopic() throws Exception { String namespace = "namespaceTest"; String topic = "topicTest"; - Block authority_builder = new Block(0, symbols); - authority_builder.add_fact(fact("revocation_id", Arrays.asList(date(Date.from(Instant.now()))))); - authority_builder.add_fact(fact("right", Arrays.asList(s("authority"), s("admin")))); - Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); + Block block0 = new Block(0, symbols); + block0.add_fact(adminFact); + Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, block0.build()); - Block block = rootBiscuit.create_block(); - block.add_check(new Check(Arrays.asList( - rule("limited_right", - Arrays.asList(string(tenant), string(namespace), string(topic), s("consume")), - Arrays.asList(pred("topic_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), string(topic), s("consume"))))) - ))); - - Biscuit biscuit = rootBiscuit.attenuate(rng, root, block.build()).get(); - - AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); - Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); - ServiceConfiguration conf = new ServiceConfiguration(); - conf.setProperties(properties); - provider.initialize(conf); - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { - @Override - public boolean hasDataFromCommand() { - return true; - } - - @Override - public String getCommandData() { - return biscuit.serialize_b64().get(); - } - }); + Block block1 = rootBiscuit.create_block(); + block1.add_check(topicOperationCheck(TopicName.get(tenant + "/" + namespace + "/" + topic), TopicOperation.CONSUME)); + Biscuit biscuit = rootBiscuit.attenuate(rng, root, block1.build()); + String authedBiscuit = authedBiscuit(root, biscuit); AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); - log.debug(biscuit.print()); assertFalse(authorizationProvider.allowTopicOperation(TopicName.get(tenant + "/" + namespace + "/" + topic), authedBiscuit, TopicOperation.PRODUCE, null)); assertTrue(authorizationProvider.allowTopicOperation(TopicName.get(tenant + "/" + namespace + "/" + topic), authedBiscuit, TopicOperation.CONSUME, null)); } @@ -224,31 +162,12 @@ public void testTopicCreation() throws Exception { String tenant = "tenantTest"; String namespace = "namespaceTest"; - Block authority_builder = new Block(0, symbols); - authority_builder.add_rule(rule("right", - Arrays.asList(s("authority"), string(tenant), string(namespace), s("create_topic")), - Arrays.asList(pred("namespace_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), s("create_topic")))))); - Biscuit biscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); - - AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); - Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); - ServiceConfiguration conf = new ServiceConfiguration(); - conf.setProperties(properties); - provider.initialize(conf); - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { - @Override - public boolean hasDataFromCommand() { - return true; - } - - @Override - public String getCommandData() { - return biscuit.serialize_b64().get(); - } - }); + Block block0 = new Block(0, symbols); + block0.add_fact(adminFact); + block0.add_rule("right($tenant, $namespace, \"create_topic\") <- namespace($tenant, $namespace), namespace_operation(\"create_topic\")"); + Biscuit biscuit = Biscuit.make(rng, root, symbols, block0.build()); + String authedBiscuit = authedBiscuit(root, biscuit); AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); log.debug(biscuit.print()); assertTrue(authorizationProvider.allowNamespaceOperation(NamespaceName.get(tenant + "/" + namespace), authedBiscuit, NamespaceOperation.CREATE_TOPIC, null)); @@ -263,40 +182,14 @@ public void testReadWriteTopicInNamespace() throws Exception { String tenant = "tenantTest"; String namespace = "namespaceTest"; - Block authority_builder = new Block(0, symbols); - authority_builder.add_rule(rule("right", - Arrays.asList(s("authority"), string(tenant), string(namespace), s("create_topic")), - Arrays.asList(pred("namespace_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), s("create_topic")))))); - authority_builder.add_rule(rule("right", - Arrays.asList(s("authority"), string(tenant), string(namespace), var("2"), s("produce")), - Arrays.asList(pred("topic_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), var("2"), s("produce")))))); - authority_builder.add_rule(rule("right", - Arrays.asList(s("authority"), string(tenant), string(namespace), var("2"), s("consume")), - Arrays.asList(pred("topic_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), var("2"), s("consume")))))); - Biscuit biscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); - - AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); - Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); - ServiceConfiguration conf = new ServiceConfiguration(); - conf.setProperties(properties); - provider.initialize(conf); - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { - @Override - public boolean hasDataFromCommand() { - return true; - } - - @Override - public String getCommandData() { - return biscuit.serialize_b64().get(); - } - }); + Block block0 = new Block(0, symbols); + block0.add_fact(adminFact); + block0.add_check("check if " + topicVariableFact(NamespaceName.get(tenant + "/" + namespace)) + ", topic_operation($operation), [\"produce\",\"consume\"].contains($operation)"); + Biscuit biscuit = Biscuit.make(rng, root, symbols, block0.build()); + String authedBiscuit = authedBiscuit(root, biscuit); log.debug(biscuit.print()); AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); - assertTrue(authorizationProvider.allowNamespaceOperation(NamespaceName.get(tenant + "/" + namespace), authedBiscuit, NamespaceOperation.CREATE_TOPIC, null)); assertTrue(authorizationProvider.allowTopicOperation(TopicName.get(tenant + "/" + namespace + "/" + "test"), authedBiscuit, TopicOperation.CONSUME, null)); assertTrue(authorizationProvider.allowTopicOperation(TopicName.get(tenant + "/" + namespace + "/" + "test123"), authedBiscuit, TopicOperation.CONSUME, null)); assertTrue(authorizationProvider.allowTopicOperation(TopicName.get(tenant + "/" + namespace + "/" + "test"), authedBiscuit, TopicOperation.PRODUCE, null)); @@ -304,7 +197,7 @@ public String getCommandData() { } @Test - public void testTopicOperation() throws IOException, AuthenticationException, ExecutionException, InterruptedException { + public void testTopicOperation() throws IOException, AuthenticationException, ExecutionException, InterruptedException, Error, NoSuchAlgorithmException, SignatureException, InvalidKeyException { SecureRandom rng = new SecureRandom(); KeyPair root = new KeyPair(rng); SymbolTable symbols = Biscuit.default_symbol_table(); @@ -312,42 +205,15 @@ public void testTopicOperation() throws IOException, AuthenticationException, Ex String tenant = "tenantTest"; String namespace = "namespaceTest"; - Block authority_builder = new Block(0, symbols); - authority_builder.add_fact(fact("revocation_id", Arrays.asList(date(Date.from(Instant.now()))))); - authority_builder.add_fact(fact("right", Arrays.asList(s("authority"), s("admin")))); - Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); - - Block block = rootBiscuit.create_block(); - block.add_check(new Check(Arrays.asList( - rule("limited_right", - Arrays.asList(string(tenant), string(namespace), var("2"), var("3")), - Arrays.asList(pred("topic_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), var("2"), var("3"))))), - rule("limited_right", - Arrays.asList(string(tenant), string(namespace), var("2")), - Arrays.asList(pred("namespace_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), var("2"))))) - ))); + Block block0 = new Block(0, symbols); + block0.add_fact(adminFact); + Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, block0.build()); - Biscuit biscuit = rootBiscuit.attenuate(rng, root, block.build()).get(); - - AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); - Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); - ServiceConfiguration conf = new ServiceConfiguration(); - conf.setProperties(properties); - provider.initialize(conf); - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { - @Override - public boolean hasDataFromCommand() { - return true; - } - - @Override - public String getCommandData() { - return biscuit.serialize_b64().get(); - } - }); + Block block1 = rootBiscuit.create_block(); + block1.add_check("check if " + topicVariableFact(tenant, namespace) + ", topic_operation($4)"); + Biscuit biscuit = rootBiscuit.attenuate(rng, root, block1.build()); + String authedBiscuit = authedBiscuit(root, biscuit); log.debug(biscuit.print()); AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); assertTrue(authorizationProvider.allowTopicOperationAsync(TopicName.get(tenant + "/" + namespace + "/" + "test"), authedBiscuit, TopicOperation.PRODUCE, null).get()); @@ -355,7 +221,7 @@ public String getCommandData() { } @Test - public void testNsLimitations() throws Exception { + public void testLimitations() throws Exception { SecureRandom rng = new SecureRandom(); KeyPair root = new KeyPair(rng); SymbolTable symbols = Biscuit.default_symbol_table(); @@ -363,41 +229,15 @@ public void testNsLimitations() throws Exception { String tenant = "tenantTest"; String namespace = "namespaceTest"; - Block authority_builder = new Block(0, symbols); - authority_builder.add_fact(fact("revocation_id", Arrays.asList(date(Date.from(Instant.now()))))); - authority_builder.add_fact(fact("right", Arrays.asList(s("authority"), s("admin")))); - Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); - - Block block = rootBiscuit.create_block(); - block.add_check(new Check(Arrays.asList( - rule("limited_right", - Arrays.asList(string(tenant), string(namespace), var("2"), var("3")), - Arrays.asList(pred("topic_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), var("2"), var("3"))))), - rule("limited_right", - Arrays.asList(string(tenant), string(namespace), var("2")), - Arrays.asList(pred("namespace_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), var("2"))))) - ))); - - Biscuit biscuit = rootBiscuit.attenuate(rng, root, block.build()).get(); - AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); - Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); - ServiceConfiguration conf = new ServiceConfiguration(); - conf.setProperties(properties); - provider.initialize(conf); - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { - @Override - public boolean hasDataFromCommand() { - return true; - } + Block block0 = new Block(0, symbols); + block0.add_fact(adminFact); + Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, block0.build()); - @Override - public String getCommandData() { - return biscuit.serialize_b64().get(); - } - }); + Block block1 = rootBiscuit.create_block(); + block1.add_check("check if " + namespaceFact(tenant, namespace) + " or " + topicVariableFact(tenant, namespace)); + Biscuit biscuit = rootBiscuit.attenuate(rng, root, block1.build()); + String authedBiscuit = authedBiscuit(root, biscuit); AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); log.debug(biscuit.print()); @@ -433,110 +273,40 @@ public String getSubscription() { assertTrue(authorizationProvider.allowTopicOperation(TopicName.get(tenant + "/" + namespace + "/" + "test"), authedBiscuit, TopicOperation.PRODUCE, null)); assertTrue(authorizationProvider.allowTopicOperation(TopicName.get(tenant + "/" + namespace + "/" + "test123"), authedBiscuit, TopicOperation.CONSUME, authData)); assertTrue(authorizationProvider.allowTopicOperation(TopicName.get(tenant + "/" + namespace + "/" + "test123"), authedBiscuit, TopicOperation.PRODUCE, null)); - assertFalse(authorizationProvider.isSuperUser(authedBiscuit, null, conf).get()); - } - - @Test - public void testBuilders() { - SecureRandom rng = new SecureRandom(); - KeyPair root = new KeyPair(rng); - SymbolTable symbols = Biscuit.default_symbol_table(); - - Block authority_builder = new Block(0, symbols); - authority_builder.add_fact(fact("revocation_id", Arrays.asList(date(Date.from(Instant.now()))))); - authority_builder.add_fact(fact("right", Arrays.asList(s("authority"), s("admin")))); - authority_builder.add_rule("right(#authority, $tenant, $namespace, $operation) <- " + - "right(#authority, #admin), namespace_operation(#ambient, $tenant, $namespace, $operation), " + - "[ #create_topic, #get_topic, #get_topics ].contains($operation)").get(); - authority_builder.add_rule("right(#authority, \"topic\", $tenant, $namespace, $topic, $operation) <- " + - "right(#authority, #admin), topic_operation(#authority, $tenant, $namespace, $topic, $operation), " + - "[ #lookup ].contains($operation)").get(); + assertTrue(authorizationProvider.allowTopicPolicyOperation(TopicName.get(tenant + "/" + namespace + "/" + "test"), authedBiscuit, PolicyName.ALL, PolicyOperation.READ, null)); + assertFalse(authorizationProvider.allowTopicPolicyOperation(TopicName.get(tenant + "/" + namespace + "/" + "test"), authedBiscuit, PolicyName.ALL, PolicyOperation.WRITE, null)); - - Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); - assertNotNull(rootBiscuit); - } - - @Test - public void testSuperUser() throws IOException, AuthenticationException, ExecutionException, InterruptedException { - SecureRandom rng = new SecureRandom(); - KeyPair root = new KeyPair(rng); - SymbolTable symbols = Biscuit.default_symbol_table(); - - Block authority_builder = new Block(0, symbols); - authority_builder.add_fact(fact("revocation_id", Arrays.asList(date(Date.from(Instant.now()))))); - authority_builder.add_fact(fact("right", Arrays.asList(s("authority"), s("admin")))); - Biscuit biscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); - - AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); + properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.getAbyte())); ServiceConfiguration conf = new ServiceConfiguration(); conf.setProperties(properties); - provider.initialize(conf); - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { - @Override - public boolean hasDataFromCommand() { - return true; - } - - @Override - public String getCommandData() { - return biscuit.serialize_b64().get(); - } - }); - - log.debug(biscuit.print()); - - AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); - assertTrue(authorizationProvider.isSuperUser(authedBiscuit, null, conf).get()); - assertTrue(authorizationProvider.allowNamespacePolicyOperation(NamespaceName.get("randomTenant/randomNamespace"), PolicyName.REPLICATION, PolicyOperation.WRITE, authedBiscuit, null)); + assertFalse(authorizationProvider.isSuperUser(authedBiscuit, null, conf).get()); } @Test - public void testSimpleSuperUser() throws IOException, AuthenticationException, ExecutionException, InterruptedException { + public void testSuperUser() throws IOException, AuthenticationException, ExecutionException, InterruptedException, Error.SymbolTableOverlap, Error.FormatError, Error.Language, Error.Parser { SecureRandom rng = new SecureRandom(); KeyPair root = new KeyPair(rng); SymbolTable symbols = Biscuit.default_symbol_table(); - Block authority_builder = new Block(0, symbols); - authority_builder.add_rule( - rule("right", - Arrays.asList(s("authority"), s("admin")), - Arrays.asList(pred("right", Arrays.asList(s("authority"), string("admin")))) - ) - ); - authority_builder.add_fact(fact("right", Arrays.asList(s("authority"), s("admin")))); - Biscuit biscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); + Block block0 = new Block(0, symbols); + block0.add_fact(adminFact); + Biscuit biscuit = Biscuit.make(rng, root, symbols, block0.build()); - AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); + String authedBiscuit = authedBiscuit(root, biscuit); + log.debug(biscuit.print()); + + AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); + properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.getAbyte())); ServiceConfiguration conf = new ServiceConfiguration(); conf.setProperties(properties); - provider.initialize(conf); - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { - @Override - public boolean hasDataFromCommand() { - return true; - } - - @Override - public String getCommandData() { - return biscuit.serialize_b64().get(); - } - }); - - log.debug(biscuit.print()); - AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); - CompletableFuture<Boolean> authorizedFuture = authorizationProvider.isSuperUser(authedBiscuit, null, conf); - assertTrue(authorizedFuture.get()); + assertTrue(authorizationProvider.isSuperUser(authedBiscuit, null, conf).get()); + assertTrue(authorizationProvider.allowNamespacePolicyOperation(NamespaceName.get("randomTenant/randomNamespace"), PolicyName.REPLICATION, PolicyOperation.WRITE, authedBiscuit, null)); } @Test - public void testNsLimitationsThenPrefixLimitation() throws IOException, AuthenticationException, ExecutionException, InterruptedException { + public void testNsLimitationsThenPrefixLimitation() throws IOException, AuthenticationException, ExecutionException, InterruptedException, Error, NoSuchAlgorithmException, SignatureException, InvalidKeyException { SecureRandom rng = new SecureRandom(); KeyPair root = new KeyPair(rng); SymbolTable symbols = Biscuit.default_symbol_table(); @@ -544,58 +314,22 @@ public void testNsLimitationsThenPrefixLimitation() throws IOException, Authenti String tenant = "tenantTest"; String namespace = "namespaceTest"; - // root token - Block authority_builder = new Block(0, symbols); - authority_builder.add_fact(fact("revocation_id", Arrays.asList(date(Date.from(Instant.now()))))); - authority_builder.add_fact(fact("right", Arrays.asList(s("authority"), s("admin")))); - Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); + Block block0 = new Block(0, symbols); + block0.add_fact(adminFact); + Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, block0.build()); // limit on ns tenant/namespace - Block block = rootBiscuit.create_block(); - block.add_check(new Check(Arrays.asList( - rule("limited_right", - Arrays.asList(string(tenant), string(namespace), var("2"), var("3")), - Arrays.asList(pred("topic_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), var("2"), var("3"))))), - rule("limited_right", - Arrays.asList(string(tenant), string(namespace), var("2")), - Arrays.asList(pred("namespace_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), var("2"))))) - ))); - Biscuit biscuit = rootBiscuit.attenuate(rng, root, block.build()).get(); + Block block1 = rootBiscuit.create_block(); + block1.add_check("check if " + namespaceFact(tenant, namespace) + " or " + topicVariableFact(tenant, namespace)); + Biscuit biscuit = rootBiscuit.attenuate(rng, root, block1.build()); // limit on tenant/namespace/PREFIX* String PREFIX = "INSTANCE_PREFIX_TO_DEFINE"; - Block attenuated = biscuit.create_block(); - /* - attenuated.add_check(Check(constrained_rule("limited_topic", - Arrays.asList(string(tenant), string(namespace), var("2")), - Arrays.asList(pred("topic_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), var("2"), var("3")))), - Arrays.asList(new StrConstraint.Prefix(2, PREFIX)) - ))); - - */ - attenuated.add_check("check if topic_operation(#ambient, \"" + tenant + "\", \"" + namespace + "\", $topic, $operation), " + - "$topic.starts_with(\"" + PREFIX + "\")").get(); - biscuit = biscuit.attenuate(rng, root, attenuated.build()).get(); - - AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); - Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); - ServiceConfiguration conf = new ServiceConfiguration(); - conf.setProperties(properties); - provider.initialize(conf); - Biscuit finalBiscuit = biscuit; - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { - @Override - public boolean hasDataFromCommand() { - return true; - } + Block block2 = biscuit.create_block(); + block2.add_check("check if " + topicVariableFact(tenant, namespace) + ", $topic.starts_with(\"" + PREFIX + "\")"); + biscuit = biscuit.attenuate(rng, root, block2.build()); - @Override - public String getCommandData() { - return finalBiscuit.serialize_b64().get(); - } - }); + String authedBiscuit = authedBiscuit(root, biscuit); AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); @@ -606,7 +340,7 @@ public String getCommandData() { } @Test - public void testLimitProduceOnTopicStartsWith() throws IOException, AuthenticationException, ExecutionException, InterruptedException { + public void testLimitProduceOnTopicStartsWith() throws IOException, AuthenticationException, ExecutionException, InterruptedException, Error, NoSuchAlgorithmException, SignatureException, InvalidKeyException { SecureRandom rng = new SecureRandom(); KeyPair root = new KeyPair(rng); SymbolTable symbols = Biscuit.default_symbol_table(); @@ -615,44 +349,17 @@ public void testLimitProduceOnTopicStartsWith() throws IOException, Authenticati String namespace = "namespaceTest"; // root token - Block authority_builder = new Block(0, symbols); - authority_builder.add_fact(fact("revocation_id", Arrays.asList(string(UUID.randomUUID().toString())))); - authority_builder.add_fact(fact("right", Arrays.asList(s("authority"), s("admin")))); - Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); + Block block0 = new Block(0, symbols); + block0.add_fact(adminFact); + Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, block0.build()); // limit on tenant/namespace/PREFIX* String PREFIX = "PREFIX"; - Block attenuated = rootBiscuit.create_block(); - /* - attenuated.add_check(Check(constrained_rule("limited_topic", - Arrays.asList(string(tenant), string(namespace), var("2")), - Arrays.asList(pred("topic_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), var("2"), s("produce")))), - Arrays.asList(new StrConstraint.Prefix(2, PREFIX)) - ))); - */ - attenuated.add_check("check if topic_operation(#ambient, \"" + tenant + "\", \"" + namespace + "\", $topic, #produce), " + - "$topic.starts_with(\"" + PREFIX + "\")").get(); - Biscuit biscuit = rootBiscuit.attenuate(rng, root, attenuated.build()).get(); + Block block2 = rootBiscuit.create_block(); + block2.add_check("check if " + topicVariableFact(tenant, namespace) + "," + topicOperationFact(TopicOperation.PRODUCE) + ", $topic.starts_with(\"" + PREFIX + "\")"); + Biscuit biscuit = rootBiscuit.attenuate(rng, root, block2.build()); - AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); - Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); - ServiceConfiguration conf = new ServiceConfiguration(); - conf.setProperties(properties); - provider.initialize(conf); - Biscuit finalBiscuit = biscuit; - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { - @Override - public boolean hasDataFromCommand() { - return true; - } - - @Override - public String getCommandData() { - return finalBiscuit.serialize_b64().get(); - } - }); + String authedBiscuit = authedBiscuit(root, biscuit); AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); @@ -666,7 +373,7 @@ public String getCommandData() { } @Test - public void testConsumeOverrideLookup() throws IOException, AuthenticationException, ExecutionException, InterruptedException { + public void testConsumeOverrideLookup() throws IOException, AuthenticationException, ExecutionException, InterruptedException, Error, NoSuchAlgorithmException, SignatureException, InvalidKeyException { SecureRandom rng = new SecureRandom(); KeyPair root = new KeyPair(rng); SymbolTable symbols = Biscuit.default_symbol_table(); @@ -674,38 +381,15 @@ public void testConsumeOverrideLookup() throws IOException, AuthenticationExcept String tenant = "tenantTest"; String namespace = "namespaceTest"; - Block authority_builder = new Block(0, symbols); - authority_builder.add_fact(fact("revocation_id", Arrays.asList(date(Date.from(Instant.now()))))); - authority_builder.add_fact(fact("right", Arrays.asList(s("authority"), s("admin")))); - Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); + Block block0 = new Block(0, symbols); + block0.add_fact(adminFact); + Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, block0.build()); - Block block = rootBiscuit.create_block(); - block.add_check(new Check(Arrays.asList( - rule("limited_right", - Arrays.asList(string(tenant), string(namespace), var("2"), var("3")), - Arrays.asList(pred("topic_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), var("2"), s("consume"))))) - ))); + Block block1 = rootBiscuit.create_block(); + block1.add_check("check if " + topicVariableFact(tenant, namespace) + "," + topicOperationFact(TopicOperation.CONSUME)); + Biscuit biscuit = rootBiscuit.attenuate(rng, root, block1.build()); - Biscuit biscuit = rootBiscuit.attenuate(rng, root, block.build()).get(); - - AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); - Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); - ServiceConfiguration conf = new ServiceConfiguration(); - conf.setProperties(properties); - provider.initialize(conf); - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { - @Override - public boolean hasDataFromCommand() { - return true; - } - - @Override - public String getCommandData() { - return biscuit.serialize_b64().get(); - } - }); + String authedBiscuit = authedBiscuit(root, biscuit); log.debug(biscuit.print()); AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); @@ -714,7 +398,7 @@ public String getCommandData() { } @Test - public void testProduceOverrideLookup() throws IOException, AuthenticationException, ExecutionException, InterruptedException { + public void testProduceOverrideLookup() throws IOException, AuthenticationException, ExecutionException, InterruptedException, Error, NoSuchAlgorithmException, SignatureException, InvalidKeyException { SecureRandom rng = new SecureRandom(); KeyPair root = new KeyPair(rng); SymbolTable symbols = Biscuit.default_symbol_table(); @@ -722,38 +406,15 @@ public void testProduceOverrideLookup() throws IOException, AuthenticationExcept String tenant = "tenantTest"; String namespace = "namespaceTest"; - Block authority_builder = new Block(0, symbols); - authority_builder.add_fact(fact("revocation_id", Arrays.asList(date(Date.from(Instant.now()))))); - authority_builder.add_fact(fact("right", Arrays.asList(s("authority"), s("admin")))); - Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); - - Block block = rootBiscuit.create_block(); - block.add_check(new Check(Arrays.asList( - rule("limited_right", - Arrays.asList(string(tenant), string(namespace), var("2"), var("3")), - Arrays.asList(pred("topic_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), var("2"), s("produce"))))) - ))); + Block block0 = new Block(0, symbols); + block0.add_fact(adminFact); + Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, block0.build()); - Biscuit biscuit = rootBiscuit.attenuate(rng, root, block.build()).get(); - - AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); - Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); - ServiceConfiguration conf = new ServiceConfiguration(); - conf.setProperties(properties); - provider.initialize(conf); - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { - @Override - public boolean hasDataFromCommand() { - return true; - } + Block block1 = rootBiscuit.create_block(); + block1.add_check("check if " + topicVariableFact(tenant, namespace) + "," + topicOperationFact(TopicOperation.PRODUCE)); + Biscuit biscuit = rootBiscuit.attenuate(rng, root, block1.build()); - @Override - public String getCommandData() { - return biscuit.serialize_b64().get(); - } - }); + String authedBiscuit = authedBiscuit(root, biscuit); log.debug(biscuit.print()); AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); @@ -762,7 +423,7 @@ public String getCommandData() { } @Test - public void testLookupIsNotOverrodeByProduce() throws IOException, AuthenticationException, ExecutionException, InterruptedException { + public void testLookupIsNotOverrodeByProduceOrConsume() throws IOException, AuthenticationException, ExecutionException, InterruptedException, Error, NoSuchAlgorithmException, SignatureException, InvalidKeyException { SecureRandom rng = new SecureRandom(); KeyPair root = new KeyPair(rng); SymbolTable symbols = Biscuit.default_symbol_table(); @@ -770,90 +431,20 @@ public void testLookupIsNotOverrodeByProduce() throws IOException, Authenticatio String tenant = "tenantTest"; String namespace = "namespaceTest"; - Block authority_builder = new Block(0, symbols); - authority_builder.add_fact(fact("revocation_id", Arrays.asList(date(Date.from(Instant.now()))))); - authority_builder.add_fact(fact("right", Arrays.asList(s("authority"), s("admin")))); - Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); - - Block block = rootBiscuit.create_block(); - block.add_check(new Check(Arrays.asList( - rule("limited_right", - Arrays.asList(string(tenant), string(namespace), var("2"), var("3")), - Arrays.asList(pred("topic_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), var("2"), s("lookup"))))) - ))); + Block block0 = new Block(0, symbols); + block0.add_fact(adminFact); + Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, block0.build()); - Biscuit biscuit = rootBiscuit.attenuate(rng, root, block.build()).get(); - - AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); - Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); - ServiceConfiguration conf = new ServiceConfiguration(); - conf.setProperties(properties); - provider.initialize(conf); - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { - @Override - public boolean hasDataFromCommand() { - return true; - } + Block block1 = rootBiscuit.create_block(); + block1.add_check("check if " + topicVariableFact(tenant, namespace) + "," + topicOperationFact(TopicOperation.LOOKUP)); + Biscuit biscuit = rootBiscuit.attenuate(rng, root, block1.build()); - @Override - public String getCommandData() { - return biscuit.serialize_b64().get(); - } - }); + String authedBiscuit = authedBiscuit(root, biscuit); log.debug(biscuit.print()); AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); assertTrue(authorizationProvider.allowTopicOperationAsync(TopicName.get(tenant + "/" + namespace + "/" + "test"), authedBiscuit, TopicOperation.LOOKUP, null).get()); assertFalse(authorizationProvider.allowTopicOperationAsync(TopicName.get(tenant + "/" + namespace + "/" + "test"), authedBiscuit, TopicOperation.PRODUCE, null).get()); - } - - @Test - public void testLookupIsNotOverrodeByConsume() throws IOException, AuthenticationException, ExecutionException, InterruptedException { - SecureRandom rng = new SecureRandom(); - KeyPair root = new KeyPair(rng); - SymbolTable symbols = Biscuit.default_symbol_table(); - - String tenant = "tenantTest"; - String namespace = "namespaceTest"; - - Block authority_builder = new Block(0, symbols); - authority_builder.add_fact(fact("revocation_id", Arrays.asList(date(Date.from(Instant.now()))))); - authority_builder.add_fact(fact("right", Arrays.asList(s("authority"), s("admin")))); - Biscuit rootBiscuit = Biscuit.make(rng, root, symbols, authority_builder.build()).get(); - - Block block = rootBiscuit.create_block(); - block.add_check(new Check(Arrays.asList( - rule("limited_right", - Arrays.asList(string(tenant), string(namespace), var("2"), var("3")), - Arrays.asList(pred("topic_operation", Arrays.asList(s("ambient"), string(tenant), string(namespace), var("2"), s("lookup"))))) - ))); - - Biscuit biscuit = rootBiscuit.attenuate(rng, root, block.build()).get(); - - AuthenticationProviderBiscuit provider = new AuthenticationProviderBiscuit(); - Properties properties = new Properties(); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_PUBLIC_ROOT_KEY, hex(root.public_key().key.compress().toByteArray())); - properties.setProperty(AuthenticationProviderBiscuit.CONF_BISCUIT_SEALING_KEY, "test"); - ServiceConfiguration conf = new ServiceConfiguration(); - conf.setProperties(properties); - provider.initialize(conf); - String authedBiscuit = provider.authenticate(new AuthenticationDataSource() { - @Override - public boolean hasDataFromCommand() { - return true; - } - - @Override - public String getCommandData() { - return biscuit.serialize_b64().get(); - } - }); - - log.debug(biscuit.print()); - AuthorizationProviderBiscuit authorizationProvider = new AuthorizationProviderBiscuit(); - assertTrue(authorizationProvider.allowTopicOperationAsync(TopicName.get(tenant + "/" + namespace + "/" + "test"), authedBiscuit, TopicOperation.LOOKUP, null).get()); assertFalse(authorizationProvider.allowTopicOperationAsync(TopicName.get(tenant + "/" + namespace + "/" + "test"), authedBiscuit, TopicOperation.CONSUME, null).get()); } } \ No newline at end of file diff --git a/src/test/java/com/clevercloud/biscuitpulsar/formatter/BiscuitFormatterTest.java b/src/test/java/com/clevercloud/biscuitpulsar/formatter/BiscuitFormatterTest.java index 41d1abe..e350aa3 100644 --- a/src/test/java/com/clevercloud/biscuitpulsar/formatter/BiscuitFormatterTest.java +++ b/src/test/java/com/clevercloud/biscuitpulsar/formatter/BiscuitFormatterTest.java @@ -1,8 +1,5 @@ package com.clevercloud.biscuitpulsar.formatter; -import org.apache.pulsar.common.naming.NamespaceName; -import org.apache.pulsar.common.policies.data.PolicyName; -import org.apache.pulsar.common.policies.data.PolicyOperation; import org.junit.Test; import static com.clevercloud.biscuitpulsar.formatter.BiscuitFormatter.*; @@ -11,22 +8,16 @@ public class BiscuitFormatterTest { @Test public void testNamespaceOperations() { - assertEquals("[#create_topic,#get_topic,#get_topics,#delete_topic,#clear_backlog,#unsubscribe]", namespaceOperations); + assertEquals("[\"create_topic\",\"get_topic\",\"get_topics\",\"delete_topic\",\"clear_backlog\",\"unsubscribe\"]", namespaceOperations); } @Test public void testPoliciesOperations() { - assertEquals("[#all_read,#anti_affinity_read,#auto_subscription_creation_read,#auto_subscription_creation_write,#auto_topic_creation_read,#auto_topic_creation_write,#backlog_read,#backlog_write,#compaction_read,#compaction_write,#deduplication_read,#deduplication_snapshot_read,#deduplication_snapshot_write,#deduplication_write,#delayed_delivery_read,#delayed_delivery_write,#encryption_read,#encryption_write,#inactive_topic_read,#inactive_topic_write,#max_consumers_read,#max_consumers_write,#max_producers_read,#max_producers_write,#max_subscriptions_read,#max_subscriptions_write,#max_topics_read,#max_topics_write,#max_unacked_read,#max_unacked_write,#offload_read,#partition_read,#partition_write,#persistence_read,#persistence_write,#rate_read,#rate_write,#replication_rate_read,#replication_read,#resourcegroup_read,#resourcegroup_write,#retention_read,#retention_write,#schema_compatibility_strategy_read,#schema_compatibility_strategy_write,#subscription_auth_mode_read,#subscription_auth_mode_write,#subscription_expiration_time_read,#subscription_expiration_time_write,#ttl_read,#ttl_write]", policiesOperations); + assertEquals("[\"all_read\",\"anti_affinity_read\",\"auto_subscription_creation_read\",\"auto_subscription_creation_write\",\"auto_topic_creation_read\",\"auto_topic_creation_write\",\"backlog_read\",\"backlog_write\",\"compaction_read\",\"compaction_write\",\"deduplication_read\",\"deduplication_snapshot_read\",\"deduplication_snapshot_write\",\"deduplication_write\",\"delayed_delivery_read\",\"delayed_delivery_write\",\"encryption_read\",\"encryption_write\",\"inactive_topic_read\",\"inactive_topic_write\",\"max_consumers_read\",\"max_consumers_write\",\"max_producers_read\",\"max_producers_write\",\"max_subscriptions_read\",\"max_subscriptions_write\",\"max_topics_read\",\"max_topics_write\",\"max_unacked_read\",\"max_unacked_write\",\"offload_read\",\"partition_read\",\"partition_write\",\"persistence_read\",\"persistence_write\",\"rate_read\",\"rate_write\",\"replication_rate_read\",\"replication_read\",\"resourcegroup_read\",\"resourcegroup_write\",\"retention_read\",\"retention_write\",\"schema_compatibility_strategy_read\",\"schema_compatibility_strategy_write\",\"subscription_auth_mode_read\",\"subscription_auth_mode_write\",\"subscription_expiration_time_read\",\"subscription_expiration_time_write\",\"ttl_read\",\"ttl_write\"]", policiesOperations); } @Test public void testTopicOperations() { - assertEquals("[#lookup,#produce,#consume,#compact,#expire_messages,#offload,#peek_messages,#reset_cursor,#skip,#terminate,#subscribe,#get_subscriptions,#unsubscribe,#get_stats,#get_metadata,#get_backlog_size,#set_replicated_subscription_status]", topicOperations); - } - - @Test - public void testNamespaceOperationFact() { - String nsFact = namespacePolicyOperationFact(NamespaceName.get("tenant/namespace"), PolicyName.COMPACTION, PolicyOperation.WRITE); - assertEquals("namespace_operation(#ambient,\"tenant\",\"namespace\",#compaction_write)", nsFact); + assertEquals("[\"lookup\",\"produce\",\"consume\",\"compact\",\"expire_messages\",\"offload\",\"peek_messages\",\"reset_cursor\",\"skip\",\"terminate\",\"subscribe\",\"get_subscriptions\",\"unsubscribe\",\"get_stats\",\"get_metadata\",\"get_backlog_size\",\"set_replicated_subscription_status\"]", topicOperations); } } \ No newline at end of file diff --git a/src/test/java/resources/log4j2.xml b/src/test/java/resources/log4j2.xml deleted file mode 100644 index fc7e008..0000000 --- a/src/test/java/resources/log4j2.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Configuration status="debug"> - <Appenders> - <Console name="Console" target="SYSTEM_OUT"> - <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> - </Console> - </Appenders> - <Loggers> - <Root level="debug"> - <AppenderRef ref="Console"/> - </Root> - </Loggers> -</Configuration> diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml new file mode 100644 index 0000000..70e29b8 --- /dev/null +++ b/src/test/resources/logback-test.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration> + + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + + <root level="debug"> + <appender-ref ref="STDOUT"/> + </root> + +</configuration> \ No newline at end of file From f1a93fad6da057f28977d9fccb9788fccded5f32 Mon Sep 17 00:00:00 2001 From: "Alexandre DUVAL - @kannarfr" <kannarfr@gmail.com> Date: Thu, 3 Mar 2022 15:42:01 +0100 Subject: [PATCH 4/8] drop useless package --- pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pom.xml b/pom.xml index 4545a61..b1c54d8 100644 --- a/pom.xml +++ b/pom.xml @@ -173,11 +173,6 @@ <artifactId>vavr</artifactId> <version>${vavr.version}</version> </dependency> - <dependency> - <groupId>org.apache.pulsar</groupId> - <artifactId>pulsar-client</artifactId> - <version>${pulsar.version}</version> - </dependency> <dependency> <groupId>org.apache.pulsar</groupId> <artifactId>pulsar-broker</artifactId> From 56abf7f368d8ee7ab595741c6b864d22c559f3d5 Mon Sep 17 00:00:00 2001 From: "Alexandre DUVAL - @kannarfr" <kannarfr@gmail.com> Date: Thu, 3 Mar 2022 15:42:09 +0100 Subject: [PATCH 5/8] exclude functions as it's not used and embed log4j conf which overrides our logback conf --- pom.xml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index b1c54d8..3e0c0a2 100644 --- a/pom.xml +++ b/pom.xml @@ -177,15 +177,10 @@ <groupId>org.apache.pulsar</groupId> <artifactId>pulsar-broker</artifactId> <version>${pulsar.version}</version> - </dependency> - <dependency> - <groupId>org.apache.pulsar</groupId> - <artifactId>pulsar-common</artifactId> - <version>${pulsar.version}</version> <exclusions> <exclusion> - <groupId>io.grpc</groupId> - <artifactId>grpc-all</artifactId> + <groupId>org.apache.pulsar</groupId> + <artifactId>pulsar-functions-runtime</artifactId> </exclusion> </exclusions> </dependency> From adef978a5f7ac6ee266bfd1e86a655a55f6c71c3 Mon Sep 17 00:00:00 2001 From: "Alexandre DUVAL - @kannarfr" <kannarfr@gmail.com> Date: Fri, 4 Mar 2022 15:44:05 +0100 Subject: [PATCH 6/8] clean unused --- .../clevercloud/biscuitpulsar/AuthenticationBiscuit.java | 7 +++---- .../biscuitpulsar/AuthenticationProviderBiscuit.java | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/clevercloud/biscuitpulsar/AuthenticationBiscuit.java b/src/main/java/com/clevercloud/biscuitpulsar/AuthenticationBiscuit.java index 37fb756..ae13a3a 100644 --- a/src/main/java/com/clevercloud/biscuitpulsar/AuthenticationBiscuit.java +++ b/src/main/java/com/clevercloud/biscuitpulsar/AuthenticationBiscuit.java @@ -4,7 +4,6 @@ import org.apache.pulsar.client.api.Authentication; import org.apache.pulsar.client.api.AuthenticationDataProvider; import org.apache.pulsar.client.api.EncodedAuthenticationParameterSupport; -import org.apache.pulsar.client.api.PulsarClientException; import java.io.IOException; import java.net.URI; @@ -31,7 +30,7 @@ public AuthenticationBiscuit(Supplier<String> biscuitSupplier) { } @Override - public void close() throws IOException { + public void close() { // noop } @@ -41,7 +40,7 @@ public String getAuthMethodName() { } @Override - public AuthenticationDataProvider getAuthData() throws PulsarClientException { + public AuthenticationDataProvider getAuthData() { return new AuthenticationDataBiscuit(biscuitSupplier); } @@ -72,7 +71,7 @@ public void configure(Map<String, String> authParams) { } @Override - public void start() throws PulsarClientException { + public void start() { // noop } } diff --git a/src/main/java/com/clevercloud/biscuitpulsar/AuthenticationProviderBiscuit.java b/src/main/java/com/clevercloud/biscuitpulsar/AuthenticationProviderBiscuit.java index fcae746..2c0a4f7 100644 --- a/src/main/java/com/clevercloud/biscuitpulsar/AuthenticationProviderBiscuit.java +++ b/src/main/java/com/clevercloud/biscuitpulsar/AuthenticationProviderBiscuit.java @@ -17,7 +17,6 @@ import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SignatureException; -import java.util.Base64; public class AuthenticationProviderBiscuit implements AuthenticationProvider { private static final Logger log = LoggerFactory.getLogger(AuthenticationProviderBiscuit.class); From 56ce2f0b570d1bff3cce3b57c8897e07c2cbdbdc Mon Sep 17 00:00:00 2001 From: "Alexandre DUVAL - @kannarfr" <kannarfr@gmail.com> Date: Fri, 4 Mar 2022 15:44:16 +0100 Subject: [PATCH 7/8] biscuit-java 2.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3e0c0a2..0886675 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ <nexus-staging-maven.version>1.6.7</nexus-staging-maven.version> <!-- dependencies --> - <biscuit-java.version>2.0.0-SNAPSHOT</biscuit-java.version> + <biscuit-java.version>2.0.0</biscuit-java.version> <logback-classic.version>1.2.10</logback-classic.version> <protobuf.version>3.16.1</protobuf.version> <pulsar.version>2.9.1</pulsar.version> From a98522d4c2f30b5501543763509573c81ced2413 Mon Sep 17 00:00:00 2001 From: "Alexandre DUVAL - @kannarfr" <kannarfr@gmail.com> Date: Fri, 4 Mar 2022 15:49:30 +0100 Subject: [PATCH 8/8] bump readme --- README.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/README.md b/README.md index 3ef2ed7..4513f83 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,6 @@ This only supports Apache Pulsar v2.9+. The listed dependencies can be necessary to add to the /lib of pulsar folder as jars: -- curve25519-elisabeth - vavr - protobuf - biscuit-java @@ -28,7 +27,6 @@ We currently are using this script to put libs on pulsar nodes: ```bash #!/bin/bash -wget -P "pulsar/lib" "https://repo1.maven.org/maven2/cafe/cryptography/curve25519-elisabeth/0.1.0/curve25519-elisabeth-0.1.0.jar" wget -P "pulsar/lib" "https://repo1.maven.org/maven2/io/vavr/vavr/0.10.3/vavr-0.10.3.jar" wget -P "pulsar/lib" "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.16.1/protobuf-java-3.16.1.jar" wget -P "pulsar/lib" "https://repo1.maven.org/maven2/com/clever-cloud/biscuit-java/<VERSION>/biscuit-java-<VERSION>.jar" @@ -54,7 +52,6 @@ authorizationProvider=com.clevercloud.biscuitpulsar.AuthorizationProviderBiscuit ### --- Biscuit Authentication Provider --- ### biscuitPublicRootKey=@@BISCUIT_PUBLIC_ROOT_KEY@@ -biscuitSealingKey=@@BISCUIT_PUBLIC_SEALING_KEY@@ # support JWT side by side with Biscuit for AuthenticationToken biscuitSupportJWT=true|false # biscuit verify run limits before TimeOut @@ -69,10 +66,6 @@ biscuitRunLimitsMaxTimeMillis=30 sed -i -e "s/@@BISCUIT_PUBLIC_ROOT_KEY@@/$1/" broker.conf sed -i -e "s/@@BISCUIT_PUBLIC_ROOT_KEY@@/$1/" proxy.conf sed -i -e "s/@@BISCUIT_PUBLIC_ROOT_KEY@@/$1/" standalone.conf - -sed -i -e "s/@@BISCUIT_PUBLIC_SEALING_KEY@@/$2/" broker.conf -sed -i -e "s/@@BISCUIT_PUBLIC_SEALING_KEY@@/$2/" proxy.conf -sed -i -e "s/@@BISCUIT_PUBLIC_SEALING_KEY@@/$2/" standalone.conf ``` ## Usage