diff --git a/apache-geode-extensions/apache-geode-extensions.gradle b/apache-geode-extensions/apache-geode-extensions.gradle new file mode 100644 index 00000000..5189cdc4 --- /dev/null +++ b/apache-geode-extensions/apache-geode-extensions.gradle @@ -0,0 +1,18 @@ +apply plugin: 'io.spring.convention.spring-module' + +description = "Apache Geode Extensions" + +dependencies { + + compile "org.apache.geode:geode-core:$apacheGeodeVersion" + compile "org.apache.geode:geode-cq:$apacheGeodeVersion" + compile "org.apache.geode:geode-lucene:$apacheGeodeVersion" + compile "org.apache.geode:geode-wan:$apacheGeodeVersion" + + testCompile "org.assertj:assertj-core" + testCompile "junit:junit" + testCompile "org.mockito:mockito-core" + testCompile "org.projectlombok:lombok" + testCompile "edu.umd.cs.mtc:multithreadedtc" + +} diff --git a/apache-geode-extensions/src/main/java/org/springframework/geode/security/TestAuthInitialize.java b/apache-geode-extensions/src/main/java/org/springframework/geode/security/TestAuthInitialize.java new file mode 100644 index 00000000..0140f403 --- /dev/null +++ b/apache-geode-extensions/src/main/java/org/springframework/geode/security/TestAuthInitialize.java @@ -0,0 +1,66 @@ +/* + * Copyright 2019 the original author or authors. + * + * 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 + * + * https://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. + */ + +package org.springframework.geode.security; + +import java.util.Properties; + +import org.apache.geode.LogWriter; +import org.apache.geode.distributed.DistributedMember; +import org.apache.geode.management.internal.security.ResourceConstants; +import org.apache.geode.security.AuthInitialize; +import org.apache.geode.security.AuthenticationFailedException; + +/** + * Simple, test {@link AuthInitialize} implementation. + * + * @author John Blum + * @see org.apache.geode.security.AuthInitialize + * @since 1.0.0 + */ +@SuppressWarnings("unused") +public class TestAuthInitialize implements AuthInitialize { + + private static final String DEFAULT_USERNAME = "test"; + private static final String DEFAULT_PASSWORD = DEFAULT_USERNAME; + + public static TestAuthInitialize create() { + return new TestAuthInitialize(); + } + + @Override + @SuppressWarnings("deprecation") + public void init(LogWriter systemLogger, LogWriter securityLogger) throws AuthenticationFailedException { } + + @Override + public Properties getCredentials(Properties securityProperties, DistributedMember server, boolean isPeer) + throws AuthenticationFailedException { + + Properties credentials = new Properties(); + + credentials.setProperty(ResourceConstants.USER_NAME, + securityProperties.getProperty(ResourceConstants.USER_NAME, DEFAULT_USERNAME)); + + credentials.setProperty(ResourceConstants.PASSWORD, + securityProperties.getProperty(ResourceConstants.PASSWORD, DEFAULT_PASSWORD)); + + return credentials; + } + + @Override + public void close() { } + +} diff --git a/apache-geode-extensions/src/main/java/org/springframework/geode/security/TestSecurityManager.java b/apache-geode-extensions/src/main/java/org/springframework/geode/security/TestSecurityManager.java new file mode 100644 index 00000000..80a88429 --- /dev/null +++ b/apache-geode-extensions/src/main/java/org/springframework/geode/security/TestSecurityManager.java @@ -0,0 +1,107 @@ +/* + * Copyright 2019 the original author or authors. + * + * 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 + * + * https://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. + */ +package org.springframework.geode.security; + +import java.io.Serializable; +import java.security.Principal; +import java.util.Properties; + +import org.apache.geode.management.internal.security.ResourceConstants; +import org.apache.geode.security.AuthenticationFailedException; + +/** + * Simple, test {@link org.apache.geode.security.SecurityManager}. + * + * @author John Blum + * @see java.security.Principal + * @see java.util.Properties + * @see org.apache.geode.security.SecurityManager + * @since 1.0.0 + */ +@SuppressWarnings("unused") +public class TestSecurityManager implements org.apache.geode.security.SecurityManager { + + @Override + public Object authenticate(Properties credentials) throws AuthenticationFailedException { + + String username = credentials.getProperty(ResourceConstants.USER_NAME); + String password = credentials.getProperty(ResourceConstants.PASSWORD); + + if (!String.valueOf(username).equals(password)) { + throw new AuthenticationFailedException(String.format("User [%s] could not be authenticated", username)); + } + + return User.create(username); + } + + public static class User implements Comparable, Principal, Serializable { + + public static User create(String name) { + return new User(name); + } + + private final String name; + + public User(String name) { + + if (name == null || name.trim().isEmpty()) { + throw new IllegalArgumentException("Username is required"); + } + + this.name = name; + } + + public String getName() { + return this.name; + } + + @Override + public int compareTo(User user) { + return this.getName().compareTo(user.getName()); + } + + @Override + public boolean equals(Object obj) { + + if (this == obj) { + return true; + } + + if (!(obj instanceof User)) { + return false; + } + + User that = (User) obj; + + return this.getName().equals(that.getName()); + } + + @Override + public int hashCode() { + + int hashValue = 17; + + hashValue = 37 * hashValue + getName().hashCode(); + + return hashValue; + } + + @Override + public String toString() { + return getName(); + } + } +} diff --git a/apache-geode-extensions/src/test/java/org/springframework/geode/security/TestAuthInitializeUnitTests.java b/apache-geode-extensions/src/test/java/org/springframework/geode/security/TestAuthInitializeUnitTests.java new file mode 100644 index 00000000..660c952d --- /dev/null +++ b/apache-geode-extensions/src/test/java/org/springframework/geode/security/TestAuthInitializeUnitTests.java @@ -0,0 +1,101 @@ +/* + * Copyright 2019 the original author or authors. + * + * 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 + * + * https://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. + */ + +package org.springframework.geode.security; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Properties; + +import org.apache.geode.management.internal.security.ResourceConstants; +import org.junit.Test; + +/** + * Unit tests for {@link TestAuthInitialize}. + * + * @author John Blum + * @see java.util.Properties + * @see org.junit.Test + * @see org.springframework.geode.security.TestAuthInitialize + * @since 1.0.0 + */ +public class TestAuthInitializeUnitTests { + + private final TestAuthInitialize authInitialize = TestAuthInitialize.create(); + + private boolean isSet(String value) { + return !(value == null || value.trim().isEmpty()); + } + + private Properties newSecurityProperties(String username, String password) { + + Properties securityProperties = new Properties(); + + if (isSet(username)) { + securityProperties.setProperty(ResourceConstants.USER_NAME, username); + } + + if (isSet(password)) { + securityProperties.setProperty(ResourceConstants.PASSWORD, password); + } + + return securityProperties; + } + + @Test + public void getCredentialsUsesProperties() { + + Properties credentials = + this.authInitialize.getCredentials(newSecurityProperties("testUser", "s3cr3t")); + + assertThat(credentials).isNotNull(); + assertThat(credentials.getProperty(ResourceConstants.USER_NAME)).isEqualTo("testUser"); + assertThat(credentials.getProperty(ResourceConstants.PASSWORD)).isEqualTo("s3cr3t"); + } + + @Test + public void getCredentialsUsesProvidedUsernameAndDefaultPassword() { + + Properties credentials = + this.authInitialize.getCredentials(newSecurityProperties("testUser", null)); + + assertThat(credentials).isNotNull(); + assertThat(credentials.getProperty(ResourceConstants.USER_NAME)).isEqualTo("testUser"); + assertThat(credentials.getProperty(ResourceConstants.PASSWORD)).isEqualTo("test"); + } + + @Test + public void getCredentialsUsesProvidedPasswordAndDefaultUsername() { + + Properties credentials = + this.authInitialize.getCredentials(newSecurityProperties(null, "s3cr3t")); + + assertThat(credentials).isNotNull(); + assertThat(credentials.getProperty(ResourceConstants.USER_NAME)).isEqualTo("test"); + assertThat(credentials.getProperty(ResourceConstants.PASSWORD)).isEqualTo("s3cr3t"); + } + + @Test + public void getCredentialsUsesDefaultUsernameAndPassword() { + + Properties credentials = + this.authInitialize.getCredentials(newSecurityProperties(null, null)); + + assertThat(credentials).isNotNull(); + assertThat(credentials.getProperty(ResourceConstants.USER_NAME)).isEqualTo("test"); + assertThat(credentials.getProperty(ResourceConstants.PASSWORD)).isEqualTo("test"); + } +} diff --git a/apache-geode-extensions/src/test/java/org/springframework/geode/security/TestSecurityManagerUnitTests.java b/apache-geode-extensions/src/test/java/org/springframework/geode/security/TestSecurityManagerUnitTests.java new file mode 100644 index 00000000..e921e6e0 --- /dev/null +++ b/apache-geode-extensions/src/test/java/org/springframework/geode/security/TestSecurityManagerUnitTests.java @@ -0,0 +1,102 @@ +/* + * Copyright 2019 the original author or authors. + * + * 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 + * + * https://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. + */ + +package org.springframework.geode.security; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +import java.security.Principal; +import java.util.Properties; + +import org.apache.geode.management.internal.security.ResourceConstants; +import org.apache.geode.security.AuthenticationFailedException; +import org.apache.geode.security.ResourcePermission; +import org.junit.Test; + +/** + * Unit tests for {@link org.springframework.geode.security.TestSecurityManager}. + * + * @author John Blum + * @see org.junit.Test + * @see org.mockito.Mockito + * @see org.springframework.geode.security.TestSecurityManager + * @since 1.0.0 + */ +public class TestSecurityManagerUnitTests { + + private TestSecurityManager securityManager = new TestSecurityManager(); + + private Properties newSecurityProperties(String username, String password) { + + Properties securityProperties = new Properties(); + + securityProperties.setProperty(ResourceConstants.USER_NAME, username); + securityProperties.setProperty(ResourceConstants.PASSWORD, password); + + return securityProperties; + } + + @Test + public void userAuthenticates() { + + Object user = this.securityManager.authenticate(newSecurityProperties("test", "test")); + + assertThat(user).isInstanceOf(TestSecurityManager.User.class); + assertThat(((TestSecurityManager.User) user).getName()).isEqualTo("test"); + } + + @Test(expected = AuthenticationFailedException.class) + public void userDoesNotAuthenticateBecauseUsernamePasswordAreCaseSensitive() { + + try { + this.securityManager.authenticate(newSecurityProperties("TestUser", "testuser")); + } + catch (AuthenticationFailedException expected) { + + assertThat(expected).hasMessage("User [TestUser] could not be authenticated"); + assertThat(expected).hasNoCause(); + + throw expected; + } + } + + @Test(expected = AuthenticationFailedException.class) + public void userDoesNotAuthenticateWhenUsernamePasswordDoNotMatch() { + + try { + this.securityManager.authenticate(newSecurityProperties("testUser", "testPassword")); + } + catch (AuthenticationFailedException expected) { + + assertThat(expected).hasMessage("User [testUser] could not be authenticated"); + assertThat(expected).hasNoCause(); + + throw expected; + } + } + + @Test + public void userIsAlwaysAuthorized() { + + ResourcePermission clusterManage = + new ResourcePermission(ResourcePermission.Resource.CLUSTER, ResourcePermission.Operation.MANAGE); + + assertThat(this.securityManager.authorize(null, clusterManage)).isTrue(); + assertThat(this.securityManager.authorize(new TestSecurityManager.User("test"), clusterManage)).isTrue(); + assertThat(this.securityManager.authorize(mock(Principal.class), clusterManage)).isTrue(); + } +}