/* * 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.security; import org.apache.geode.cache.Region; import org.apache.geode.cache.client.Pool; import org.apache.geode.cache.execute.FunctionService; import org.apache.geode.cache.query.CqAttributesFactory; import org.apache.geode.cache.query.CqException; import org.apache.geode.cache.query.CqQuery; import org.apache.geode.cache.query.Query; import org.apache.geode.distributed.ConfigurationProperties; import org.apache.geode.internal.cache.GemFireCacheImpl; import org.apache.geode.internal.cache.PoolManagerImpl; import org.apache.geode.security.generator.CredentialGenerator; import org.apache.geode.security.generator.DummyCredentialGenerator; import org.apache.geode.test.junit.categories.DistributedTest; import org.apache.geode.test.junit.categories.SecurityTest; import org.junit.Test; import org.junit.experimental.categories.Category; import javax.net.ssl.SSLException; import javax.net.ssl.SSLHandshakeException; import java.io.IOException; import java.util.Properties; import static org.apache.geode.security.SecurityTestUtils.NO_EXCEPTION; import static org.apache.geode.test.dunit.Assert.fail; import static org.apache.geode.test.dunit.LogWriterUtils.getLogWriter; @Category({DistributedTest.class, SecurityTest.class}) public class MultiUserAPIDUnitTest extends ClientAuthorizationTestCase { private static final String[] serverIgnoredExceptions = {AuthenticationRequiredException.class.getName(), AuthenticationFailedException.class.getName(), GemFireSecurityException.class.getName(), ClassNotFoundException.class.getName(), IOException.class.getName(), SSLException.class.getName(), SSLHandshakeException.class.getName()}; private static final String[] clientIgnoredExceptions = {AuthenticationRequiredException.class.getName(), AuthenticationFailedException.class.getName(), SSLHandshakeException.class.getName()}; @Test public void testSingleUserUnsupportedAPIs() { // Start servers // Start clients with multiuser-authentication set to false setUpVMs(new DummyCredentialGenerator(), false); client1.invoke(() -> verifyDisallowedOps(false)); } @Test public void testMultiUserUnsupportedAPIs() { // Start servers. // Start clients with multiuser-authentication set to true. setUpVMs(new DummyCredentialGenerator(), true); client1.invoke(() -> verifyDisallowedOps(true)); } private void verifyDisallowedOps(final boolean multiUserMode) throws Exception { String op = "unknown"; boolean success = false; if (!multiUserMode) { success = false; try { // Attempt cache.createAuthenticatedCacheView() and expect an exception, fail otherwise op = "Pool.createSecureUserCache()"; GemFireCacheImpl.getInstance().createAuthenticatedView(new Properties(), "testPool"); } catch (IllegalStateException uoe) { getLogWriter().info(op + ": Got expected exception: " + uoe); success = true; } if (!success) { fail("Did not get exception while doing " + op); } } else { // multiuser mode Region realRegion = GemFireCacheImpl.getInstance().getRegion(SecurityTestUtils.REGION_NAME); Region proxyRegion = SecurityTestUtils.getProxyCaches(0).getRegion(SecurityTestUtils.REGION_NAME); Pool pool = PoolManagerImpl.getPMI().find("testPool"); for (int i = 0; i <= 27; i++) { success = false; try { switch (i) { // Attempt (real) Region.create/put/get/containsKeyOnServer/destroy/ // destroyRegion/clear/remove/registerInterest/unregisterInterest() // and expect an exception, fail otherwise. case 0: op = "Region.create()"; realRegion.create("key", "value"); break; case 1: op = "Region.put()"; realRegion.put("key", "value"); break; case 2: op = "Region.get()"; realRegion.get("key"); break; case 3: op = "Region.containsKeyOnServer()"; realRegion.containsKeyOnServer("key"); break; case 4: op = "Region.remove()"; realRegion.remove("key"); break; case 5: op = "Region.destroy()"; realRegion.destroy("key"); break; case 6: op = "Region.destroyRegion()"; realRegion.destroyRegion(); break; case 7: op = "Region.registerInterest()"; realRegion.registerInterest("key"); break; // case 8: // op = "Region.unregisterInterest()"; // realRegion.unregisterInterest("key"); // break; case 8: op = "Region.clear()"; realRegion.clear(); break; // Attempt ProxyRegion.createSubregion/forceRolling/ // getAttributesMutator/registerInterest/loadSnapShot/saveSnapshot/ // setUserAttribute/unregisterInterest/writeToDisk // and expect an exception, fail otherwise. case 9: op = "ProxyRegion.createSubregion()"; proxyRegion.createSubregion("subregion", null); break; case 10: op = "ProxyRegion.forceRolling()"; proxyRegion.forceRolling(); break; case 11: op = "ProxyRegion.getAttributesMutator()"; proxyRegion.getAttributesMutator(); break; case 12: op = "ProxyRegion.registerInterest()"; proxyRegion.registerInterest("key"); break; case 13: op = "ProxyRegion.loadSnapshot()"; proxyRegion.loadSnapshot(null); break; case 14: op = "ProxyRegion.saveSnapshot()"; proxyRegion.saveSnapshot(null); break; case 15: op = "ProxyRegion.setUserAttribute()"; proxyRegion.setUserAttribute(null); break; case 16: op = "ProxyRegion.unregisterInterestRegex()"; proxyRegion.unregisterInterestRegex("*"); break; // Attempt FunctionService.onRegion/onServer/s(pool) and expect an // exception, fail otherwise. case 17: op = "FunctionService.onRegion()"; FunctionService.onRegion(realRegion); break; case 18: op = "FunctionService.onServer(pool)"; FunctionService.onServer(pool); break; case 19: op = "FunctionService.onServers(pool)"; FunctionService.onServers(pool); break; // Attempt // QueryService.newQuery().execute()/newCq().execute/executeWithInitialResults() case 20: op = "QueryService.newQuery.execute()"; Query query = pool.getQueryService() .newQuery("SELECT * FROM /" + SecurityTestUtils.REGION_NAME); query.execute(); break; case 21: op = "QueryService.newCq.execute()"; CqQuery cqQuery = pool.getQueryService().newCq("SELECT * FROM /" + SecurityTestUtils.REGION_NAME, new CqAttributesFactory().create()); try { cqQuery.execute(); } catch (CqException ce) { throw (Exception) ce.getCause(); } break; case 22: op = "QueryService.newCq.executeWithInitialResults()"; cqQuery = pool.getQueryService().newCq("SELECT * FROM /" + SecurityTestUtils.REGION_NAME, new CqAttributesFactory().create()); try { cqQuery.executeWithInitialResults(); } catch (CqException ce) { throw (Exception) ce.getCause(); } break; // Attempt ProxyQueryService.getIndex/createIndex/removeIndex() and // expect an exception, fail otherwise. case 23: op = "ProxyQueryService().getIndexes()"; SecurityTestUtils.getProxyCaches(0).getQueryService().getIndexes(null); break; case 24: op = "ProxyQueryService().createIndex()"; SecurityTestUtils.getProxyCaches(0).getQueryService().createIndex(null, null, null); break; case 25: op = "ProxyQueryService().removeIndexes()"; SecurityTestUtils.getProxyCaches(0).getQueryService().removeIndexes(); break; case 26: op = "ProxyRegion.localDestroy()"; proxyRegion.localDestroy("key"); break; case 27: op = "ProxyRegion.localInvalidate()"; proxyRegion.localInvalidate("key"); break; default: fail("Unknown op code: " + i); break; } } catch (UnsupportedOperationException uoe) { getLogWriter().info(op + ": Got expected exception: " + uoe); success = true; } if (!success) { fail("Did not get exception while doing " + op); } } } } private void setUpVMs(final CredentialGenerator gen, final boolean multiUser) { Properties extraProps = gen.getSystemProperties(); Properties javaProps = gen.getJavaProperties(); String authenticator = gen.getAuthenticator(); String authInit = gen.getAuthInit(); getLogWriter().info("testValidCredentials: Using scheme: " + gen.classCode()); getLogWriter().info("testValidCredentials: Using authenticator: " + authenticator); getLogWriter().info("testValidCredentials: Using authinit: " + authInit); // Start the servers int locPort1 = SecurityTestUtils.getLocatorPort(); int locPort2 = SecurityTestUtils.getLocatorPort(); String locString = SecurityTestUtils.getAndClearLocatorString(); int port1 = server1 .invoke(() -> createCacheServer(locPort1, locString, authenticator, extraProps, javaProps)); int port2 = server2 .invoke(() -> createCacheServer(locPort2, locString, authenticator, extraProps, javaProps)); // Start the clients with valid credentials Properties credentials1 = gen.getValidCredentials(1); Properties javaProps1 = gen.getJavaProperties(); getLogWriter().info( "testValidCredentials: For first client credentials: " + credentials1 + " : " + javaProps1); Properties credentials2 = gen.getValidCredentials(2); Properties javaProps2 = gen.getJavaProperties(); getLogWriter().info("testValidCredentials: For second client credentials: " + credentials2 + " : " + javaProps2); client1.invoke(() -> createCacheClient(authInit, credentials1, javaProps1, port1, port2, 0, multiUser, NO_EXCEPTION)); } private int createCacheServer(final int dsPort, final String locatorString, final String authenticator, final Properties extraProps, final Properties javaProps) { Properties authProps = new Properties(); if (extraProps != null) { authProps.putAll(extraProps); } if (authenticator != null) { authProps.setProperty(ConfigurationProperties.SECURITY_CLIENT_AUTHENTICATOR, authenticator); } return SecurityTestUtils.createCacheServer(authProps, javaProps, dsPort, locatorString, 0, NO_EXCEPTION); } // a protected static void createCacheClient(final String authInit, final Properties authProps, final Properties javaProps, final int[] ports, final int numConnections, final boolean multiUserMode, final int expectedResult) { SecurityTestUtils.createCacheClient(authInit, authProps, javaProps, ports, numConnections, multiUserMode, expectedResult); // invokes SecurityTestUtils 2 } // b private void createCacheClient(final String authInit, final Properties authProps, final Properties javaProps, final int port1, final int port2, final int numConnections, final boolean multiUserMode, final int expectedResult) { createCacheClient(authInit, authProps, javaProps, new int[] {port1, port2}, numConnections, multiUserMode, expectedResult); // invokes a } }