| /* |
| * 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 |
| } |
| } |