From 05eba8cb421bb948f5f72b8adec7cd34429391f4 Mon Sep 17 00:00:00 2001 From: efiacor Date: Thu, 22 Jul 2021 12:02:49 +0100 Subject: [DMAAP-KAFKA] Revert module name change Signed-off-by: efiacor Change-Id: I5fe1f4175085bf0dee0f571790c9f6d982f5fa83 Issue-ID: DMAAP-209 --- pom.xml | 2 + .../kafkaAuthorize/KafkaCustomAuthorizer.java | 233 +++++++++++++++++++++ .../dmaap/kafkaAuthorize/PlainLoginModule1.java | 68 ++++++ .../dmaap/kafkaAuthorize/PlainSaslServer1.java | 203 ++++++++++++++++++ .../kafkaAuthorize/PlainSaslServerProvider1.java | 42 ++++ .../kafkaauthorize/KafkaCustomAuthorizer.java | 233 --------------------- .../dmaap/kafkaauthorize/PlainLoginModule1.java | 68 ------ .../dmaap/kafkaauthorize/PlainSaslServer1.java | 203 ------------------ .../kafkaauthorize/PlainSaslServerProvider1.java | 42 ---- .../kafkaAuthorize/KafkaCustomAuthorizerTest.java | 216 +++++++++++++++++++ .../kafkaAuthorize/PlainLoginModule1Test.java | 80 +++++++ .../dmaap/kafkaAuthorize/PlainSaslServer1Test.java | 184 ++++++++++++++++ .../kafkaauthorize/KafkaCustomAuthorizerTest.java | 216 ------------------- .../kafkaauthorize/PlainLoginModule1Test.java | 80 ------- .../dmaap/kafkaauthorize/PlainSaslServer1Test.java | 184 ---------------- 15 files changed, 1028 insertions(+), 1026 deletions(-) create mode 100644 src/main/java/org/onap/dmaap/kafkaAuthorize/KafkaCustomAuthorizer.java create mode 100644 src/main/java/org/onap/dmaap/kafkaAuthorize/PlainLoginModule1.java create mode 100644 src/main/java/org/onap/dmaap/kafkaAuthorize/PlainSaslServer1.java create mode 100644 src/main/java/org/onap/dmaap/kafkaAuthorize/PlainSaslServerProvider1.java delete mode 100644 src/main/java/org/onap/dmaap/kafkaauthorize/KafkaCustomAuthorizer.java delete mode 100644 src/main/java/org/onap/dmaap/kafkaauthorize/PlainLoginModule1.java delete mode 100644 src/main/java/org/onap/dmaap/kafkaauthorize/PlainSaslServer1.java delete mode 100644 src/main/java/org/onap/dmaap/kafkaauthorize/PlainSaslServerProvider1.java create mode 100644 src/test/java/org/onap/dmaap/kafkaAuthorize/KafkaCustomAuthorizerTest.java create mode 100644 src/test/java/org/onap/dmaap/kafkaAuthorize/PlainLoginModule1Test.java create mode 100644 src/test/java/org/onap/dmaap/kafkaAuthorize/PlainSaslServer1Test.java delete mode 100644 src/test/java/org/onap/dmaap/kafkaauthorize/KafkaCustomAuthorizerTest.java delete mode 100644 src/test/java/org/onap/dmaap/kafkaauthorize/PlainLoginModule1Test.java delete mode 100644 src/test/java/org/onap/dmaap/kafkaauthorize/PlainSaslServer1Test.java diff --git a/pom.xml b/pom.xml index be2e4ae..2a7c5db 100644 --- a/pom.xml +++ b/pom.xml @@ -33,6 +33,7 @@ true true + true https://nexus.onap.org nexus3.onap.org:10003 https://nexus.onap.org @@ -294,6 +295,7 @@ onap/dmaap/kafka111 + true try ${basedir}/target/docker-stage Dockerfile diff --git a/src/main/java/org/onap/dmaap/kafkaAuthorize/KafkaCustomAuthorizer.java b/src/main/java/org/onap/dmaap/kafkaAuthorize/KafkaCustomAuthorizer.java new file mode 100644 index 0000000..4ad10e8 --- /dev/null +++ b/src/main/java/org/onap/dmaap/kafkaAuthorize/KafkaCustomAuthorizer.java @@ -0,0 +1,233 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Modification copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 +* + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * + *******************************************************************************/ +package org.onap.dmaap.kafkaAuthorize; + +import java.util.EnumSet; +import java.util.Map; + +import org.apache.kafka.common.acl.AclOperation; +import org.apache.kafka.common.security.auth.KafkaPrincipal; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.onap.dmaap.commonauth.kafka.base.authorization.AuthorizationProviderFactory; +import org.onap.dmaap.commonauth.kafka.base.authorization.Cadi3AAFProvider; + +import kafka.network.RequestChannel.Session; +import kafka.security.auth.Acl; +import kafka.security.auth.Authorizer; +import kafka.security.auth.Operation; +import kafka.security.auth.Resource; +import scala.collection.immutable.Set; + +/** + * A trivial Kafka Authorizer for use with SSL and AAF + * Authentication/Authorization. + * + */ +public class KafkaCustomAuthorizer implements Authorizer { + + private final String[] adminPermission = new String[3]; + protected static final EnumSet TOPIC_DESCRIBE_OPERATIONS = EnumSet.of(AclOperation.DESCRIBE_CONFIGS); + protected static final EnumSet TOPIC_READ_WRITE_DESCRIBE_OPERATIONS = EnumSet.of(AclOperation.WRITE, + AclOperation.READ, AclOperation.DESCRIBE_CONFIGS); + protected static final EnumSet TOPIC_ADMIN_OPERATIONS = EnumSet.of(AclOperation.ALTER, + AclOperation.ALTER_CONFIGS, AclOperation.CREATE); + static final String TOPIC = "Topic"; + + private static final Logger logger = LoggerFactory.getLogger(KafkaCustomAuthorizer.class); + + @Override + public void configure(final Map arg0) { + // TODO Auto-generate method stub + } + + @Override + public void addAcls(final Set arg0, final Resource arg1) { + // TODO Auto-generated method stub + + } + + private String[] getTopicPermission(String topicName, AclOperation aclOperation) { + + String namspace = topicName.substring(0, topicName.lastIndexOf(".")); + String[] permission = new String[3]; + if (TOPIC_READ_WRITE_DESCRIBE_OPERATIONS.contains(aclOperation)) { + permission[0] = namspace + ".topic"; + String instancePart = (System.getenv("pubSubInstPart") != null) ? System.getenv("pubSubInstPart") + : ".topic"; + permission[1] = instancePart + topicName; + + if (aclOperation.equals(AclOperation.WRITE)) { + permission[2] = "pub"; + } else if (aclOperation.equals(AclOperation.READ)) { + permission[2] = "sub"; + + } else if (TOPIC_DESCRIBE_OPERATIONS.contains(aclOperation)) { + permission[2] = "view"; + + } + } else if (aclOperation.equals(AclOperation.DELETE)) { + permission = (System.getProperty("msgRtr.topicfactory.aaf") + namspace + "|destroy").split("\\|"); + + } else if (TOPIC_ADMIN_OPERATIONS.contains(aclOperation)) { + permission = (System.getProperty("msgRtr.topicfactory.aaf") + namspace + "|create").split("\\|"); + } + + return permission; + } + + private String[] getAdminPermission() { + + if (adminPermission[0] == null) { + adminPermission[0] = System.getProperty("namespace") + ".kafka.access"; + adminPermission[1] = "*"; + adminPermission[2] = "*"; + } + + return adminPermission; + } + + private String[] getPermission(AclOperation aclOperation, String resource, String topicName) { + String[] permission = new String[3]; + switch (aclOperation) { + + case ALTER: + case ALTER_CONFIGS: + case CREATE: + case DELETE: + if (resource.equals(TOPIC)) { + permission = getTopicPermission(topicName, aclOperation); + } else if (resource.equals("Cluster")) { + permission = getAdminPermission(); + } + break; + case DESCRIBE_CONFIGS: + case READ: + case WRITE: + if (resource.equals(TOPIC)) { + permission = getTopicPermission(topicName, aclOperation); + } + break; + case IDEMPOTENT_WRITE: + if (resource.equals("Cluster")) { + permission = getAdminPermission(); + } + break; + default: + break; + + } + return permission; + + } + + @Override + public boolean authorize(final Session arg0, final Operation arg1, final Resource arg2) { + if (arg0.principal() == null) { + return false; + } + + String fullName = arg0.principal().getName(); + fullName = fullName != null ? fullName.trim() : fullName; + String topicName = null; + String[] permission; + + String resource = arg2.resourceType().name(); + + if (resource.equals(TOPIC)) { + topicName = arg2.name(); + } + + if (fullName != null && fullName.equals(Cadi3AAFProvider.getKafkaUsername())) { + return true; + } + + if ((!Cadi3AAFProvider.isCadiEnabled())||(null != topicName && !topicName.startsWith("org.onap"))) { + return true; + } + + permission = getPermission(arg1.toJava(), resource, topicName); + + if (permission[0] != null) { + return !checkPermissions(fullName, topicName, permission); + } + return true; + } + + private boolean checkPermissions(String fullName, String topicName, String[] permission) { + try { + + if (null != topicName) { + boolean hasResp = AuthorizationProviderFactory.getProviderFactory().getProvider() + .hasPermission(fullName, permission[0], permission[1], permission[2]); + if (hasResp) { + logger.info("Successful Authorization for {} on {} for {} | {} | {}", fullName, topicName, + permission[0], permission[1], permission[2]); + } + if (!hasResp) { + logger.info("{} is not allowed in {} | {} | {}", fullName, permission[0], permission[1], + permission[2]); + return true; + } + } + } catch (final Exception e) { + return true; + } + return false; + } + + @Override + public void close() { + // TODO Auto-generated method stub + + } + + @Override + public scala.collection.immutable.Map> getAcls() { + // TODO Auto-generated method stub + return null; + } + + @Override + public scala.collection.immutable.Map> getAcls(final KafkaPrincipal arg0) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean removeAcls(final Resource arg0) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean removeAcls(final Set arg0, final Resource arg1) { + // TODO Auto-generated method stub + return false; + } + + public Set getAcls(Resource arg0) { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/main/java/org/onap/dmaap/kafkaAuthorize/PlainLoginModule1.java b/src/main/java/org/onap/dmaap/kafkaAuthorize/PlainLoginModule1.java new file mode 100644 index 0000000..af5aa8f --- /dev/null +++ b/src/main/java/org/onap/dmaap/kafkaAuthorize/PlainLoginModule1.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Modification copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 +* + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * + *******************************************************************************/ +package org.onap.dmaap.kafkaAuthorize; + +import java.util.Map; +import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.spi.LoginModule; + +public class PlainLoginModule1 implements LoginModule { + + private static final String USERNAME_CONFIG = "username"; + private static final String PASSWORD_CONFIG = "password"; + + static { + PlainSaslServerProvider1.initialize(); + } + + @Override + public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { + String username = (String) options.get(USERNAME_CONFIG); + if (username != null) + subject.getPublicCredentials().add(username); + String password = (String) options.get(PASSWORD_CONFIG); + if (password != null) + subject.getPrivateCredentials().add(password); + + } + + @Override + public boolean login() { + return true; + } + + @Override + public boolean logout() { + return true; + } + + @Override + public boolean commit() { + return true; + } + + @Override + public boolean abort() { + return false; + } +} diff --git a/src/main/java/org/onap/dmaap/kafkaAuthorize/PlainSaslServer1.java b/src/main/java/org/onap/dmaap/kafkaAuthorize/PlainSaslServer1.java new file mode 100644 index 0000000..7a9bede --- /dev/null +++ b/src/main/java/org/onap/dmaap/kafkaAuthorize/PlainSaslServer1.java @@ -0,0 +1,203 @@ +/****************************************************************************** + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Modification copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 +* + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * + *******************************************************************************/ +package org.onap.dmaap.kafkaAuthorize; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import javax.security.auth.callback.CallbackHandler; +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; +import javax.security.sasl.SaslServerFactory; +import org.apache.kafka.common.errors.SaslAuthenticationException; +import org.onap.dmaap.commonauth.kafka.base.authorization.AuthorizationProviderFactory; + +/** + * Simple SaslServer implementation for SASL/PLAIN. In order to make this + * implementation fully pluggable, authentication of username/password is fully + * contained within the server implementation. + *

+ * Valid users with passwords are specified in the Jaas configuration file. Each + * user is specified with user_ as key and as value. This + * is consistent with Zookeeper Digest-MD5 implementation. + *

+ * To avoid storing clear passwords on disk or to integrate with external + * authentication servers in production systems, this module can be replaced + * with a different implementation. + * + */ +public class PlainSaslServer1 implements SaslServer { + + public static final String PLAIN_MECHANISM = "PLAIN"; + + private boolean complete; + private String authorizationId; + private static final String AUTH_EXC_NOT_COMPLETE = "Authentication exchange has not completed"; + + + /** + * @throws SaslAuthenticationException if username/password combination is invalid or if the requested + * authorization id is not the same as username. + *

+ * Note: This method may throw {@link SaslAuthenticationException} to provide custom error messages + * to clients. But care should be taken to avoid including any information in the exception message that + * should not be leaked to unauthenticated clients. It may be safer to throw {@link SaslException} in + * some cases so that a standard error message is returned to clients. + *

+ */ + @Override + public byte[] evaluateResponse(byte[] responseBytes) throws SaslAuthenticationException { + /* + * Message format (from https://tools.ietf.org/html/rfc4616): + * + * message = [authzid] UTF8NUL authcid UTF8NUL passwd + * authcid = 1*SAFE ; MUST accept up to 255 octets + * authzid = 1*SAFE ; MUST accept up to 255 octets + * passwd = 1*SAFE ; MUST accept up to 255 octets + * UTF8NUL = %x00 ; UTF-8 encoded NUL character + * + * SAFE = UTF1 / UTF2 / UTF3 / UTF4 + * ;; any UTF-8 encoded Unicode character except NUL + */ + String response = new String(responseBytes, StandardCharsets.UTF_8); + List tokens = extractTokens(response); + String authorizationIdFromClient = tokens.get(0); + String username = tokens.get(1); + String password = tokens.get(2); + + if (username.isEmpty()) { + throw new SaslAuthenticationException("Authentication failed: username not specified"); + } + if (password.isEmpty()) { + throw new SaslAuthenticationException("Authentication failed: password not specified"); + } + + String aafResponse = "Not Verified"; + try { + aafResponse = AuthorizationProviderFactory.getProviderFactory().getProvider().authenticate(username, + password); + } catch (Exception ignored) { + throw new SaslAuthenticationException("Authentication failed: " + aafResponse + " User " + username); + } + if (null != aafResponse) { + throw new SaslAuthenticationException("Authentication failed: " + aafResponse + " User " + username); + } + + if (!authorizationIdFromClient.isEmpty() && !authorizationIdFromClient.equals(username)) + throw new SaslAuthenticationException("Authentication failed: Client requested an authorization id that is different from username"); + + this.authorizationId = username; + + complete = true; + return new byte[0]; + } + + private List extractTokens(String string) { + List tokens = new ArrayList<>(); + int startIndex = 0; + for (int i = 0; i < 4; ++i) { + int endIndex = string.indexOf("\u0000", startIndex); + if (endIndex == -1) { + tokens.add(string.substring(startIndex)); + break; + } + tokens.add(string.substring(startIndex, endIndex)); + startIndex = endIndex + 1; + } + + if (tokens.size() != 3) + throw new SaslAuthenticationException("Invalid SASL/PLAIN response: expected 3 tokens, got " + + tokens.size()); + + return tokens; + } + + @Override + public String getAuthorizationID() { + if (!complete) + throw new IllegalStateException(AUTH_EXC_NOT_COMPLETE); + return authorizationId; + } + + @Override + public String getMechanismName() { + return PLAIN_MECHANISM; + } + + @Override + public Object getNegotiatedProperty(String propName) { + if (!complete) + throw new IllegalStateException(AUTH_EXC_NOT_COMPLETE); + return null; + } + + @Override + public boolean isComplete() { + return complete; + } + + @Override + public byte[] unwrap(byte[] incoming, int offset, int len) { + if (!complete) + throw new IllegalStateException(AUTH_EXC_NOT_COMPLETE); + return Arrays.copyOfRange(incoming, offset, offset + len); + } + + @Override + public byte[] wrap(byte[] outgoing, int offset, int len) { + if (!complete) + throw new IllegalStateException(AUTH_EXC_NOT_COMPLETE); + return Arrays.copyOfRange(outgoing, offset, offset + len); + } + + @Override + public void dispose() { + // TODO Auto-generate method stub + } + + public static class PlainSaslServerFactory1 implements SaslServerFactory { + + @Override + public SaslServer createSaslServer(String mechanism, String protocol, String serverName, Map props, CallbackHandler cbh) + throws SaslException { + + if (!PLAIN_MECHANISM.equals(mechanism)) + throw new SaslException(String.format("Mechanism '%s' is not supported. Only PLAIN is supported.", mechanism)); + + return new PlainSaslServer1(); + } + + @Override + public String[] getMechanismNames(Map props) { + if (props == null) return new String[]{PLAIN_MECHANISM}; + String noPlainText = (String) props.get(Sasl.POLICY_NOPLAINTEXT); + if ("true".equals(noPlainText)) + return new String[]{}; + else + return new String[]{PLAIN_MECHANISM}; + } + } +} + diff --git a/src/main/java/org/onap/dmaap/kafkaAuthorize/PlainSaslServerProvider1.java b/src/main/java/org/onap/dmaap/kafkaAuthorize/PlainSaslServerProvider1.java new file mode 100644 index 0000000..37b408e --- /dev/null +++ b/src/main/java/org/onap/dmaap/kafkaAuthorize/PlainSaslServerProvider1.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Modification copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 +* + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * + *******************************************************************************/ +package org.onap.dmaap.kafkaAuthorize; + +import java.security.Provider; +import java.security.Security; + +import org.onap.dmaap.kafkaAuthorize.PlainSaslServer1.PlainSaslServerFactory1; + +public class PlainSaslServerProvider1 extends Provider { + + private static final long serialVersionUID = 1L; + + protected PlainSaslServerProvider1() { + super("Simple SASL/PLAIN Server Provider", 1.0, "Simple SASL/PLAIN Server Provider for Kafka"); + super.put("SaslServerFactory." + PlainSaslServer1.PLAIN_MECHANISM, PlainSaslServerFactory1.class.getName()); + } + + public static void initialize() { + Security.insertProviderAt(new PlainSaslServerProvider1(),1); + } +} + diff --git a/src/main/java/org/onap/dmaap/kafkaauthorize/KafkaCustomAuthorizer.java b/src/main/java/org/onap/dmaap/kafkaauthorize/KafkaCustomAuthorizer.java deleted file mode 100644 index 09f704a..0000000 --- a/src/main/java/org/onap/dmaap/kafkaauthorize/KafkaCustomAuthorizer.java +++ /dev/null @@ -1,233 +0,0 @@ -/******************************************************************************* - * ============LICENSE_START======================================================= - * org.onap.dmaap - * ================================================================================ - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Modification copyright (C) 2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 -* - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * - *******************************************************************************/ -package org.onap.dmaap.kafkaauthorize; - -import java.util.EnumSet; -import java.util.Map; - -import org.apache.kafka.common.acl.AclOperation; -import org.apache.kafka.common.security.auth.KafkaPrincipal; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.onap.dmaap.commonauth.kafka.base.authorization.AuthorizationProviderFactory; -import org.onap.dmaap.commonauth.kafka.base.authorization.Cadi3AAFProvider; - -import kafka.network.RequestChannel.Session; -import kafka.security.auth.Acl; -import kafka.security.auth.Authorizer; -import kafka.security.auth.Operation; -import kafka.security.auth.Resource; -import scala.collection.immutable.Set; - -/** - * A trivial Kafka Authorizer for use with SSL and AAF - * Authentication/Authorization. - * - */ -public class KafkaCustomAuthorizer implements Authorizer { - - private final String[] adminPermission = new String[3]; - protected static final EnumSet TOPIC_DESCRIBE_OPERATIONS = EnumSet.of(AclOperation.DESCRIBE_CONFIGS); - protected static final EnumSet TOPIC_READ_WRITE_DESCRIBE_OPERATIONS = EnumSet.of(AclOperation.WRITE, - AclOperation.READ, AclOperation.DESCRIBE_CONFIGS); - protected static final EnumSet TOPIC_ADMIN_OPERATIONS = EnumSet.of(AclOperation.ALTER, - AclOperation.ALTER_CONFIGS, AclOperation.CREATE); - static final String TOPIC = "Topic"; - - private static final Logger logger = LoggerFactory.getLogger(KafkaCustomAuthorizer.class); - - @Override - public void configure(final Map arg0) { - // TODO Auto-generate method stub - } - - @Override - public void addAcls(final Set arg0, final Resource arg1) { - // TODO Auto-generated method stub - - } - - private String[] getTopicPermission(String topicName, AclOperation aclOperation) { - - String namspace = topicName.substring(0, topicName.lastIndexOf(".")); - String[] permission = new String[3]; - if (TOPIC_READ_WRITE_DESCRIBE_OPERATIONS.contains(aclOperation)) { - permission[0] = namspace + ".topic"; - String instancePart = (System.getenv("pubSubInstPart") != null) ? System.getenv("pubSubInstPart") - : ".topic"; - permission[1] = instancePart + topicName; - - if (aclOperation.equals(AclOperation.WRITE)) { - permission[2] = "pub"; - } else if (aclOperation.equals(AclOperation.READ)) { - permission[2] = "sub"; - - } else if (TOPIC_DESCRIBE_OPERATIONS.contains(aclOperation)) { - permission[2] = "view"; - - } - } else if (aclOperation.equals(AclOperation.DELETE)) { - permission = (System.getProperty("msgRtr.topicfactory.aaf") + namspace + "|destroy").split("\\|"); - - } else if (TOPIC_ADMIN_OPERATIONS.contains(aclOperation)) { - permission = (System.getProperty("msgRtr.topicfactory.aaf") + namspace + "|create").split("\\|"); - } - - return permission; - } - - private String[] getAdminPermission() { - - if (adminPermission[0] == null) { - adminPermission[0] = System.getProperty("namespace") + ".kafka.access"; - adminPermission[1] = "*"; - adminPermission[2] = "*"; - } - - return adminPermission; - } - - private String[] getPermission(AclOperation aclOperation, String resource, String topicName) { - String[] permission = new String[3]; - switch (aclOperation) { - - case ALTER: - case ALTER_CONFIGS: - case CREATE: - case DELETE: - if (resource.equals(TOPIC)) { - permission = getTopicPermission(topicName, aclOperation); - } else if (resource.equals("Cluster")) { - permission = getAdminPermission(); - } - break; - case DESCRIBE_CONFIGS: - case READ: - case WRITE: - if (resource.equals(TOPIC)) { - permission = getTopicPermission(topicName, aclOperation); - } - break; - case IDEMPOTENT_WRITE: - if (resource.equals("Cluster")) { - permission = getAdminPermission(); - } - break; - default: - break; - - } - return permission; - - } - - @Override - public boolean authorize(final Session arg0, final Operation arg1, final Resource arg2) { - if (arg0.principal() == null) { - return false; - } - - String fullName = arg0.principal().getName(); - fullName = fullName != null ? fullName.trim() : fullName; - String topicName = null; - String[] permission; - - String resource = arg2.resourceType().name(); - - if (resource.equals(TOPIC)) { - topicName = arg2.name(); - } - - if (fullName != null && fullName.equals(Cadi3AAFProvider.getKafkaUsername())) { - return true; - } - - if ((!Cadi3AAFProvider.isCadiEnabled())||(null != topicName && !topicName.startsWith("org.onap"))) { - return true; - } - - permission = getPermission(arg1.toJava(), resource, topicName); - - if (permission[0] != null) { - return !checkPermissions(fullName, topicName, permission); - } - return true; - } - - private boolean checkPermissions(String fullName, String topicName, String[] permission) { - try { - - if (null != topicName) { - boolean hasResp = AuthorizationProviderFactory.getProviderFactory().getProvider() - .hasPermission(fullName, permission[0], permission[1], permission[2]); - if (hasResp) { - logger.info("Successful Authorization for {} on {} for {} | {} | {}", fullName, topicName, - permission[0], permission[1], permission[2]); - } - if (!hasResp) { - logger.info("{} is not allowed in {} | {} | {}", fullName, permission[0], permission[1], - permission[2]); - return true; - } - } - } catch (final Exception e) { - return true; - } - return false; - } - - @Override - public void close() { - // TODO Auto-generated method stub - - } - - @Override - public scala.collection.immutable.Map> getAcls() { - // TODO Auto-generated method stub - return null; - } - - @Override - public scala.collection.immutable.Map> getAcls(final KafkaPrincipal arg0) { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean removeAcls(final Resource arg0) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean removeAcls(final Set arg0, final Resource arg1) { - // TODO Auto-generated method stub - return false; - } - - public Set getAcls(Resource arg0) { - // TODO Auto-generated method stub - return null; - } -} diff --git a/src/main/java/org/onap/dmaap/kafkaauthorize/PlainLoginModule1.java b/src/main/java/org/onap/dmaap/kafkaauthorize/PlainLoginModule1.java deleted file mode 100644 index f230418..0000000 --- a/src/main/java/org/onap/dmaap/kafkaauthorize/PlainLoginModule1.java +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************* - * ============LICENSE_START======================================================= - * org.onap.dmaap - * ================================================================================ - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Modification copyright (C) 2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 -* - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * - *******************************************************************************/ -package org.onap.dmaap.kafkaauthorize; - -import java.util.Map; -import javax.security.auth.Subject; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.spi.LoginModule; - -public class PlainLoginModule1 implements LoginModule { - - private static final String USERNAME_CONFIG = "username"; - private static final String PASSWORD_CONFIG = "password"; - - static { - PlainSaslServerProvider1.initialize(); - } - - @Override - public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { - String username = (String) options.get(USERNAME_CONFIG); - if (username != null) - subject.getPublicCredentials().add(username); - String password = (String) options.get(PASSWORD_CONFIG); - if (password != null) - subject.getPrivateCredentials().add(password); - - } - - @Override - public boolean login() { - return true; - } - - @Override - public boolean logout() { - return true; - } - - @Override - public boolean commit() { - return true; - } - - @Override - public boolean abort() { - return false; - } -} diff --git a/src/main/java/org/onap/dmaap/kafkaauthorize/PlainSaslServer1.java b/src/main/java/org/onap/dmaap/kafkaauthorize/PlainSaslServer1.java deleted file mode 100644 index ae15bbc..0000000 --- a/src/main/java/org/onap/dmaap/kafkaauthorize/PlainSaslServer1.java +++ /dev/null @@ -1,203 +0,0 @@ -/****************************************************************************** - * ============LICENSE_START======================================================= - * org.onap.dmaap - * ================================================================================ - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Modification copyright (C) 2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 -* - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * - *******************************************************************************/ -package org.onap.dmaap.kafkaauthorize; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import javax.security.auth.callback.CallbackHandler; -import javax.security.sasl.Sasl; -import javax.security.sasl.SaslException; -import javax.security.sasl.SaslServer; -import javax.security.sasl.SaslServerFactory; -import org.apache.kafka.common.errors.SaslAuthenticationException; -import org.onap.dmaap.commonauth.kafka.base.authorization.AuthorizationProviderFactory; - -/** - * Simple SaslServer implementation for SASL/PLAIN. In order to make this - * implementation fully pluggable, authentication of username/password is fully - * contained within the server implementation. - *

- * Valid users with passwords are specified in the Jaas configuration file. Each - * user is specified with user_ as key and as value. This - * is consistent with Zookeeper Digest-MD5 implementation. - *

- * To avoid storing clear passwords on disk or to integrate with external - * authentication servers in production systems, this module can be replaced - * with a different implementation. - * - */ -public class PlainSaslServer1 implements SaslServer { - - public static final String PLAIN_MECHANISM = "PLAIN"; - - private boolean complete; - private String authorizationId; - private static final String AUTH_EXC_NOT_COMPLETE = "Authentication exchange has not completed"; - - - /** - * @throws SaslAuthenticationException if username/password combination is invalid or if the requested - * authorization id is not the same as username. - *

- * Note: This method may throw {@link SaslAuthenticationException} to provide custom error messages - * to clients. But care should be taken to avoid including any information in the exception message that - * should not be leaked to unauthenticated clients. It may be safer to throw {@link SaslException} in - * some cases so that a standard error message is returned to clients. - *

- */ - @Override - public byte[] evaluateResponse(byte[] responseBytes) throws SaslAuthenticationException { - /* - * Message format (from https://tools.ietf.org/html/rfc4616): - * - * message = [authzid] UTF8NUL authcid UTF8NUL passwd - * authcid = 1*SAFE ; MUST accept up to 255 octets - * authzid = 1*SAFE ; MUST accept up to 255 octets - * passwd = 1*SAFE ; MUST accept up to 255 octets - * UTF8NUL = %x00 ; UTF-8 encoded NUL character - * - * SAFE = UTF1 / UTF2 / UTF3 / UTF4 - * ;; any UTF-8 encoded Unicode character except NUL - */ - String response = new String(responseBytes, StandardCharsets.UTF_8); - List tokens = extractTokens(response); - String authorizationIdFromClient = tokens.get(0); - String username = tokens.get(1); - String password = tokens.get(2); - - if (username.isEmpty()) { - throw new SaslAuthenticationException("Authentication failed: username not specified"); - } - if (password.isEmpty()) { - throw new SaslAuthenticationException("Authentication failed: password not specified"); - } - - String aafResponse = "Not Verified"; - try { - aafResponse = AuthorizationProviderFactory.getProviderFactory().getProvider().authenticate(username, - password); - } catch (Exception ignored) { - throw new SaslAuthenticationException("Authentication failed: " + aafResponse + " User " + username); - } - if (null != aafResponse) { - throw new SaslAuthenticationException("Authentication failed: " + aafResponse + " User " + username); - } - - if (!authorizationIdFromClient.isEmpty() && !authorizationIdFromClient.equals(username)) - throw new SaslAuthenticationException("Authentication failed: Client requested an authorization id that is different from username"); - - this.authorizationId = username; - - complete = true; - return new byte[0]; - } - - private List extractTokens(String string) { - List tokens = new ArrayList<>(); - int startIndex = 0; - for (int i = 0; i < 4; ++i) { - int endIndex = string.indexOf("\u0000", startIndex); - if (endIndex == -1) { - tokens.add(string.substring(startIndex)); - break; - } - tokens.add(string.substring(startIndex, endIndex)); - startIndex = endIndex + 1; - } - - if (tokens.size() != 3) - throw new SaslAuthenticationException("Invalid SASL/PLAIN response: expected 3 tokens, got " + - tokens.size()); - - return tokens; - } - - @Override - public String getAuthorizationID() { - if (!complete) - throw new IllegalStateException(AUTH_EXC_NOT_COMPLETE); - return authorizationId; - } - - @Override - public String getMechanismName() { - return PLAIN_MECHANISM; - } - - @Override - public Object getNegotiatedProperty(String propName) { - if (!complete) - throw new IllegalStateException(AUTH_EXC_NOT_COMPLETE); - return null; - } - - @Override - public boolean isComplete() { - return complete; - } - - @Override - public byte[] unwrap(byte[] incoming, int offset, int len) { - if (!complete) - throw new IllegalStateException(AUTH_EXC_NOT_COMPLETE); - return Arrays.copyOfRange(incoming, offset, offset + len); - } - - @Override - public byte[] wrap(byte[] outgoing, int offset, int len) { - if (!complete) - throw new IllegalStateException(AUTH_EXC_NOT_COMPLETE); - return Arrays.copyOfRange(outgoing, offset, offset + len); - } - - @Override - public void dispose() { - // TODO Auto-generate method stub - } - - public static class PlainSaslServerFactory1 implements SaslServerFactory { - - @Override - public SaslServer createSaslServer(String mechanism, String protocol, String serverName, Map props, CallbackHandler cbh) - throws SaslException { - - if (!PLAIN_MECHANISM.equals(mechanism)) - throw new SaslException(String.format("Mechanism '%s' is not supported. Only PLAIN is supported.", mechanism)); - - return new PlainSaslServer1(); - } - - @Override - public String[] getMechanismNames(Map props) { - if (props == null) return new String[]{PLAIN_MECHANISM}; - String noPlainText = (String) props.get(Sasl.POLICY_NOPLAINTEXT); - if ("true".equals(noPlainText)) - return new String[]{}; - else - return new String[]{PLAIN_MECHANISM}; - } - } -} - diff --git a/src/main/java/org/onap/dmaap/kafkaauthorize/PlainSaslServerProvider1.java b/src/main/java/org/onap/dmaap/kafkaauthorize/PlainSaslServerProvider1.java deleted file mode 100644 index b9fbf7a..0000000 --- a/src/main/java/org/onap/dmaap/kafkaauthorize/PlainSaslServerProvider1.java +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * ============LICENSE_START======================================================= - * org.onap.dmaap - * ================================================================================ - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Modification copyright (C) 2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 -* - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * - *******************************************************************************/ -package org.onap.dmaap.kafkaauthorize; - -import java.security.Provider; -import java.security.Security; - -import org.onap.dmaap.kafkaauthorize.PlainSaslServer1.PlainSaslServerFactory1; - -public class PlainSaslServerProvider1 extends Provider { - - private static final long serialVersionUID = 1L; - - protected PlainSaslServerProvider1() { - super("Simple SASL/PLAIN Server Provider", 1.0, "Simple SASL/PLAIN Server Provider for Kafka"); - super.put("SaslServerFactory." + PlainSaslServer1.PLAIN_MECHANISM, PlainSaslServerFactory1.class.getName()); - } - - public static void initialize() { - Security.insertProviderAt(new PlainSaslServerProvider1(),1); - } -} - diff --git a/src/test/java/org/onap/dmaap/kafkaAuthorize/KafkaCustomAuthorizerTest.java b/src/test/java/org/onap/dmaap/kafkaAuthorize/KafkaCustomAuthorizerTest.java new file mode 100644 index 0000000..e2e85af --- /dev/null +++ b/src/test/java/org/onap/dmaap/kafkaAuthorize/KafkaCustomAuthorizerTest.java @@ -0,0 +1,216 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Modification copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 +* + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * + *******************************************************************************/ +package org.onap.dmaap.kafkaAuthorize; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.apache.kafka.common.acl.AclOperation; +import org.apache.kafka.common.security.auth.KafkaPrincipal; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.dmaap.commonauth.kafka.base.authorization.AuthorizationProvider; +import org.onap.dmaap.commonauth.kafka.base.authorization.AuthorizationProviderFactory; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import kafka.network.RequestChannel.Session; +import kafka.security.auth.Operation; +import kafka.security.auth.Resource; +import kafka.security.auth.ResourceType; + +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({"javax.net.ssl.*", "javax.security.auth.*", "jdk.internal.reflect.*", "javax.crypto.*"}) +@PrepareForTest({ AuthorizationProviderFactory.class }) +public class KafkaCustomAuthorizerTest { + @Mock + Session arg0; + @Mock + Operation arg1; + @Mock + Resource arg2; + @Mock + KafkaPrincipal principal; + @Mock + ResourceType resourceType; + @Mock + AuthorizationProviderFactory factory; + @Mock + AuthorizationProvider provider; + + KafkaCustomAuthorizer authorizer; + + static { + System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); + System.setProperty("enableCadi", "true"); + } + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + PowerMockito.when(principal.getName()).thenReturn("fullName"); + PowerMockito.when(arg0.principal()).thenReturn(principal); + PowerMockito.when(arg1.name()).thenReturn("Write"); + PowerMockito.when(resourceType.name()).thenReturn("Topic"); + PowerMockito.when(arg2.resourceType()).thenReturn(resourceType); + PowerMockito.when(arg2.name()).thenReturn("namespace.Topic"); + PowerMockito.mockStatic(AuthorizationProviderFactory.class); + PowerMockito.when(AuthorizationProviderFactory.getProviderFactory()).thenReturn(factory); + PowerMockito.when(factory.getProvider()).thenReturn(provider); + + } + + @Test + public void testAuthorizerSuccess() { + PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) + .thenReturn(true); + authorizer = new KafkaCustomAuthorizer(); + assertTrue(authorizer.authorize(arg0, arg1, arg2)); + } + + @Test + public void testAuthorizerFailure() { + System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); + PowerMockito.when(arg2.name()).thenReturn("org.onap.dmaap.mr.testtopic"); + PowerMockito.when(arg1.toJava()).thenReturn(AclOperation.CREATE); + System.setProperty("msgRtr.topicfactory.aaf", "org.onap.dmaap.mr.topicFactory|:org.onap.dmaap.mr.topic:"); + PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) + .thenReturn(false); + authorizer = new KafkaCustomAuthorizer(); + try { + authorizer.authorize(arg0, arg1, arg2); + } catch (Exception e) { + assertTrue(true); + } + + } + + @Test + public void testAuthorizerFailure1() { + System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); + PowerMockito.when(arg2.name()).thenReturn("org.onap.dmaap.mr.testtopic"); + PowerMockito.when(resourceType.name()).thenReturn("Cluster"); + PowerMockito.when(arg1.toJava()).thenReturn(AclOperation.CREATE); + System.setProperty("msgRtr.topicfactory.aaf", "org.onap.dmaap.mr.topicFactory|:org.onap.dmaap.mr.topic:"); + PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) + .thenReturn(false); + authorizer = new KafkaCustomAuthorizer(); + try { + authorizer.authorize(arg0, arg1, arg2); + } catch (Exception e) { + assertTrue(true); + } + + } + + @Test + public void testAuthorizerFailure2() { + System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); + PowerMockito.when(arg2.name()).thenReturn("org.onap.dmaap.mr.testtopic"); + PowerMockito.when(resourceType.name()).thenReturn("Topic"); + PowerMockito.when(arg1.toJava()).thenReturn(AclOperation.WRITE); + PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) + .thenReturn(false); + authorizer = new KafkaCustomAuthorizer(); + try { + authorizer.authorize(arg0, arg1, arg2); + } catch (Exception e) { + assertTrue(true); + } + + } + + @Test + public void testAuthorizerFailure3() { + System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); + PowerMockito.when(arg2.name()).thenReturn("org.onap.dmaap.mr.testtopic"); + PowerMockito.when(resourceType.name()).thenReturn("Topic"); + PowerMockito.when(arg1.toJava()).thenReturn(AclOperation.DESCRIBE); + PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) + .thenReturn(false); + authorizer = new KafkaCustomAuthorizer(); + try { + authorizer.authorize(arg0, arg1, arg2); + } catch (Exception e) { + assertTrue(true); + } + + } + @Test + public void testAuthorizerFailure4() { + System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); + PowerMockito.when(arg2.name()).thenReturn("org.onap.dmaap.mr.testtopic"); + PowerMockito.when(resourceType.name()).thenReturn("Topic"); + PowerMockito.when(arg1.toJava()).thenReturn(AclOperation.READ); + PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) + .thenReturn(false); + authorizer = new KafkaCustomAuthorizer(); + try { + authorizer.authorize(arg0, arg1, arg2); + } catch (Exception e) { + assertTrue(true); + } + + } + + @Test + public void testAuthorizerFailure5() { + System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); + PowerMockito.when(arg2.name()).thenReturn("org.onap.dmaap.mr.testtopic"); + PowerMockito.when(resourceType.name()).thenReturn("Cluster"); + PowerMockito.when(arg1.toJava()).thenReturn(AclOperation.IDEMPOTENT_WRITE); + System.setProperty("msgRtr.topicfactory.aaf", "org.onap.dmaap.mr.topicFactory|:org.onap.dmaap.mr.topic:"); + PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) + .thenReturn(false); + authorizer = new KafkaCustomAuthorizer(); + try { + authorizer.authorize(arg0, arg1, arg2); + } catch (Exception e) { + assertTrue(true); + } + + } + + @Test + public void testAuthorizerFailure6() { + System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); + PowerMockito.when(arg2.name()).thenReturn("org.onap.dmaap.mr.testtopic"); + PowerMockito.when(arg1.toJava()).thenReturn(AclOperation.DELETE); + System.setProperty("msgRtr.topicfactory.aaf", "org.onap.dmaap.mr.topicFactory|:org.onap.dmaap.mr.topic:"); + PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) + .thenReturn(false); + authorizer = new KafkaCustomAuthorizer(); + try { + authorizer.authorize(arg0, arg1, arg2); + } catch (Exception e) { + assertTrue(true); + } + + } + + +} diff --git a/src/test/java/org/onap/dmaap/kafkaAuthorize/PlainLoginModule1Test.java b/src/test/java/org/onap/dmaap/kafkaAuthorize/PlainLoginModule1Test.java new file mode 100644 index 0000000..9383539 --- /dev/null +++ b/src/test/java/org/onap/dmaap/kafkaAuthorize/PlainLoginModule1Test.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Modification copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 +* + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * + *******************************************************************************/ +package org.onap.dmaap.kafkaAuthorize; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Map; +import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; + +@PowerMockIgnore({"jdk.internal.reflect.*"}) +@PrepareForTest({ PlainLoginModule1.class }) +public class PlainLoginModule1Test { + + static PlainLoginModule1 pLogin = new PlainLoginModule1(); + static Subject subject; + @Mock + static CallbackHandler callbackHandler; + + @Mock + static Map mymap1; + + @Mock + static Map mymap2; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + PowerMockito.when(mymap1.get("username")).thenReturn("user1"); + PowerMockito.when(mymap1.get("password")).thenReturn("pass1"); + pLogin.initialize(subject, callbackHandler, mymap1, mymap2); + } + + @Test + public void testLogin() { + assertTrue(pLogin.login()); + } + + @Test + public void testLogout() { + assertTrue(pLogin.logout()); + } + + @Test + public void testCommit() { + assertTrue(pLogin.commit()); + } + + @Test + public void testAbort() { + assertFalse(pLogin.abort()); + } +} diff --git a/src/test/java/org/onap/dmaap/kafkaAuthorize/PlainSaslServer1Test.java b/src/test/java/org/onap/dmaap/kafkaAuthorize/PlainSaslServer1Test.java new file mode 100644 index 0000000..5d18bbd --- /dev/null +++ b/src/test/java/org/onap/dmaap/kafkaAuthorize/PlainSaslServer1Test.java @@ -0,0 +1,184 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 +* + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * + *******************************************************************************/ +package org.onap.dmaap.kafkaAuthorize; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Map; +import javax.security.auth.callback.CallbackHandler; +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslException; +import org.apache.kafka.common.errors.SaslAuthenticationException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.onap.dmaap.commonauth.kafka.base.authorization.AuthorizationProvider; +import org.onap.dmaap.commonauth.kafka.base.authorization.AuthorizationProviderFactory; +import org.onap.dmaap.kafkaAuthorize.PlainSaslServer1.PlainSaslServerFactory1; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({"javax.security.auth.*", "jdk.internal.reflect.*", "javax.crypto.*"}) +@PrepareForTest({ AuthorizationProviderFactory.class }) +public class PlainSaslServer1Test { + + PlainSaslServer1 sslServer = new PlainSaslServer1(); + + @Mock + AuthorizationProviderFactory factory; + @Mock + AuthorizationProvider provider; + @Mock + CallbackHandler callbackHandler; + @Mock + static Map props; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + PowerMockito.mockStatic(AuthorizationProviderFactory.class); + PowerMockito.when(AuthorizationProviderFactory.getProviderFactory()).thenReturn(factory); + PowerMockito.when(factory.getProvider()).thenReturn(provider); + } + + public void testAuthentication() throws Exception { + String response = "authorizationID\u0000username\u0000password"; + PowerMockito.when(provider.authenticate("username", "password")).thenReturn(null); + assertNotNull(sslServer.evaluateResponse(response.getBytes())); + + } + + @Test + public void testAuthenticationEmptyAuth() throws Exception { + String response = "\u0000username\u0000password"; + PowerMockito.when(provider.authenticate("username", "password")).thenReturn(null); + assertNotNull(sslServer.evaluateResponse(response.getBytes())); + } + + @Test + public void testAuthenticationEmptyUser() throws Exception { + String response = "authorizationID\u0000\u0000password"; + PowerMockito.when(provider.authenticate("username", "password")).thenReturn(null); + try { + sslServer.evaluateResponse(response.getBytes()); + } + catch (SaslAuthenticationException e) { + assertNotNull(e); + } + } + + @Test + public void testAuthenticationEmptyPassword() throws Exception { + String response = "authorizationID\u0000username\u0000"; + PowerMockito.when(provider.authenticate("username", "password")).thenReturn(null); + try { + sslServer.evaluateResponse(response.getBytes()); + } + catch (SaslAuthenticationException e) { + assertNotNull(e); + } + } + + @Test + public void testGetAuthorizationIdWithException() { + try { + sslServer.getAuthorizationID(); + } + catch (IllegalStateException ise) { + assertTrue(ise.getMessage().equalsIgnoreCase("Authentication exchange has not completed")); + } + } + + @Test + public void testGetNegotiatedPropertyWithException() { + try { + sslServer.getNegotiatedProperty("test"); + } + catch (IllegalStateException ise) { + assertTrue(ise.getMessage().equalsIgnoreCase("Authentication exchange has not completed")); + } + } + + @Test + public void testIsComplete() { + try { + sslServer.getNegotiatedProperty("test"); + } + catch (IllegalStateException ise) { + assertTrue(ise.getMessage().equalsIgnoreCase("Authentication exchange has not completed")); + } + assert(true); + } + + @Test + public void testUnwrap() { + try { + sslServer.unwrap(new byte[1], 0, 0); + } + catch (IllegalStateException ise) { + assertTrue(ise.getMessage().equalsIgnoreCase("Authentication exchange has not completed")); + } catch (SaslAuthenticationException e) { + e.printStackTrace(); + } + assert(true); + } + + @Test + public void testWrap() { + try { + sslServer.wrap(new byte[1], 0, 0); + } + catch (IllegalStateException ise) { + assertTrue(ise.getMessage().equalsIgnoreCase("Authentication exchange has not completed")); + } catch (SaslAuthenticationException e) { + e.printStackTrace(); + } + assert(true); + } + + @Test + public void testGetMech() { + assertEquals("PLAIN", sslServer.getMechanismName()); + } + + @Test + public void testIsCompleteBool() { + assertFalse(sslServer.isComplete()); + } + + @Test + public void testPlainSaslServer1() throws SaslException { + PlainSaslServerFactory1 plainSaslServerFactory1 = new PlainSaslServerFactory1(); + PlainSaslServer1 saslServer1 = (PlainSaslServer1) plainSaslServerFactory1.createSaslServer(PlainSaslServer1.PLAIN_MECHANISM, "https", "mySaslServer", props, callbackHandler); + assertNotNull(saslServer1); + Mockito.when(props.get(Sasl.POLICY_NOPLAINTEXT)).thenReturn("javax.security.sasl.policy.noplaintext"); + assertEquals(new String[]{"PLAIN"}, plainSaslServerFactory1.getMechanismNames(props)); + } +} diff --git a/src/test/java/org/onap/dmaap/kafkaauthorize/KafkaCustomAuthorizerTest.java b/src/test/java/org/onap/dmaap/kafkaauthorize/KafkaCustomAuthorizerTest.java deleted file mode 100644 index 098d472..0000000 --- a/src/test/java/org/onap/dmaap/kafkaauthorize/KafkaCustomAuthorizerTest.java +++ /dev/null @@ -1,216 +0,0 @@ -/******************************************************************************* - * ============LICENSE_START======================================================= - * org.onap.dmaap - * ================================================================================ - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Modification copyright (C) 2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 -* - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * - *******************************************************************************/ -package org.onap.dmaap.kafkaauthorize; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import org.apache.kafka.common.acl.AclOperation; -import org.apache.kafka.common.security.auth.KafkaPrincipal; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.onap.dmaap.commonauth.kafka.base.authorization.AuthorizationProvider; -import org.onap.dmaap.commonauth.kafka.base.authorization.AuthorizationProviderFactory; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import kafka.network.RequestChannel.Session; -import kafka.security.auth.Operation; -import kafka.security.auth.Resource; -import kafka.security.auth.ResourceType; - -@RunWith(PowerMockRunner.class) -@PowerMockIgnore({"javax.net.ssl.*", "javax.security.auth.*", "jdk.internal.reflect.*", "javax.crypto.*"}) -@PrepareForTest({ AuthorizationProviderFactory.class }) -public class KafkaCustomAuthorizerTest { - @Mock - Session arg0; - @Mock - Operation arg1; - @Mock - Resource arg2; - @Mock - KafkaPrincipal principal; - @Mock - ResourceType resourceType; - @Mock - AuthorizationProviderFactory factory; - @Mock - AuthorizationProvider provider; - - KafkaCustomAuthorizer authorizer; - - static { - System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); - System.setProperty("enableCadi", "true"); - } - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - PowerMockito.when(principal.getName()).thenReturn("fullName"); - PowerMockito.when(arg0.principal()).thenReturn(principal); - PowerMockito.when(arg1.name()).thenReturn("Write"); - PowerMockito.when(resourceType.name()).thenReturn("Topic"); - PowerMockito.when(arg2.resourceType()).thenReturn(resourceType); - PowerMockito.when(arg2.name()).thenReturn("namespace.Topic"); - PowerMockito.mockStatic(AuthorizationProviderFactory.class); - PowerMockito.when(AuthorizationProviderFactory.getProviderFactory()).thenReturn(factory); - PowerMockito.when(factory.getProvider()).thenReturn(provider); - - } - - @Test - public void testAuthorizerSuccess() { - PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) - .thenReturn(true); - authorizer = new KafkaCustomAuthorizer(); - assertTrue(authorizer.authorize(arg0, arg1, arg2)); - } - - @Test - public void testAuthorizerFailure() { - System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); - PowerMockito.when(arg2.name()).thenReturn("org.onap.dmaap.mr.testtopic"); - PowerMockito.when(arg1.toJava()).thenReturn(AclOperation.CREATE); - System.setProperty("msgRtr.topicfactory.aaf", "org.onap.dmaap.mr.topicFactory|:org.onap.dmaap.mr.topic:"); - PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) - .thenReturn(false); - authorizer = new KafkaCustomAuthorizer(); - try { - authorizer.authorize(arg0, arg1, arg2); - } catch (Exception e) { - assertTrue(true); - } - - } - - @Test - public void testAuthorizerFailure1() { - System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); - PowerMockito.when(arg2.name()).thenReturn("org.onap.dmaap.mr.testtopic"); - PowerMockito.when(resourceType.name()).thenReturn("Cluster"); - PowerMockito.when(arg1.toJava()).thenReturn(AclOperation.CREATE); - System.setProperty("msgRtr.topicfactory.aaf", "org.onap.dmaap.mr.topicFactory|:org.onap.dmaap.mr.topic:"); - PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) - .thenReturn(false); - authorizer = new KafkaCustomAuthorizer(); - try { - authorizer.authorize(arg0, arg1, arg2); - } catch (Exception e) { - assertTrue(true); - } - - } - - @Test - public void testAuthorizerFailure2() { - System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); - PowerMockito.when(arg2.name()).thenReturn("org.onap.dmaap.mr.testtopic"); - PowerMockito.when(resourceType.name()).thenReturn("Topic"); - PowerMockito.when(arg1.toJava()).thenReturn(AclOperation.WRITE); - PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) - .thenReturn(false); - authorizer = new KafkaCustomAuthorizer(); - try { - authorizer.authorize(arg0, arg1, arg2); - } catch (Exception e) { - assertTrue(true); - } - - } - - @Test - public void testAuthorizerFailure3() { - System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); - PowerMockito.when(arg2.name()).thenReturn("org.onap.dmaap.mr.testtopic"); - PowerMockito.when(resourceType.name()).thenReturn("Topic"); - PowerMockito.when(arg1.toJava()).thenReturn(AclOperation.DESCRIBE); - PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) - .thenReturn(false); - authorizer = new KafkaCustomAuthorizer(); - try { - authorizer.authorize(arg0, arg1, arg2); - } catch (Exception e) { - assertTrue(true); - } - - } - @Test - public void testAuthorizerFailure4() { - System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); - PowerMockito.when(arg2.name()).thenReturn("org.onap.dmaap.mr.testtopic"); - PowerMockito.when(resourceType.name()).thenReturn("Topic"); - PowerMockito.when(arg1.toJava()).thenReturn(AclOperation.READ); - PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) - .thenReturn(false); - authorizer = new KafkaCustomAuthorizer(); - try { - authorizer.authorize(arg0, arg1, arg2); - } catch (Exception e) { - assertTrue(true); - } - - } - - @Test - public void testAuthorizerFailure5() { - System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); - PowerMockito.when(arg2.name()).thenReturn("org.onap.dmaap.mr.testtopic"); - PowerMockito.when(resourceType.name()).thenReturn("Cluster"); - PowerMockito.when(arg1.toJava()).thenReturn(AclOperation.IDEMPOTENT_WRITE); - System.setProperty("msgRtr.topicfactory.aaf", "org.onap.dmaap.mr.topicFactory|:org.onap.dmaap.mr.topic:"); - PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) - .thenReturn(false); - authorizer = new KafkaCustomAuthorizer(); - try { - authorizer.authorize(arg0, arg1, arg2); - } catch (Exception e) { - assertTrue(true); - } - - } - - @Test - public void testAuthorizerFailure6() { - System.setProperty("CADI_PROPERTIES", "src/test/resources/cadi.properties"); - PowerMockito.when(arg2.name()).thenReturn("org.onap.dmaap.mr.testtopic"); - PowerMockito.when(arg1.toJava()).thenReturn(AclOperation.DELETE); - System.setProperty("msgRtr.topicfactory.aaf", "org.onap.dmaap.mr.topicFactory|:org.onap.dmaap.mr.topic:"); - PowerMockito.when(provider.hasPermission("fullName", "namespace.topic", ":topic.namespace.Topic", "pub")) - .thenReturn(false); - authorizer = new KafkaCustomAuthorizer(); - try { - authorizer.authorize(arg0, arg1, arg2); - } catch (Exception e) { - assertTrue(true); - } - - } - - -} diff --git a/src/test/java/org/onap/dmaap/kafkaauthorize/PlainLoginModule1Test.java b/src/test/java/org/onap/dmaap/kafkaauthorize/PlainLoginModule1Test.java deleted file mode 100644 index 33a0708..0000000 --- a/src/test/java/org/onap/dmaap/kafkaauthorize/PlainLoginModule1Test.java +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************* - * ============LICENSE_START======================================================= - * org.onap.dmaap - * ================================================================================ - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Modification copyright (C) 2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 -* - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * - *******************************************************************************/ -package org.onap.dmaap.kafkaauthorize; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.util.Map; -import javax.security.auth.Subject; -import javax.security.auth.callback.CallbackHandler; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; - -@PowerMockIgnore({"jdk.internal.reflect.*"}) -@PrepareForTest({ PlainLoginModule1.class }) -public class PlainLoginModule1Test { - - static PlainLoginModule1 pLogin = new PlainLoginModule1(); - static Subject subject; - @Mock - static CallbackHandler callbackHandler; - - @Mock - static Map mymap1; - - @Mock - static Map mymap2; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - PowerMockito.when(mymap1.get("username")).thenReturn("user1"); - PowerMockito.when(mymap1.get("password")).thenReturn("pass1"); - pLogin.initialize(subject, callbackHandler, mymap1, mymap2); - } - - @Test - public void testLogin() { - assertTrue(pLogin.login()); - } - - @Test - public void testLogout() { - assertTrue(pLogin.logout()); - } - - @Test - public void testCommit() { - assertTrue(pLogin.commit()); - } - - @Test - public void testAbort() { - assertFalse(pLogin.abort()); - } -} diff --git a/src/test/java/org/onap/dmaap/kafkaauthorize/PlainSaslServer1Test.java b/src/test/java/org/onap/dmaap/kafkaauthorize/PlainSaslServer1Test.java deleted file mode 100644 index 6128978..0000000 --- a/src/test/java/org/onap/dmaap/kafkaauthorize/PlainSaslServer1Test.java +++ /dev/null @@ -1,184 +0,0 @@ -/******************************************************************************* - * ============LICENSE_START======================================================= - * org.onap.dmaap - * ================================================================================ - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 -* - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * - *******************************************************************************/ -package org.onap.dmaap.kafkaauthorize; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.Map; -import javax.security.auth.callback.CallbackHandler; -import javax.security.sasl.Sasl; -import javax.security.sasl.SaslException; -import org.apache.kafka.common.errors.SaslAuthenticationException; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.onap.dmaap.commonauth.kafka.base.authorization.AuthorizationProvider; -import org.onap.dmaap.commonauth.kafka.base.authorization.AuthorizationProviderFactory; -import org.onap.dmaap.kafkaauthorize.PlainSaslServer1.PlainSaslServerFactory1; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -@RunWith(PowerMockRunner.class) -@PowerMockIgnore({"javax.security.auth.*", "jdk.internal.reflect.*", "javax.crypto.*"}) -@PrepareForTest({ AuthorizationProviderFactory.class }) -public class PlainSaslServer1Test { - - PlainSaslServer1 sslServer = new PlainSaslServer1(); - - @Mock - AuthorizationProviderFactory factory; - @Mock - AuthorizationProvider provider; - @Mock - CallbackHandler callbackHandler; - @Mock - static Map props; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - PowerMockito.mockStatic(AuthorizationProviderFactory.class); - PowerMockito.when(AuthorizationProviderFactory.getProviderFactory()).thenReturn(factory); - PowerMockito.when(factory.getProvider()).thenReturn(provider); - } - - public void testAuthentication() throws Exception { - String response = "authorizationID\u0000username\u0000password"; - PowerMockito.when(provider.authenticate("username", "password")).thenReturn(null); - assertNotNull(sslServer.evaluateResponse(response.getBytes())); - - } - - @Test - public void testAuthenticationEmptyAuth() throws Exception { - String response = "\u0000username\u0000password"; - PowerMockito.when(provider.authenticate("username", "password")).thenReturn(null); - assertNotNull(sslServer.evaluateResponse(response.getBytes())); - } - - @Test - public void testAuthenticationEmptyUser() throws Exception { - String response = "authorizationID\u0000\u0000password"; - PowerMockito.when(provider.authenticate("username", "password")).thenReturn(null); - try { - sslServer.evaluateResponse(response.getBytes()); - } - catch (SaslAuthenticationException e) { - assertNotNull(e); - } - } - - @Test - public void testAuthenticationEmptyPassword() throws Exception { - String response = "authorizationID\u0000username\u0000"; - PowerMockito.when(provider.authenticate("username", "password")).thenReturn(null); - try { - sslServer.evaluateResponse(response.getBytes()); - } - catch (SaslAuthenticationException e) { - assertNotNull(e); - } - } - - @Test - public void testGetAuthorizationIdWithException() { - try { - sslServer.getAuthorizationID(); - } - catch (IllegalStateException ise) { - assertTrue(ise.getMessage().equalsIgnoreCase("Authentication exchange has not completed")); - } - } - - @Test - public void testGetNegotiatedPropertyWithException() { - try { - sslServer.getNegotiatedProperty("test"); - } - catch (IllegalStateException ise) { - assertTrue(ise.getMessage().equalsIgnoreCase("Authentication exchange has not completed")); - } - } - - @Test - public void testIsComplete() { - try { - sslServer.getNegotiatedProperty("test"); - } - catch (IllegalStateException ise) { - assertTrue(ise.getMessage().equalsIgnoreCase("Authentication exchange has not completed")); - } - assert(true); - } - - @Test - public void testUnwrap() { - try { - sslServer.unwrap(new byte[1], 0, 0); - } - catch (IllegalStateException ise) { - assertTrue(ise.getMessage().equalsIgnoreCase("Authentication exchange has not completed")); - } catch (SaslAuthenticationException e) { - e.printStackTrace(); - } - assert(true); - } - - @Test - public void testWrap() { - try { - sslServer.wrap(new byte[1], 0, 0); - } - catch (IllegalStateException ise) { - assertTrue(ise.getMessage().equalsIgnoreCase("Authentication exchange has not completed")); - } catch (SaslAuthenticationException e) { - e.printStackTrace(); - } - assert(true); - } - - @Test - public void testGetMech() { - assertEquals("PLAIN", sslServer.getMechanismName()); - } - - @Test - public void testIsCompleteBool() { - assertFalse(sslServer.isComplete()); - } - - @Test - public void testPlainSaslServer1() throws SaslException { - PlainSaslServerFactory1 plainSaslServerFactory1 = new PlainSaslServerFactory1(); - PlainSaslServer1 saslServer1 = (PlainSaslServer1) plainSaslServerFactory1.createSaslServer(PlainSaslServer1.PLAIN_MECHANISM, "https", "mySaslServer", props, callbackHandler); - assertNotNull(saslServer1); - Mockito.when(props.get(Sasl.POLICY_NOPLAINTEXT)).thenReturn("javax.security.sasl.policy.noplaintext"); - assertEquals(new String[]{"PLAIN"}, plainSaslServerFactory1.getMechanismNames(props)); - } -} -- cgit 1.2.3-korg