/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You 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. */ package org.apache.geode.internal.cache.wan.misc; import static org.apache.geode.distributed.ConfigurationProperties.*; import static org.apache.geode.test.dunit.Assert.*; import java.util.Properties; import java.util.concurrent.TimeUnit; import com.jayway.awaitility.Awaitility; import org.apache.geode.security.TestSecurityManager; import org.apache.logging.log4j.Logger; import org.junit.Test; import org.junit.experimental.categories.Category; import org.apache.geode.cache.CacheFactory; import org.apache.geode.cache.Region; import org.apache.geode.distributed.DistributedMember; import org.apache.geode.distributed.DistributedSystem; import org.apache.geode.internal.Assert; import org.apache.geode.internal.cache.wan.WANTestBase; import org.apache.geode.internal.logging.LogService; import org.apache.geode.security.AuthInitialize; import org.apache.geode.security.AuthenticationFailedException; import org.apache.geode.security.SecurityTestUtils; import org.apache.geode.security.generator.CredentialGenerator; import org.apache.geode.security.generator.DummyCredentialGenerator; import org.apache.geode.security.templates.UserPasswordAuthInit; import org.apache.geode.test.junit.categories.DistributedTest; @Category(DistributedTest.class) public class NewWanAuthenticationDUnitTest extends WANTestBase { public static final Logger logger = LogService.getLogger(); public static boolean isDifferentServerInGetCredentialCall = false; /** * Authentication test for new WAN with valid credentials. Although, nothing related to * authentication has been changed in new WAN, this test case is added on request from QA for * defect 44650. */ @Test public void testWanAuthValidCredentials() { Integer lnPort = (Integer) vm0.invoke(() -> WANTestBase.createFirstLocatorWithDSId(1)); logger.info("Created locator on local site"); Integer nyPort = (Integer) vm1.invoke(() -> WANTestBase.createFirstRemoteLocator(2, lnPort)); logger.info("Created locator on remote site"); CredentialGenerator gen = new DummyCredentialGenerator(); Properties extraProps = gen.getSystemProperties(); String clientauthenticator = gen.getAuthenticator(); String clientauthInit = gen.getAuthInit(); Properties credentials1 = gen.getValidCredentials(1); if (extraProps != null) { credentials1.putAll(extraProps); } Properties javaProps1 = gen.getJavaProperties(); // vm3's invalid credentials Properties credentials2 = gen.getInvalidCredentials(1); if (extraProps != null) { credentials2.putAll(extraProps); } Properties javaProps2 = gen.getJavaProperties(); Properties props1 = buildProperties(clientauthenticator, clientauthInit, null, credentials1, null); // have vm 3 start a cache with invalid credentails Properties props2 = buildProperties(clientauthenticator, clientauthInit, null, credentials2, null); vm2.invoke(() -> NewWanAuthenticationDUnitTest.createSecuredCache(props1, javaProps1, lnPort)); logger.info("Created secured cache in vm2"); vm3.invoke(() -> NewWanAuthenticationDUnitTest.createSecuredCache(props2, javaProps2, nyPort)); logger.info("Created secured cache in vm3"); vm2.invoke(() -> WANTestBase.createSender("ln", 2, false, 100, 10, false, false, null, true)); logger.info("Created sender in vm2"); vm3.invoke(() -> createReceiverInSecuredCache()); logger.info("Created receiver in vm3"); vm2.invoke( () -> WANTestBase.createReplicatedRegion(getTestMethodName() + "_RR", "ln", isOffHeap())); logger.info("Created RR in vm2"); vm3.invoke( () -> WANTestBase.createReplicatedRegion(getTestMethodName() + "_RR", null, isOffHeap())); logger.info("Created RR in vm3"); // this tests verifies that even though vm3 has invalid credentials, vm2 can still send data to // vm3 because // vm2 has valid credentials vm2.invoke(() -> WANTestBase.startSender("ln")); vm2.invoke(() -> WANTestBase.waitForSenderRunningState("ln")); vm2.invoke(() -> WANTestBase.doPuts(getTestMethodName() + "_RR", 1)); vm3.invoke(() -> { Region r = cache.getRegion(Region.SEPARATOR + getTestMethodName() + "_RR"); Awaitility.waitAtMost(20, TimeUnit.SECONDS).until(() -> assertTrue(r.size() > 0)); }); logger.info("Done successfully."); } @Test public void testWanIntegratedSecurityWithValidCredentials() { Integer lnPort = (Integer) vm0.invoke(() -> WANTestBase.createFirstLocatorWithDSId(1)); logger.info("Created locator on local site"); Integer nyPort = (Integer) vm1.invoke(() -> WANTestBase.createFirstRemoteLocator(2, lnPort)); logger.info("Created locator on remote site"); Properties props1 = buildSecurityProperties("admin", "secret"); Properties props2 = buildSecurityProperties("guest", "guest"); vm2.invoke(() -> NewWanAuthenticationDUnitTest.createSecuredCache(props1, null, lnPort)); logger.info("Created secured cache in vm2"); vm3.invoke(() -> NewWanAuthenticationDUnitTest.createSecuredCache(props2, null, nyPort)); logger.info("Created secured cache in vm3"); vm2.invoke(() -> WANTestBase.createSender("ln", 2, false, 100, 10, false, false, null, true)); logger.info("Created sender in vm2"); vm3.invoke(() -> createReceiverInSecuredCache()); logger.info("Created receiver in vm3"); vm2.invoke( () -> WANTestBase.createReplicatedRegion(getTestMethodName() + "_RR", "ln", isOffHeap())); logger.info("Created RR in vm2"); vm3.invoke( () -> WANTestBase.createReplicatedRegion(getTestMethodName() + "_RR", null, isOffHeap())); logger.info("Created RR in vm3"); vm2.invoke(() -> WANTestBase.startSender("ln")); vm2.invoke(() -> WANTestBase.waitForSenderRunningState("ln")); vm2.invoke(() -> WANTestBase.doPuts(getTestMethodName() + "_RR", 1)); vm3.invoke(() -> { Region r = cache.getRegion(Region.SEPARATOR + getTestMethodName() + "_RR"); Awaitility.waitAtMost(20, TimeUnit.SECONDS).until(() -> assertTrue(r.size() > 0)); }); logger.info("Done successfully."); } /** * Test authentication with new WAN with invalid credentials. Although, nothing related to * authentication has been changed in new WAN, this test case is added on request from QA for * defect 44650. */ @Test public void testWanAuthInvalidCredentials() { Integer lnPort = (Integer) vm0.invoke(() -> WANTestBase.createFirstLocatorWithDSId(1)); logger.info("Created locator on local site"); Integer nyPort = (Integer) vm1.invoke(() -> WANTestBase.createFirstRemoteLocator(2, lnPort)); logger.info("Created locator on remote site"); CredentialGenerator gen = new DummyCredentialGenerator(); logger.info("Picked up credential: " + gen); Properties extraProps = gen.getSystemProperties(); String clientauthenticator = gen.getAuthenticator(); String clientauthInit = gen.getAuthInit(); Properties credentials1 = gen.getInvalidCredentials(1); if (extraProps != null) { credentials1.putAll(extraProps); } Properties javaProps1 = gen.getJavaProperties(); Properties credentials2 = gen.getInvalidCredentials(2); if (extraProps != null) { credentials2.putAll(extraProps); } Properties javaProps2 = gen.getJavaProperties(); Properties props1 = buildProperties(clientauthenticator, clientauthInit, null, credentials1, null); Properties props2 = buildProperties(clientauthenticator, clientauthInit, null, credentials2, null); logger.info("Done building auth properties"); vm2.invoke(() -> NewWanAuthenticationDUnitTest.createSecuredCache(props1, javaProps1, lnPort)); logger.info("Created secured cache in vm2"); vm3.invoke(() -> NewWanAuthenticationDUnitTest.createSecuredCache(props2, javaProps2, nyPort)); logger.info("Created secured cache in vm3"); vm2.invoke(() -> WANTestBase.createSender("ln", 2, false, 100, 10, false, false, null, true)); logger.info("Created sender in vm2"); vm3.invoke(() -> createReceiverInSecuredCache()); logger.info("Created receiver in vm3"); vm2.invoke( () -> WANTestBase.createReplicatedRegion(getTestMethodName() + "_RR", "ln", isOffHeap())); logger.info("Created RR in vm2"); vm3.invoke( () -> WANTestBase.createReplicatedRegion(getTestMethodName() + "_RR", null, isOffHeap())); logger.info("Created RR in vm3"); try { vm2.invoke(() -> WANTestBase.startSender("ln")); fail( "Authentication Failed: While starting the sender, an exception should have been thrown"); } catch (Exception e) { if (!(e.getCause().getCause() instanceof AuthenticationFailedException)) { fail("Authentication is not working as expected", e); } } } /** * Test authentication with new WAN with invalid credentials. Although, nothing related to * authentication has been changed in new WAN, this test case is added on request from QA for * defect 44650. */ @Test public void testWanSecurityManagerWithInvalidCredentials() { Integer lnPort = (Integer) vm0.invoke(() -> WANTestBase.createFirstLocatorWithDSId(1)); logger.info("Created locator on local site"); Integer nyPort = (Integer) vm1.invoke(() -> WANTestBase.createFirstRemoteLocator(2, lnPort)); logger.info("Created locator on remote site"); Properties props1 = buildSecurityProperties("admin", "wrongPswd"); Properties props2 = buildSecurityProperties("guest", "wrongPswd"); logger.info("Done building auth properties"); vm2.invoke(() -> NewWanAuthenticationDUnitTest.createSecuredCache(props1, null, lnPort)); logger.info("Created secured cache in vm2"); vm3.invoke(() -> NewWanAuthenticationDUnitTest.createSecuredCache(props2, null, nyPort)); logger.info("Created secured cache in vm3"); vm2.invoke(() -> WANTestBase.createSender("ln", 2, false, 100, 10, false, false, null, true)); logger.info("Created sender in vm2"); vm3.invoke(() -> createReceiverInSecuredCache()); logger.info("Created receiver in vm3"); vm2.invoke( () -> WANTestBase.createReplicatedRegion(getTestMethodName() + "_RR", "ln", isOffHeap())); logger.info("Created RR in vm2"); vm3.invoke( () -> WANTestBase.createReplicatedRegion(getTestMethodName() + "_RR", null, isOffHeap())); logger.info("Created RR in vm3"); try { vm2.invoke(() -> WANTestBase.startSender("ln")); fail( "Authentication Failed: While starting the sender, an exception should have been thrown"); } catch (Exception e) { if (!(e.getCause().getCause() instanceof AuthenticationFailedException)) { fail("Authentication is not working as expected", e); } } } private static Properties buildProperties(String clientauthenticator, String clientAuthInit, String accessor, Properties extraAuthProps, Properties extraAuthzProps) { Properties authProps = new Properties(); if (clientauthenticator != null) { authProps.setProperty(SECURITY_CLIENT_AUTHENTICATOR, clientauthenticator); } if (accessor != null) { authProps.setProperty(SECURITY_CLIENT_ACCESSOR, accessor); } if (clientAuthInit != null) { authProps.setProperty(SECURITY_CLIENT_AUTH_INIT, clientAuthInit); } if (extraAuthProps != null) { authProps.putAll(extraAuthProps); } if (extraAuthzProps != null) { authProps.putAll(extraAuthzProps); } return authProps; } private static Properties buildSecurityProperties(String username, String password) { Properties props = new Properties(); props.put(SECURITY_MANAGER, TestSecurityManager.class.getName()); props.put("security-json", "org/apache/geode/security/templates/security.json"); props.put(SECURITY_CLIENT_AUTH_INIT, UserPasswdAI.class.getName()); props.put("security-username", username); props.put("security-password", password); return props; } public static void createSecuredCache(Properties authProps, Object javaProps, Integer locPort) { authProps.setProperty(MCAST_PORT, "0"); authProps.setProperty(LOCATORS, "localhost[" + locPort + "]"); logger.info("Set the server properties to: " + authProps); logger.info("Set the java properties to: " + javaProps); SecurityTestUtils tmpInstance = new SecurityTestUtils("temp"); DistributedSystem ds = tmpInstance.createSystem(authProps, (Properties) javaProps); assertNotNull(ds); assertTrue(ds.isConnected()); cache = CacheFactory.create(ds); assertNotNull(cache); } public static class UserPasswdAI extends UserPasswordAuthInit { public static AuthInitialize createAI() { return new UserPasswdAI(); } @Override public Properties getCredentials(Properties props, DistributedMember server, boolean isPeer) throws AuthenticationFailedException { boolean val = (CacheFactory.getAnyInstance().getDistributedSystem().getDistributedMember() .getProcessId() != server.getProcessId()); Assert.assertTrue(val, "getCredentials: Server should be different"); Properties p = super.getCredentials(props, server, isPeer); if (val) { isDifferentServerInGetCredentialCall = true; CacheFactory.getAnyInstance().getLoggerI18n().convertToLogWriter() .config("setting isDifferentServerInGetCredentialCall " + isDifferentServerInGetCredentialCall); } else { CacheFactory.getAnyInstance().getLoggerI18n().convertToLogWriter() .config("setting22 isDifferentServerInGetCredentialCall " + isDifferentServerInGetCredentialCall); } return p; } } public static void verifyDifferentServerInGetCredentialCall() { Assert.assertTrue(isDifferentServerInGetCredentialCall, "verifyDifferentServerInGetCredentialCall: Server should be different"); isDifferentServerInGetCredentialCall = false; } @Test public void testWanAuthValidCredentialsWithServer() { disconnectAllFromDS(); { Integer lnPort = (Integer) vm0.invoke(() -> WANTestBase.createFirstLocatorWithDSId(1)); logger.info("Created locator on local site"); Integer nyPort = (Integer) vm1.invoke(() -> WANTestBase.createFirstRemoteLocator(2, lnPort)); logger.info("Created locator on remote site"); DummyCredentialGenerator gen = new DummyCredentialGenerator(); gen.init(); Properties extraProps = gen.getSystemProperties(); String clientauthenticator = gen.getAuthenticator(); String clientauthInit = UserPasswdAI.class.getName() + ".createAI"; Properties credentials1 = gen.getValidCredentials(1); if (extraProps != null) { credentials1.putAll(extraProps); } Properties javaProps1 = gen.getJavaProperties(); Properties credentials2 = gen.getInvalidCredentials(2); if (extraProps != null) { credentials2.putAll(extraProps); } Properties javaProps2 = gen.getJavaProperties(); Properties props1 = buildProperties(clientauthenticator, clientauthInit, null, credentials1, null); Properties props2 = buildProperties(clientauthenticator, clientauthInit, null, credentials2, null); vm2.invoke( () -> NewWanAuthenticationDUnitTest.createSecuredCache(props1, javaProps1, lnPort)); logger.info("Created secured cache in vm2"); vm3.invoke( () -> NewWanAuthenticationDUnitTest.createSecuredCache(props2, javaProps2, nyPort)); logger.info("Created secured cache in vm3"); vm2.invoke(() -> WANTestBase.createSender("ln", 2, false, 100, 10, false, false, null, true)); logger.info("Created sender in vm2"); vm3.invoke(() -> createReceiverInSecuredCache()); logger.info("Created receiver in vm3"); vm2.invoke(() -> WANTestBase.startSender("ln")); vm2.invoke(() -> WANTestBase.waitForSenderRunningState("ln")); vm2.invoke(() -> verifyDifferentServerInGetCredentialCall()); vm3.invoke(() -> verifyDifferentServerInGetCredentialCall()); } } @Test public void testWanSecurityManagerAuthValidCredentialsWithServer() { disconnectAllFromDS(); { Integer lnPort = (Integer) vm0.invoke(() -> WANTestBase.createFirstLocatorWithDSId(1)); logger.info("Created locator on local site"); Integer nyPort = (Integer) vm1.invoke(() -> WANTestBase.createFirstRemoteLocator(2, lnPort)); logger.info("Created locator on remote site"); Properties props1 = buildSecurityProperties("admin", "secret"); Properties props2 = buildSecurityProperties("guest", "guest"); vm2.invoke(() -> NewWanAuthenticationDUnitTest.createSecuredCache(props1, null, lnPort)); logger.info("Created secured cache in vm2"); vm3.invoke(() -> NewWanAuthenticationDUnitTest.createSecuredCache(props2, null, nyPort)); logger.info("Created secured cache in vm3"); vm2.invoke(() -> WANTestBase.createSender("ln", 2, false, 100, 10, false, false, null, true)); logger.info("Created sender in vm2"); vm3.invoke(() -> createReceiverInSecuredCache()); logger.info("Created receiver in vm3"); vm2.invoke(() -> WANTestBase.startSender("ln")); vm2.invoke(() -> WANTestBase.waitForSenderRunningState("ln")); vm2.invoke(() -> verifyDifferentServerInGetCredentialCall()); // this would fail for now because for integrated security, we are not sending the receiver's // credentials back // to the sender. Because in the old security implementation, even though the receiver's // credentials are sent back to the sender // the sender is not checking it. // vm3.invoke(() -> verifyDifferentServerInGetCredentialCall()); } } }