http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9d7a6960/geode-core/src/test/java/org/apache/geode/security/IntegratedClientRegionClearAuthDistributedTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/IntegratedClientRegionClearAuthDistributedTest.java b/geode-core/src/test/java/org/apache/geode/security/IntegratedClientRegionClearAuthDistributedTest.java new file mode 100644 index 0000000..3c5a2ef --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/security/IntegratedClientRegionClearAuthDistributedTest.java @@ -0,0 +1,63 @@ +/* + * 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 com.gemstone.gemfire.security; + +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.gemstone.gemfire.cache.Region; +import com.gemstone.gemfire.cache.client.ClientCache; +import com.gemstone.gemfire.cache.client.ClientCacheFactory; +import com.gemstone.gemfire.cache.client.ClientRegionShortcut; +import com.gemstone.gemfire.test.dunit.SerializableRunnable; +import com.gemstone.gemfire.test.junit.categories.DistributedTest; +import com.gemstone.gemfire.test.junit.categories.SecurityTest; + +@Category({ DistributedTest.class, SecurityTest.class }) +public class IntegratedClientRegionClearAuthDistributedTest extends AbstractSecureServerDUnitTest { + + @Test + public void testRegionClear() throws InterruptedException { + // Verify that an unauthorized user can't clear the region + SerializableRunnable clearUnauthorized = new SerializableRunnable() { + @Override + public void run() { + ClientCache cache = new ClientCacheFactory(createClientProperties("stranger", "1234567")).setPoolSubscriptionEnabled(true) + .addPoolServer("localhost", serverPort) + .create(); + + Region region = cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(REGION_NAME); + assertNotAuthorized(() -> region.clear(), "DATA:WRITE:AuthRegion"); + } + }; + client1.invoke(clearUnauthorized); + + // Verify that an authorized user can clear the region + SerializableRunnable clearAuthorized = new SerializableRunnable() { + @Override + public void run() { + ClientCache cache = new ClientCacheFactory(createClientProperties("authRegionUser", "1234567")).setPoolSubscriptionEnabled(true) + .addPoolServer("localhost", serverPort) + .create(); + + Region region = cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(REGION_NAME); + region.clear(); + } + }; + client2.invoke(clearAuthorized); + } +}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9d7a6960/geode-core/src/test/java/org/apache/geode/security/IntegratedClientRegisterInterestAuthDistributedTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/IntegratedClientRegisterInterestAuthDistributedTest.java b/geode-core/src/test/java/org/apache/geode/security/IntegratedClientRegisterInterestAuthDistributedTest.java new file mode 100644 index 0000000..8e67ead --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/security/IntegratedClientRegisterInterestAuthDistributedTest.java @@ -0,0 +1,164 @@ +/* + * 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 com.gemstone.gemfire.security; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.gemstone.gemfire.cache.Region; +import com.gemstone.gemfire.cache.client.ClientCache; +import com.gemstone.gemfire.cache.client.ClientCacheFactory; +import com.gemstone.gemfire.cache.client.ClientRegionShortcut; +import com.gemstone.gemfire.test.dunit.AsyncInvocation; +import com.gemstone.gemfire.test.junit.categories.DistributedTest; +import com.gemstone.gemfire.test.junit.categories.SecurityTest; + +@Category({ DistributedTest.class, SecurityTest.class }) +public class IntegratedClientRegisterInterestAuthDistributedTest extends AbstractSecureServerDUnitTest { + + @Test + public void testRegisterInterest() throws InterruptedException { + // client1 connects to server as a user not authorized to do any operations + AsyncInvocation ai1 = client1.invokeAsync(() -> { + ClientCache cache = new ClientCacheFactory(createClientProperties("stranger", "1234567")).setPoolSubscriptionEnabled(true) + .addPoolServer("localhost", serverPort) + .create(); + + Region region = cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(REGION_NAME); + assertNotAuthorized(() -> region.registerInterest("key3"), "DATA:READ:AuthRegion:key3"); + }); + + // client2 connects to user as a user authorized to use AuthRegion region + AsyncInvocation ai2 = client2.invokeAsync(() -> { + ClientCache cache = new ClientCacheFactory(createClientProperties("authRegionUser", "1234567")).setPoolSubscriptionEnabled(true) + .addPoolServer("localhost", serverPort) + .create(); + + Region region = cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(REGION_NAME); + region.registerInterest("key3"); // DATA:READ:AuthRegion:key3; + }); + + // client3 connects to user as a user authorized to use key1 in AuthRegion region + AsyncInvocation ai3 = client3.invokeAsync(() -> { + ClientCache cache = new ClientCacheFactory(createClientProperties("key1User", "1234567")).setPoolSubscriptionEnabled(true) + .addPoolServer("localhost", serverPort) + .create(); + + Region region = cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(REGION_NAME); + assertNotAuthorized(() -> region.registerInterest("key2"), "DATA:READ:AuthRegion:key2"); + }); + + ai1.join(); + ai2.join(); + ai3.join(); + + ai1.checkException(); + ai2.checkException(); + ai3.checkException(); + } + + @Test + public void testRegisterInterestRegex() throws InterruptedException { + //client1 connects to server as a user not authorized to do any operations + AsyncInvocation ai1 = client1.invokeAsync(() -> { + ClientCache cache = new ClientCacheFactory(createClientProperties("stranger", "1234567")).setPoolSubscriptionEnabled(true) + .addPoolServer("localhost", serverPort) + .create(); + + Region region = cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(REGION_NAME); + assertNotAuthorized(() -> region.registerInterestRegex("key.*"), "DATA:READ:AuthRegion"); + }); + + // client2 connects to user as a user authorized to use AuthRegion region + AsyncInvocation ai2 = client2.invokeAsync(() -> { + ClientCache cache = new ClientCacheFactory(createClientProperties("authRegionUser", "1234567")).setPoolSubscriptionEnabled(true) + .addPoolServer("localhost", serverPort) + .create(); + + Region region = cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(REGION_NAME); + region.registerInterestRegex("key[0-9]+"); // DATA:READ:AuthRegion:key3; + }); + + // client3 connects to user as a user authorized to use key1 in AuthRegion region + AsyncInvocation ai3 = client3.invokeAsync(() -> { + ClientCache cache = new ClientCacheFactory(createClientProperties("key1User", "1234567")).setPoolSubscriptionEnabled(true) + .addPoolServer("localhost", serverPort) + .create(); + + Region region = cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(REGION_NAME); + assertNotAuthorized(() -> region.registerInterestRegex("key[0-9]+"), "DATA:READ:AuthRegion"); + assertNotAuthorized(() -> region.registerInterestRegex("key1"), "DATA:READ:AuthRegion"); + }); + + ai1.join(); + ai2.join(); + ai3.join(); + + ai1.checkException(); + ai2.checkException(); + ai3.checkException(); + } + + @Test + public void testRegisterInterestList() throws InterruptedException { + List<String> keys = new ArrayList<>(); + keys.add("key1"); + keys.add("key2"); + + //client1 connects to server as a user not authorized to do any operations + AsyncInvocation ai1 = client1.invokeAsync(() -> { + ClientCache cache = new ClientCacheFactory(createClientProperties("stranger", "1234567")).setPoolSubscriptionEnabled(true) + .addPoolServer("localhost", serverPort) + .create(); + + Region region = cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(REGION_NAME); + assertNotAuthorized(() -> region.registerInterest(keys), "DATA:READ:AuthRegion"); + }); + + // client2 connects to user as a user authorized to use AuthRegion region + AsyncInvocation ai2 = client2.invokeAsync(() -> { + ClientCache cache = new ClientCacheFactory(createClientProperties("authRegionUser", "1234567")).setPoolSubscriptionEnabled(true) + .addPoolServer("localhost", serverPort) + .create(); + + Region region = cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(REGION_NAME); + region.registerInterest(keys); // DATA:READ:AuthRegion; + }); + + // client3 connects to user as a user authorized to use key1 in AuthRegion region + AsyncInvocation ai3 = client3.invokeAsync(() -> { + ClientCache cache = new ClientCacheFactory(createClientProperties("key1User", "1234567")).setPoolSubscriptionEnabled(true) + .addPoolServer("localhost", serverPort) + .create(); + + Region region = cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(REGION_NAME); + assertNotAuthorized(() -> region.registerInterest(keys), "DATA:READ:AuthRegion"); + }); + + ai1.join(); + ai2.join(); + ai3.join(); + + ai1.checkException(); + ai2.checkException(); + ai3.checkException(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9d7a6960/geode-core/src/test/java/org/apache/geode/security/IntegratedClientRemoveAllAuthDistributedTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/IntegratedClientRemoveAllAuthDistributedTest.java b/geode-core/src/test/java/org/apache/geode/security/IntegratedClientRemoveAllAuthDistributedTest.java new file mode 100644 index 0000000..357ed98 --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/security/IntegratedClientRemoveAllAuthDistributedTest.java @@ -0,0 +1,65 @@ +/* + * 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 com.gemstone.gemfire.security; + +import static org.junit.Assert.*; + +import java.util.Arrays; + +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.gemstone.gemfire.cache.Region; +import com.gemstone.gemfire.cache.client.ClientCache; +import com.gemstone.gemfire.cache.client.ClientCacheFactory; +import com.gemstone.gemfire.cache.client.ClientRegionShortcut; +import com.gemstone.gemfire.test.dunit.AsyncInvocation; +import com.gemstone.gemfire.test.junit.categories.DistributedTest; +import com.gemstone.gemfire.test.junit.categories.SecurityTest; + +@Category({ DistributedTest.class, SecurityTest.class }) +public class IntegratedClientRemoveAllAuthDistributedTest extends AbstractSecureServerDUnitTest { + + @Test + public void testRemoveAll() throws InterruptedException { + + AsyncInvocation ai1 = client1.invokeAsync(() -> { + ClientCache cache = new ClientCacheFactory(createClientProperties("authRegionReader", "1234567")).setPoolSubscriptionEnabled(true) + .addPoolServer("localhost", serverPort) + .create(); + + Region region = cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(REGION_NAME); + assertNotAuthorized(() -> region.removeAll(Arrays.asList("key1", "key2", "key3", "key4")), "DATA:WRITE:AuthRegion"); + }); + + AsyncInvocation ai2 = client2.invokeAsync(() -> { + ClientCache cache = new ClientCacheFactory(createClientProperties("authRegionWriter", "1234567")).setPoolSubscriptionEnabled(true) + .addPoolServer("localhost", serverPort) + .create(); + + Region region = cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(REGION_NAME); + region.removeAll(Arrays.asList("key1", "key2", "key3", "key4")); + assertFalse(region.containsKey("key1")); + assertNotAuthorized(() -> region.containsKeyOnServer("key1"), "DATA:READ:AuthRegion:key1"); + }); + ai1.join(); + ai2.join(); + ai1.checkException(); + ai2.checkException(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9d7a6960/geode-core/src/test/java/org/apache/geode/security/IntegratedClientSizeAuthDistributedTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/IntegratedClientSizeAuthDistributedTest.java b/geode-core/src/test/java/org/apache/geode/security/IntegratedClientSizeAuthDistributedTest.java new file mode 100644 index 0000000..8ca6995 --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/security/IntegratedClientSizeAuthDistributedTest.java @@ -0,0 +1,54 @@ +/* + * 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 com.gemstone.gemfire.security; + +import org.junit.Ignore; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.gemstone.gemfire.cache.client.ClientCache; +import com.gemstone.gemfire.cache.client.internal.InternalPool; +import com.gemstone.gemfire.cache.client.internal.SizeOp; +import com.gemstone.gemfire.test.dunit.AsyncInvocation; +import com.gemstone.gemfire.test.junit.categories.DistributedTest; +import com.gemstone.gemfire.test.junit.categories.SecurityTest; + +@Category({ DistributedTest.class, SecurityTest.class }) +public class IntegratedClientSizeAuthDistributedTest extends AbstractSecureServerDUnitTest { + + @Test + @Ignore("This is not a supported client message") + // this would fail sporadically because ServerConnection.isInternalMessage would return true for this message, + // and it won't bind the correct subject on the executing thread. + public void testSize() throws InterruptedException { + + AsyncInvocation ai1 = client1.invokeAsync(() -> { + ClientCache cache = createClientCache("dataWriter", "1234567", serverPort); + assertNotAuthorized(() -> SizeOp.execute((InternalPool) cache.getDefaultPool(), REGION_NAME), "DATA:READ:AuthRegion"); + }); + + AsyncInvocation ai2 = client2.invokeAsync(() -> { + ClientCache cache = createClientCache("authRegionReader", "1234567", serverPort); + SizeOp.execute((InternalPool) cache.getDefaultPool(), REGION_NAME); + }); + + ai1.join(); + ai2.join(); + ai1.checkException(); + ai2.checkException(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9d7a6960/geode-core/src/test/java/org/apache/geode/security/IntegratedClientUnregisterInterestAuthDistributedTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/IntegratedClientUnregisterInterestAuthDistributedTest.java b/geode-core/src/test/java/org/apache/geode/security/IntegratedClientUnregisterInterestAuthDistributedTest.java new file mode 100644 index 0000000..14edeb4 --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/security/IntegratedClientUnregisterInterestAuthDistributedTest.java @@ -0,0 +1,48 @@ +/* + * 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 com.gemstone.gemfire.security; + +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.gemstone.gemfire.cache.Region; +import com.gemstone.gemfire.cache.client.ClientCache; +import com.gemstone.gemfire.cache.client.ClientCacheFactory; +import com.gemstone.gemfire.cache.client.ClientRegionShortcut; +import com.gemstone.gemfire.test.dunit.AsyncInvocation; +import com.gemstone.gemfire.test.junit.categories.DistributedTest; +import com.gemstone.gemfire.test.junit.categories.SecurityTest; + +@Category({ DistributedTest.class, SecurityTest.class }) +public class IntegratedClientUnregisterInterestAuthDistributedTest extends AbstractSecureServerDUnitTest { + + @Test + public void testUnregisterInterest() throws InterruptedException { + // client2 connects to user as a user authorized to use AuthRegion region + AsyncInvocation ai1 = client2.invokeAsync(() -> { + ClientCache cache = new ClientCacheFactory(createClientProperties("authRegionUser", "1234567")).setPoolSubscriptionEnabled(true) + .addPoolServer("localhost", serverPort) + .create(); + + Region region = cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(REGION_NAME); + region.registerInterest("key3"); + region.unregisterInterest("key3"); // DATA:READ:AuthRegion:key3; + }); + ai1.join(); + ai1.checkException(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9d7a6960/geode-core/src/test/java/org/apache/geode/security/IntegratedSecurityCacheLifecycleDistributedTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/IntegratedSecurityCacheLifecycleDistributedTest.java b/geode-core/src/test/java/org/apache/geode/security/IntegratedSecurityCacheLifecycleDistributedTest.java new file mode 100644 index 0000000..2920fd5 --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/security/IntegratedSecurityCacheLifecycleDistributedTest.java @@ -0,0 +1,134 @@ +/* + * 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 com.gemstone.gemfire.security; + +import static com.gemstone.gemfire.distributed.ConfigurationProperties.*; +import static org.assertj.core.api.Assertions.*; + +import java.io.IOException; +import java.util.Properties; + +import org.apache.geode.security.templates.SampleSecurityManager; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.gemstone.gemfire.cache.server.CacheServer; +import com.gemstone.gemfire.internal.AvailablePort; +import com.gemstone.gemfire.internal.security.IntegratedSecurityService; +import com.gemstone.gemfire.internal.security.SecurityService; +import com.gemstone.gemfire.internal.AvailablePortHelper; +import com.gemstone.gemfire.management.ManagementService; +import com.gemstone.gemfire.test.dunit.DistributedTestUtils; +import com.gemstone.gemfire.test.dunit.Host; +import com.gemstone.gemfire.test.dunit.NetworkUtils; +import com.gemstone.gemfire.test.dunit.VM; +import com.gemstone.gemfire.test.dunit.cache.internal.JUnit4CacheTestCase; +import com.gemstone.gemfire.test.junit.categories.DistributedTest; +import com.gemstone.gemfire.test.junit.categories.SecurityTest; + +@Ignore("This is broken but fixed on feature/GEODE-1673") +@Category({DistributedTest.class, SecurityTest.class}) +public class IntegratedSecurityCacheLifecycleDistributedTest extends JUnit4CacheTestCase { + + private String locators; + private VM locator; + private SecurityService securityService; + + @Override + public final void postSetUp() throws Exception { + Host host = Host.getHost(0); + locator = host.getVM(0); + + securityService = IntegratedSecurityService.getSecurityService(); + + int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2); + int locatorPort = ports[0]; + int managerPort = ports[1]; + + locators = NetworkUtils.getServerHostName(host) + "[" + locatorPort + "]"; + + locator.invoke(() -> { + DistributedTestUtils.deleteLocatorStateFile(locatorPort); + + final Properties properties = new Properties(); + properties.setProperty(SampleSecurityManager.SECURITY_JSON, "com/gemstone/gemfire/management/internal/security/clientServer.json"); + properties.setProperty(LOCATORS, locators); + properties.setProperty(MCAST_PORT, "0"); + properties.setProperty(SECURITY_ENABLED_COMPONENTS, ""); + properties.setProperty(SECURITY_MANAGER, SpySecurityManager.class.getName()); + properties.setProperty(START_LOCATOR, locators); + properties.setProperty(JMX_MANAGER, "true"); + properties.setProperty(JMX_MANAGER_START, "true"); + properties.setProperty(JMX_MANAGER_PORT, String.valueOf(managerPort)); + properties.setProperty(USE_CLUSTER_CONFIGURATION, "false"); + getSystem(properties); + getCache(); + }); + } + + @Test + public void initAndCloseTest() throws Exception { + connect(); + + { + ManagementService ms = ManagementService.getExistingManagementService(getCache()); + assertThat(ms).isNotNull(); + assertThat(ms.isManager()).isFalse(); + + verifyInitCloseInvoked(); + } + + locator.invoke(() -> { + ManagementService ms = ManagementService.getExistingManagementService(getCache()); + assertThat(ms).isNotNull(); + assertThat(ms.isManager()).isTrue(); + + verifyInitCloseInvoked(); + }); + } + + private void connect() throws IOException { + final Properties properties = new Properties(); + properties.setProperty(SampleSecurityManager.SECURITY_JSON, "com/gemstone/gemfire/management/internal/security/clientServer.json"); + properties.setProperty(LOCATORS, locators); + properties.setProperty(MCAST_PORT, "0"); + properties.setProperty(SECURITY_ENABLED_COMPONENTS, ""); + properties.setProperty(SECURITY_MANAGER, SpySecurityManager.class.getName()); + properties.setProperty(USE_CLUSTER_CONFIGURATION, "false"); + + getSystem(properties); + + CacheServer server1 = getCache().addCacheServer(); + server1.setPort(0); + server1.start(); + + getCache(); + } + + @Override + public void postTearDownCacheTestCase() throws Exception { + closeAllCache(); + } + + private void verifyInitCloseInvoked() { + SpySecurityManager ssm = (SpySecurityManager) this.securityService.getSecurityManager(); + assertThat(ssm.initInvoked).isEqualTo(1); + getCache().close(); + assertThat(ssm.closeInvoked).isEqualTo(1); + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9d7a6960/geode-core/src/test/java/org/apache/geode/security/IntegratedSecurityCacheLifecycleIntegrationTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/IntegratedSecurityCacheLifecycleIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/security/IntegratedSecurityCacheLifecycleIntegrationTest.java new file mode 100644 index 0000000..8cb894a --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/security/IntegratedSecurityCacheLifecycleIntegrationTest.java @@ -0,0 +1,74 @@ +/* + * 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 com.gemstone.gemfire.security; + +import static com.gemstone.gemfire.distributed.ConfigurationProperties.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.Properties; + +import com.gemstone.gemfire.cache.Cache; +import com.gemstone.gemfire.cache.CacheFactory; +import com.gemstone.gemfire.internal.security.IntegratedSecurityService; +import com.gemstone.gemfire.internal.security.SecurityService; +import com.gemstone.gemfire.test.junit.categories.IntegrationTest; +import com.gemstone.gemfire.test.junit.categories.SecurityTest; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +@Category({IntegrationTest.class, SecurityTest.class}) +public class IntegratedSecurityCacheLifecycleIntegrationTest { + + private Properties securityProps; + private Cache cache; + private SecurityService securityService; + + @Before + public void before() { + securityService = IntegratedSecurityService.getSecurityService(); + + securityProps = new Properties(); + securityProps.setProperty(SECURITY_MANAGER, SpySecurityManager.class.getName()); + + Properties props = new Properties(); + props.putAll(securityProps); + props.setProperty(MCAST_PORT, "0"); + props.setProperty(LOCATORS, ""); + + cache = new CacheFactory(props).create(); + } + + @After + public void after() { + if (cache != null && !cache.isClosed()) { + cache.close(); + } + } + + @Test + public void initAndCloseTest () { + SpySecurityManager ssm = (SpySecurityManager)securityService.getSecurityManager(); + assertThat(ssm.initInvoked).isEqualTo(1); + cache.close(); + assertThat(ssm.closeInvoked).isEqualTo(1); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9d7a6960/geode-core/src/test/java/org/apache/geode/security/IntegratedSecurityPeerAuthDistributedTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/IntegratedSecurityPeerAuthDistributedTest.java b/geode-core/src/test/java/org/apache/geode/security/IntegratedSecurityPeerAuthDistributedTest.java new file mode 100644 index 0000000..7a4830d --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/security/IntegratedSecurityPeerAuthDistributedTest.java @@ -0,0 +1,146 @@ +/* + * 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 com.gemstone.gemfire.security; + +import static com.gemstone.gemfire.distributed.ConfigurationProperties.*; +import static com.gemstone.gemfire.test.dunit.Invoke.*; +import static org.assertj.core.api.Assertions.*; + +import java.util.Properties; + +import com.gemstone.gemfire.internal.AvailablePort; +import com.gemstone.gemfire.security.templates.UserPasswordAuthInit; +import com.gemstone.gemfire.test.dunit.DistributedTestUtils; +import com.gemstone.gemfire.test.dunit.Host; +import com.gemstone.gemfire.test.dunit.NetworkUtils; +import com.gemstone.gemfire.test.dunit.VM; +import com.gemstone.gemfire.test.dunit.cache.internal.JUnit4CacheTestCase; +import com.gemstone.gemfire.test.junit.categories.DistributedTest; +import com.gemstone.gemfire.test.junit.categories.SecurityTest; + +import org.apache.geode.security.templates.SampleSecurityManager; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +@Category({ DistributedTest.class, SecurityTest.class }) +public class IntegratedSecurityPeerAuthDistributedTest extends JUnit4CacheTestCase{ + + private static SpySecurityManager spySecurityManager; + + private VM locator; + private VM server1; + private VM server2; + + private String locators; + + @Override + public final void postSetUp() throws Exception { + Host host = Host.getHost(0); + locator = host.getVM(0); + server1 = host.getVM(1); + server2 = host.getVM(2); + + int locatorPort = AvailablePort.getRandomAvailablePort(AvailablePort.SOCKET); + locators = NetworkUtils.getServerHostName(host) + "[" + locatorPort + "]"; + + locator.invoke(() -> { + spySecurityManager = new SpySecurityManager(); + + DistributedTestUtils.deleteLocatorStateFile(locatorPort); + + final Properties properties = createProperties(locators); + properties.setProperty(SampleSecurityManager.SECURITY_JSON, "com/gemstone/gemfire/security/peerAuth.json"); + properties.setProperty(UserPasswordAuthInit.USER_NAME, "locator1"); + properties.setProperty(UserPasswordAuthInit.PASSWORD, "1234567"); + properties.setProperty(START_LOCATOR, locators); + + getSystem(properties); + getCache(); + }); + + server1.invoke(()-> { + spySecurityManager = new SpySecurityManager(); + + final Properties properties = createProperties(locators); + properties.setProperty(SampleSecurityManager.SECURITY_JSON, "com/gemstone/gemfire/security/peerAuth.json"); + properties.setProperty(UserPasswordAuthInit.USER_NAME, "server1"); + properties.setProperty(UserPasswordAuthInit.PASSWORD, "1234567"); + + getSystem(properties); + getCache(); + }); + + server2.invoke(()-> { + spySecurityManager = new SpySecurityManager(); + + final Properties properties = createProperties(locators); + properties.setProperty(SampleSecurityManager.SECURITY_JSON, "com/gemstone/gemfire/security/peerAuth.json"); + properties.setProperty(UserPasswordAuthInit.USER_NAME, "server2"); + properties.setProperty(UserPasswordAuthInit.PASSWORD, "1234567"); + + getSystem(properties); + getCache(); + }); + } + + @Test + public void initAndCloseTest() throws Exception { + spySecurityManager = new SpySecurityManager(); + + final Properties properties = createProperties(locators); + properties.setProperty(SampleSecurityManager.SECURITY_JSON, "com/gemstone/gemfire/security/peerAuth.json"); + properties.setProperty(UserPasswordAuthInit.USER_NAME, "stranger"); + properties.setProperty(UserPasswordAuthInit.PASSWORD, "1234567"); + + assertThatThrownBy(() -> getSystem(properties)).isExactlyInstanceOf(AuthenticationFailedException.class); + } + + @Override + public void postTearDownCacheTestCase() throws Exception { + closeAllCache(); + spySecurityManager = null; + invokeInEveryVM(() -> { spySecurityManager = null; }); + } + + private static Properties createProperties(String locators) { + Properties allProperties = new Properties(); + allProperties.setProperty(LOCATORS, locators); + allProperties.setProperty(MCAST_PORT, "0"); + allProperties.setProperty(SECURITY_MANAGER, SpySecurityManager.class.getName()); + allProperties.setProperty(SECURITY_PEER_AUTH_INIT, UserPasswordAuthInit.class.getName() + ".create"); + allProperties.setProperty(USE_CLUSTER_CONFIGURATION, "false"); + return allProperties; + } + + public static class SpySecurityManager extends SampleSecurityManager { + + static int initInvoked = 0; + static int closeInvoked = 0; + + @Override + public void init(final Properties securityProps) { + initInvoked++; + super.init(securityProps); + } + + @Override + public void close() { + closeInvoked++; + super.close(); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9d7a6960/geode-core/src/test/java/org/apache/geode/security/NoShowValue1PostProcessor.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/NoShowValue1PostProcessor.java b/geode-core/src/test/java/org/apache/geode/security/NoShowValue1PostProcessor.java new file mode 100644 index 0000000..d2adffd --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/security/NoShowValue1PostProcessor.java @@ -0,0 +1,36 @@ +/* + * 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 com.gemstone.gemfire.security; + +import java.io.Serializable; + +import org.apache.geode.security.PostProcessor; + +public class NoShowValue1PostProcessor implements PostProcessor { + + @Override + public Object processRegionValue(final Object principal, + final String regionName, + final Object key, + final Object value) { + if (value.equals("value1")) { + return null; + } else { + return value; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9d7a6960/geode-core/src/test/java/org/apache/geode/security/NoShowValue1PostProcessorDUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/NoShowValue1PostProcessorDUnitTest.java b/geode-core/src/test/java/org/apache/geode/security/NoShowValue1PostProcessorDUnitTest.java new file mode 100644 index 0000000..5d071a8 --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/security/NoShowValue1PostProcessorDUnitTest.java @@ -0,0 +1,86 @@ +/* + * 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 com.gemstone.gemfire.security; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.gemstone.gemfire.cache.Region; +import com.gemstone.gemfire.cache.client.ClientCache; +import com.gemstone.gemfire.cache.client.Pool; +import com.gemstone.gemfire.cache.client.PoolManager; +import com.gemstone.gemfire.cache.query.SelectResults; +import com.gemstone.gemfire.test.junit.categories.DistributedTest; +import com.gemstone.gemfire.test.junit.categories.SecurityTest; + +@Category({ DistributedTest.class, SecurityTest.class }) +public class NoShowValue1PostProcessorDUnitTest extends AbstractSecureServerDUnitTest { + + public NoShowValue1PostProcessorDUnitTest(){ + this.postProcessor = NoShowValue1PostProcessor.class; + } + + @Test + public void testPostProcess(){ + List<String> keys = new ArrayList<>(); + keys.add("key1"); + keys.add("key2"); + + client1.invoke(()->{ + ClientCache cache = createClientCache("super-user", "1234567", serverPort); + Region region = cache.getRegion(REGION_NAME); + + // post process for get + assertEquals("value3", region.get("key3")); + + assertNull(region.get("key1")); + + // post processs for getAll + Map values = region.getAll(keys); + assertEquals(2, values.size()); + assertEquals("value2", values.get("key2")); + assertNull(values.get("key1")); + + // post process for query + String query = "select * from /AuthRegion"; + SelectResults result = region.query(query); + System.out.println("query result: "+result); + assertEquals(5, result.size()); + assertTrue(result.contains("value0")); + assertFalse(result.contains("value1")); + assertTrue(result.contains("value2")); + assertTrue(result.contains("value3")); + assertTrue(result.contains("value4")); + + Pool pool = PoolManager.find(region); + result = (SelectResults)pool.getQueryService().newQuery(query).execute(); + System.out.println("query result: "+result); + assertTrue(result.contains("value0")); + assertFalse(result.contains("value1")); + assertTrue(result.contains("value2")); + assertTrue(result.contains("value3")); + assertTrue(result.contains("value4")); + }); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9d7a6960/geode-core/src/test/java/org/apache/geode/security/NotAuthorizedExceptionTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/NotAuthorizedExceptionTest.java b/geode-core/src/test/java/org/apache/geode/security/NotAuthorizedExceptionTest.java new file mode 100644 index 0000000..67dfadc --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/security/NotAuthorizedExceptionTest.java @@ -0,0 +1,200 @@ +/* + * 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 com.gemstone.gemfire.security; + +import static com.googlecode.catchexception.CatchException.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.io.NotSerializableException; +import java.io.Serializable; +import java.security.Principal; +import javax.naming.NamingException; + +import org.apache.commons.lang.SerializationUtils; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; + +import com.gemstone.gemfire.test.junit.categories.SecurityTest; +import com.gemstone.gemfire.test.junit.categories.UnitTest; + +/** + * Unit tests for {@link NotAuthorizedException}. + */ +@Category({ UnitTest.class, SecurityTest.class }) +public class NotAuthorizedExceptionTest { + + private String message; + private String causeMessage; + private Object nonSerializableResolvedObj; + private NamingException nonSerializableNamingException; + private SerializableObject serializableResolvedObj; + private NamingException serializableNamingException; + private String principalName; + private Principal nonSerializablePrincipal; + private SerializablePrincipal serializablePrincipal; + + @Rule + public TestName testName = new TestName(); + + @Before + public void setUp() throws Exception { + this.message = testName.getMethodName() + " message"; + this.causeMessage = testName.getMethodName() + " cause message"; + + this.nonSerializableResolvedObj = new Object(); + this.nonSerializableNamingException = new NamingException(this.causeMessage); + this.nonSerializableNamingException.setResolvedObj(this.nonSerializableResolvedObj); + + this.serializableResolvedObj = new SerializableObject(this.testName.getMethodName()); + this.serializableNamingException = new NamingException(this.causeMessage); + this.serializableNamingException.setResolvedObj(this.serializableResolvedObj); + + this.principalName = "jsmith"; + this.nonSerializablePrincipal = mock(Principal.class); + this.serializablePrincipal = new SerializablePrincipal(this.principalName); + + assertPreconditions(); + } + + private void assertPreconditions() { + catchException(this).clone(this.nonSerializableNamingException); + assertThat((Throwable)caughtException()).isNotNull(); + assertThat((Throwable)caughtException().getCause()).isInstanceOf(NotSerializableException.class); + + catchException(this).clone(this.serializableNamingException); + assertThat((Throwable)caughtException()).isNull(); + + assertThat(this.nonSerializableResolvedObj).isNotInstanceOf(Serializable.class); + + catchException(this).clone(this.serializableResolvedObj); + assertThat((Throwable)caughtException()).isNull(); + + assertThat(this.nonSerializablePrincipal).isNotInstanceOf(Serializable.class); + + catchException(this).clone(this.serializablePrincipal); + assertThat((Throwable)caughtException()).isNull(); + } + + @Test + public void isSerializable() throws Exception { + assertThat(NotAuthorizedException.class).isInstanceOf(Serializable.class); + } + + @Test + public void serializes() throws Exception { + NotAuthorizedException instance = new NotAuthorizedException(this.message); + + NotAuthorizedException cloned = (NotAuthorizedException) SerializationUtils.clone(instance); + + assertThat(cloned).hasMessage(this.message); + } + + @Test + public void serializesWithThrowable() throws Exception { + Throwable cause = new Exception(this.causeMessage); + NotAuthorizedException instance = new NotAuthorizedException(this.message, cause); + + NotAuthorizedException cloned = (NotAuthorizedException) SerializationUtils.clone(instance); + + assertThat(cloned).hasMessage(this.message); + assertThat(cloned).hasCause(cause); + } + + @Test + public void serializesWithNonSerializablePrincipal() throws Exception { + NotAuthorizedException instance = new NotAuthorizedException(this.message, this.nonSerializablePrincipal); + assertThat(instance.getPrincipal()).isNotNull(); + + NotAuthorizedException cloned = (NotAuthorizedException) SerializationUtils.clone(instance); + + assertThat(cloned).hasMessage(this.message); + assertThat(cloned.getPrincipal()).isNull(); + } + + @Test + public void serializesWithSerializablePrincipal() throws Exception { + NotAuthorizedException instance = new NotAuthorizedException(this.message, this.serializablePrincipal); + + NotAuthorizedException cloned = (NotAuthorizedException) SerializationUtils.clone(instance); + + assertThat(cloned).hasMessage(this.message); + assertThat(cloned.getPrincipal()).isNotNull().isEqualTo(this.serializablePrincipal); + } + + public Object clone(final Serializable object) { + return SerializationUtils.clone(object); + } + + public static class SerializableObject implements Serializable { + + private String name; + + SerializableObject(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SerializableObject that = (SerializableObject) o; + + return name != null ? name.equals(that.name) : that.name == null; + + } + + @Override + public int hashCode() { + return name != null ? name.hashCode() : 0; + } + } + + public static class SerializablePrincipal implements Principal, Serializable { + + private String name; + + SerializablePrincipal(String name) { + this.name = name; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SerializablePrincipal that = (SerializablePrincipal) o; + + return name != null ? name.equals(that.name) : that.name == null; + + } + + @Override + public int hashCode() { + return name != null ? name.hashCode() : 0; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9d7a6960/geode-core/src/test/java/org/apache/geode/security/P2PAuthenticationDUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/P2PAuthenticationDUnitTest.java b/geode-core/src/test/java/org/apache/geode/security/P2PAuthenticationDUnitTest.java new file mode 100644 index 0000000..cb1836e --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/security/P2PAuthenticationDUnitTest.java @@ -0,0 +1,541 @@ +/* + * 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 com.gemstone.gemfire.security; + +import com.gemstone.gemfire.distributed.ConfigurationProperties; +import com.gemstone.gemfire.distributed.DistributedSystem; +import com.gemstone.gemfire.distributed.Locator; +import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem; +import com.gemstone.gemfire.distributed.internal.membership.MembershipManager; +import com.gemstone.gemfire.distributed.internal.membership.gms.MembershipManagerHelper; +import com.gemstone.gemfire.security.generator.CredentialGenerator; +import com.gemstone.gemfire.security.generator.DummyCredentialGenerator; +import com.gemstone.gemfire.security.generator.LdapUserCredentialGenerator; +import com.gemstone.gemfire.security.generator.UserPasswordWithExtraPropsAuthInit; +import com.gemstone.gemfire.security.templates.LdapUserAuthenticator; +import com.gemstone.gemfire.security.templates.UserPasswordAuthInit; +import com.gemstone.gemfire.test.dunit.Host; +import com.gemstone.gemfire.test.dunit.VM; +import com.gemstone.gemfire.test.dunit.internal.JUnit4DistributedTestCase; +import com.gemstone.gemfire.test.junit.categories.DistributedTest; +import com.gemstone.gemfire.test.junit.categories.FlakyTest; +import com.gemstone.gemfire.test.junit.categories.SecurityTest; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import javax.net.ssl.SSLHandshakeException; +import java.util.Properties; + +import static com.gemstone.gemfire.distributed.ConfigurationProperties.*; +import static com.gemstone.gemfire.internal.AvailablePort.SOCKET; +import static com.gemstone.gemfire.internal.AvailablePort.getRandomAvailablePort; +import static com.gemstone.gemfire.security.SecurityTestUtils.startLocator; +import static com.gemstone.gemfire.security.SecurityTestUtils.stopLocator; +import static com.gemstone.gemfire.test.dunit.Assert.*; +import static com.gemstone.gemfire.test.dunit.IgnoredException.addIgnoredException; +import static com.gemstone.gemfire.test.dunit.NetworkUtils.getIPLiteral; +import static com.gemstone.gemfire.test.dunit.Wait.pause; + +/** + * Tests peer to peer authentication in Gemfire + * + * @since GemFire 5.5 + */ +@Category({ DistributedTest.class, SecurityTest.class }) +public class P2PAuthenticationDUnitTest extends JUnit4DistributedTestCase { + + private static VM locatorVM = null; + + private static final String[] ignoredExceptions = { + AuthenticationRequiredException.class.getName(), + AuthenticationFailedException.class.getName(), + GemFireSecurityException.class.getName(), + SSLHandshakeException.class.getName(), + ClassNotFoundException.class.getName(), + "Authentication failed for", + "Failed to obtain credentials" + }; + + @Override + public final void postSetUp() throws Exception { + disconnectAllFromDS(); + locatorVM = Host.getHost(0).getVM(0); + for (String exceptionString : ignoredExceptions) { + addIgnoredException(exceptionString); + } + } + + /** + * Check that mcast-port setting for discovery or with locator are + * incompatible with security + */ + @Test + public void testIllegalPropertyCombos() throws Exception { + int port = getRandomAvailablePort(SOCKET); + + Properties props = new Properties(); + props.setProperty(MCAST_PORT, "26753"); + props.setProperty(ConfigurationProperties.LOCATORS, getIPLiteral() + "[" + port + "]"); + props.setProperty(ConfigurationProperties.SECURITY_PEER_AUTH_INIT, UserPasswordAuthInit.class.getName() + ".create"); + props.setProperty(ConfigurationProperties.ENABLE_CLUSTER_CONFIGURATION, "false"); + + try { + Locator.startLocatorAndDS(port, null, null, props); + fail("Expected an IllegalArgumentException while starting locator"); + + } catch (IllegalArgumentException ex) { + // success + } + + // Also try setting the authenticator + props = new Properties(); + props.setProperty(MCAST_PORT, "26753"); + props.setProperty(LOCATORS, getIPLiteral() + "[" + port + "]"); + props.setProperty(SECURITY_PEER_AUTHENTICATOR, LdapUserAuthenticator.class.getName() + ".create"); + props.setProperty(ENABLE_CLUSTER_CONFIGURATION, "false"); + + try { + Locator.startLocatorAndDS(port, null, null, props); + fail("Expected an IllegalArgumentException while starting locator"); + + } catch (IllegalArgumentException expected) { + // success + } + + props = new Properties(); + props.setProperty(MCAST_PORT, "26753"); + props.setProperty(SECURITY_PEER_AUTH_INIT, UserPasswordAuthInit.class.getName() + ".create"); + + try { + getSystem(props); + fail("Expected an IllegalArgumentException while connection to DS"); + + } catch (IllegalArgumentException expected) { + // success + } + + // Also try setting the authenticator + props = new Properties(); + props.setProperty(MCAST_PORT, "26753"); + props.setProperty(SECURITY_PEER_AUTHENTICATOR, LdapUserAuthenticator.class.getName() + ".create"); + + try { + getSystem(props); + fail("Expected an IllegalArgumentException while connection to DS"); + + } catch (IllegalArgumentException expected) { + // success + } + } + + /** + * AuthInitialize is incorrect + */ + @Test + public void testP2PAuthenticationWithInvalidAuthInitialize() throws Exception { + int locatorPort = getRandomAvailablePort(SOCKET); + + CredentialGenerator gen = new DummyCredentialGenerator(); + assertNotNull(gen.getAuthenticator()); + assertNull(gen.getJavaProperties()); + + Properties props = new Properties(); + props.setProperty(MCAST_PORT, "0"); + props.setProperty(LOCATORS, getIPLiteral() + "[" + locatorPort + "]"); + props.setProperty(SECURITY_PEER_AUTH_INIT, "Incorrect_AuthInitialize"); + props.setProperty(SECURITY_PEER_AUTHENTICATOR, gen.getAuthenticator()); + + startTheLocator(props, gen.getJavaProperties(), locatorPort); + + try { + new SecurityTestUtils("tmp").createSystem(props, null); + fail("AuthenticationFailedException was expected as the AuthInitialize object passed is incorrect"); + + } catch (AuthenticationFailedException expected) { + // success + + } finally { + locatorVM.invoke(() -> stopLocator(locatorPort, ignoredExceptions)); + } + } + + /** + * Authenticator is incorrect + */ + @Category(FlakyTest.class) // GEODE-1089: random port + @Test + public void testP2PAuthenticationWithInvalidAuthenticator() throws Exception { + int locatorPort = getRandomAvailablePort(SOCKET); + + CredentialGenerator gen = new DummyCredentialGenerator(); + assertNotNull(gen.getAuthInit()); + assertNull(gen.getJavaProperties()); + + Properties props = new Properties(); + props.setProperty(MCAST_PORT, "0"); + props.setProperty(LOCATORS, getIPLiteral() + "[" + locatorPort + "]"); + props.setProperty(SECURITY_PEER_AUTH_INIT, gen.getAuthInit()); + props.setProperty(SECURITY_PEER_AUTHENTICATOR, "xyz"); + + startTheLocator(props, null, locatorPort); + + try { + new SecurityTestUtils("tmp").createSystem(props, null); + fail("AuthenticationFailedException was expected as the Authenticator object passed is incorrect"); + + } catch (AuthenticationFailedException expected) { + // success + + } finally { + locatorVM.invoke(() -> stopLocator(locatorPort, ignoredExceptions)); + } + } + + @Category(FlakyTest.class) // GEODE-1091: random port + @Test + public void testP2PAuthenticationWithNoCredentials() throws Exception { + int locatorPort = getRandomAvailablePort(SOCKET); + + CredentialGenerator gen = new DummyCredentialGenerator(); + assertNotNull(gen.getAuthenticator()); + assertNotNull(gen.getAuthInit()); + assertNull(gen.getJavaProperties()); + assertNull(gen.getSystemProperties()); + + Properties props = new Properties(); + props.setProperty(MCAST_PORT, "0"); + props.setProperty(LOCATORS, getIPLiteral() + "[" + locatorPort + "]"); + props.setProperty(SECURITY_PEER_AUTH_INIT, gen.getAuthInit()); + props.setProperty(SECURITY_PEER_AUTHENTICATOR, gen.getAuthenticator()); + + startTheLocator(props, null, locatorPort); + + try { + new SecurityTestUtils("tmp").createSystem(props, null); + fail("AuthenticationFailedException was expected as no credentials are set"); + + } catch (AuthenticationFailedException expected) { + // success + + } finally { + locatorVM.invoke(() -> stopLocator(locatorPort, ignoredExceptions)); + } + } + + @Test + public void testP2PAuthenticationWithValidCredentials() throws Exception { + int locatorPort = getRandomAvailablePort(SOCKET); + + CredentialGenerator gen = new DummyCredentialGenerator(); + assertNotNull(gen.getAuthenticator()); + assertNotNull(gen.getAuthInit()); + assertNull(gen.getJavaProperties()); + assertNull(gen.getSystemProperties()); + assertNotNull(gen.getValidCredentials(1)); + + Properties props = new Properties(); + props.setProperty(MCAST_PORT, "0"); + props.setProperty(LOCATORS, getIPLiteral() + "[" + locatorPort + "]"); + props.setProperty(SECURITY_PEER_AUTH_INIT, gen.getAuthInit()); + props.setProperty(SECURITY_PEER_AUTHENTICATOR, gen.getAuthenticator()); + props.putAll(gen.getValidCredentials(1)); + + startTheLocator(props, gen.getJavaProperties(), locatorPort); + + try { + createDS(props, gen.getJavaProperties()); + verifyMembers(2); + disconnectFromDS(); + + } finally { + locatorVM.invoke(() -> stopLocator(locatorPort, ignoredExceptions)); + } + } + + @Test + public void testP2PAuthenticationWithBothValidAndInValidCredentials() throws Exception { + addIgnoredException("Authentication failed"); + + int locatorPort = getRandomAvailablePort(SOCKET); + + CredentialGenerator gen = new DummyCredentialGenerator(); + assertNotNull(gen.getAuthenticator()); + assertNotNull(gen.getAuthInit()); + assertNotNull(gen.getInvalidCredentials(1)); + assertNull(gen.getJavaProperties()); + assertNull(gen.getSystemProperties()); + assertNotNull(gen.getValidCredentials(1)); + assertNotNull(gen.getValidCredentials(3)); + + Properties props = new Properties(); + props.setProperty(MCAST_PORT, "0"); + props.setProperty(LOCATORS, getIPLiteral() + "[" + locatorPort + "]"); + props.setProperty(SECURITY_PEER_AUTH_INIT, gen.getAuthInit()); + props.setProperty(SECURITY_PEER_AUTHENTICATOR, gen.getAuthenticator()); + props.putAll(gen.getValidCredentials(1)); + + startTheLocator(props, null, locatorPort); + + try { + // invalid credentials for the peer + props.putAll(gen.getInvalidCredentials(1)); + + try { + new SecurityTestUtils("tmp").createSystem(props, null); + fail("AuthenticationFailedException was expected as wrong credentials were passed"); + + } catch (AuthenticationFailedException expected) { + // success + } + + props.putAll(gen.getValidCredentials(3)); + + createDS(props, null); + verifyMembers(2); + disconnectFromDS(); + + } finally { + locatorVM.invoke(() -> stopLocator(locatorPort, ignoredExceptions)); + } + } + + /** + * The strategy is to test view change reject by having two different + * authenticators on different VMs. + * + * Here locator will accept the credentials from peer2 but the first peer will + * reject them due to different authenticator. Hence the number of members + * reported by the first peer should be only two while others will report as + * three. + */ + @Ignore("disabled for some reason?") + @Test + public void testP2PViewChangeReject() throws Exception { + final Host host = Host.getHost(0); + final VM peer2 = host.getVM(1); + final VM peer3 = host.getVM(2); + + CredentialGenerator gen = new LdapUserCredentialGenerator(); + gen.init(); + Properties extraProps = gen.getSystemProperties(); + String authenticator = gen.getAuthenticator(); + String authInit = gen.getAuthInit(); + + if (extraProps == null) { + extraProps = new Properties(); + } + + CredentialGenerator gen2 = new DummyCredentialGenerator(); + gen2.init(); + Properties extraProps2 = gen2.getSystemProperties(); + String authenticator2 = gen2.getAuthenticator(); + + if (extraProps2 == null) { + extraProps2 = new Properties(); + } + + // Start the locator with the LDAP authenticator + Properties props = new Properties(); + int port = getRandomAvailablePort(SOCKET); + final String locators = getIPLiteral() +"["+port+"]"; + + props.setProperty(SECURITY_PEER_AUTH_INIT, authInit); + props.setProperty(SECURITY_PEER_AUTHENTICATOR, authenticator); + Properties credentials = gen.getValidCredentials(1); + Properties javaProps = gen.getJavaProperties(); + props.putAll(credentials); + props.putAll(extraProps); + + startTheLocator(props, javaProps, port); + + try { + + // Start the first peer with different authenticator + props = new Properties(); + props.setProperty(MCAST_PORT, "0"); + props.setProperty(LOCATORS, locators); + props.setProperty(SECURITY_PEER_AUTH_INIT, authInit); + props.setProperty(SECURITY_PEER_AUTHENTICATOR, authenticator2); + + credentials = gen.getValidCredentials(3); + Properties javaProps2 = gen2.getJavaProperties(); + props.putAll(credentials); + props.putAll(extraProps2); + + createDS(props, javaProps2); + + // Start the second peer with the same authenticator as locator + props = new Properties(); + props.setProperty(MCAST_PORT, "0"); + props.setProperty(LOCATORS, locators); + props.setProperty(SECURITY_PEER_AUTH_INIT, authInit); + props.setProperty(SECURITY_PEER_AUTHENTICATOR, authenticator); + + credentials = gen.getValidCredentials(7); + javaProps = gen.getJavaProperties(); + props.putAll(credentials); + props.putAll(extraProps); + + createDS(peer2, props, javaProps); + + createDS(peer3, props, javaProps); + + // wait for view propagation + pause(2000); + + // Verify the number of members on all peers and locator + locatorVM.invoke(() -> verifyMembers(4)); + verifyMembers(2); + peer2.invoke(() -> verifyMembers(4)); + peer3.invoke(() -> verifyMembers(4)); + + // Disconnect the first peer and check again + disconnectFromDS(); + pause(2000); + + locatorVM.invoke(() -> verifyMembers(3)); + peer2.invoke(() -> verifyMembers(3)); + peer3.invoke(() -> verifyMembers(3)); + + // Disconnect the second peer and check again + peer2.invoke(() -> disconnectFromDS()); + pause(2000); + + locatorVM.invoke(() -> verifyMembers(2)); + peer3.invoke(() -> verifyMembers(2)); + + // Same for last peer + peer3.invoke(() -> disconnectFromDS()); + pause(2000); + + locatorVM.invoke(() -> verifyMembers(1)); + + } finally { + locatorVM.invoke(() -> stopLocator(port, ignoredExceptions)); + } + } + + /** + * The strategy is to test credential size greater than UDP datagram size. + * + * Here locator will accept the credentials from peer2 and the large credential + * from the first peer. Number of members in the DS + * should be four + */ + @Test + public void testP2PLargeCredentialSucceeds() throws Exception { + int locatorPort = getRandomAvailablePort(SOCKET); + + final Host host = Host.getHost(0); + final VM peer2 = host.getVM(1); + final VM peer3 = host.getVM(2); + + CredentialGenerator gen = new DummyCredentialGenerator(); + gen.init(); + + assertNotNull(gen.getAuthenticator()); + assertNull(gen.getJavaProperties()); + assertNull(gen.getSystemProperties()); + assertNotNull(gen.getValidCredentials(1)); + + String authInit = UserPasswordWithExtraPropsAuthInit.class.getName() + ".create"; + Properties credentials = gen.getValidCredentials(1); + + Properties props = new Properties(); + props.setProperty(SECURITY_PEER_AUTH_INIT, authInit); + props.setProperty(SECURITY_PEER_AUTHENTICATOR, gen.getAuthenticator()); + props.putAll(credentials); + + startTheLocator(props, null, locatorPort); + + try { + // Start the first peer with huge credentials + props = new Properties(); + props.setProperty(MCAST_PORT, "0"); + props.setProperty(LOCATORS, getIPLiteral() + "[" + locatorPort + "]"); + props.setProperty(SECURITY_PEER_AUTH_INIT, authInit); + props.setProperty(SECURITY_PEER_AUTHENTICATOR, gen.getAuthenticator()); + + String hugeStr = "20KString"; + for (int i = 0; i <= 20000; i++) { + hugeStr += "A"; + } + + credentials = gen.getValidCredentials(3); + credentials.setProperty("security-keep-extra-props", "-"); + credentials.setProperty("security-hugeentryone", hugeStr); + credentials.setProperty("security-hugeentrytwo", hugeStr); + credentials.setProperty("security-hugeentrythree", hugeStr); + + props.putAll(credentials); + + createDS(props, null); + // fail("AuthenticationFailedException was expected as credentials were passed beyond 50k"); --? + + // Start the second peer with the same authenticator as locator + props = new Properties(); + props.setProperty(MCAST_PORT, "0"); + props.setProperty(LOCATORS, getIPLiteral() + "[" + locatorPort + "]"); + props.setProperty(SECURITY_PEER_AUTH_INIT, authInit); + props.setProperty(SECURITY_PEER_AUTHENTICATOR, gen.getAuthenticator()); + + credentials = gen.getValidCredentials(7); + props.putAll(credentials); + + createDS(peer2, props, null); + createDS(peer3, props, null); + + // wait for view propagation + pause(2000); + + // Verify the number of members on all peers and locator + locatorVM.invoke(() -> verifyMembers(4)); + peer2.invoke(() -> verifyMembers(4)); + peer3.invoke(() -> verifyMembers(4)); + + // Disconnect the peers + disconnectFromDS(); + peer2.invoke(() -> disconnectFromDS()); + peer3.invoke(() -> disconnectFromDS()); + + } finally { + locatorVM.invoke(() -> stopLocator(locatorPort, ignoredExceptions)); + } + } + + private void createDS(final VM peer2, final Properties props, final Properties javaProps) { + peer2.invoke(() -> createDS(props, javaProps)); + } + + private void startTheLocator(final Properties props, final Properties javaProps, final int port) { + locatorVM.invoke(() -> startLocator(getUniqueName(), port, props, javaProps, ignoredExceptions)); + } + + private static void createDS(final Properties props, final Properties javaProps) { + SecurityTestUtils tmpUtil = new SecurityTestUtils("tmp"); + tmpUtil.createSystem(props, javaProps); + } + + private static void verifyMembers(final int numExpectedMembers) { + DistributedSystem ds = InternalDistributedSystem.getAnyInstance(); + MembershipManager mgr = MembershipManagerHelper.getMembershipManager(ds); + assertEquals(numExpectedMembers, mgr.getView().size()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9d7a6960/geode-core/src/test/java/org/apache/geode/security/PDXGfshPostProcessorOnRemoteServerTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/PDXGfshPostProcessorOnRemoteServerTest.java b/geode-core/src/test/java/org/apache/geode/security/PDXGfshPostProcessorOnRemoteServerTest.java new file mode 100644 index 0000000..81b3add --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/security/PDXGfshPostProcessorOnRemoteServerTest.java @@ -0,0 +1,159 @@ +/* + * 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 com.gemstone.gemfire.security; + +import static com.gemstone.gemfire.distributed.ConfigurationProperties.*; +import static org.junit.Assert.*; + +import java.io.File; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + +import com.jayway.awaitility.Awaitility; +import org.apache.geode.security.templates.SampleSecurityManager; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.gemstone.gemfire.cache.Cache; +import com.gemstone.gemfire.cache.CacheFactory; +import com.gemstone.gemfire.cache.Region; +import com.gemstone.gemfire.cache.RegionShortcut; +import com.gemstone.gemfire.cache.server.CacheServer; +import com.gemstone.gemfire.distributed.Locator; +import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem; +import com.gemstone.gemfire.internal.AvailablePortHelper; +import com.gemstone.gemfire.internal.security.SecurityService; +import com.gemstone.gemfire.management.ManagementService; +import com.gemstone.gemfire.management.cli.Result.Status; +import com.gemstone.gemfire.management.internal.cli.CliUtil; +import com.gemstone.gemfire.management.internal.cli.HeadlessGfsh; +import com.gemstone.gemfire.management.internal.cli.i18n.CliStrings; +import com.gemstone.gemfire.management.internal.cli.result.CommandResult; +import com.gemstone.gemfire.management.internal.cli.util.CommandStringBuilder; +import com.gemstone.gemfire.pdx.SimpleClass; +import com.gemstone.gemfire.security.templates.UserPasswordAuthInit; +import com.gemstone.gemfire.test.dunit.Host; +import com.gemstone.gemfire.test.dunit.VM; +import com.gemstone.gemfire.test.dunit.internal.JUnit4DistributedTestCase; +import com.gemstone.gemfire.test.junit.categories.DistributedTest; +import com.gemstone.gemfire.test.junit.categories.SecurityTest; + +@Category({ DistributedTest.class, SecurityTest.class }) +public class PDXGfshPostProcessorOnRemoteServerTest extends JUnit4DistributedTestCase { + protected static final String REGION_NAME = "AuthRegion"; + protected VM locator = null; + protected VM server = null; + + @Before + public void before() throws Exception { + final Host host = Host.getHost(0); + this.locator = host.getVM(0); + this.server = host.getVM(1); + } + + @Test + public void testGfshCommand() throws Exception{ + // set up locator with security + int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2); + int locatorPort = ports[0]; + int jmxPort = ports[1]; + locator.invoke(()->{ + Properties props = new Properties(); + props.setProperty(SampleSecurityManager.SECURITY_JSON, "com/gemstone/gemfire/management/internal/security/clientServer.json"); + props.setProperty(SECURITY_MANAGER, SampleSecurityManager.class.getName()); + props.setProperty(MCAST_PORT, "0"); + props.put(JMX_MANAGER, "true"); + props.put(JMX_MANAGER_START, "true"); + props.put(JMX_MANAGER_PORT, jmxPort+""); + props.setProperty(SECURITY_POST_PROCESSOR, PDXPostProcessor.class.getName()); + Locator.startLocatorAndDS(locatorPort, new File("locator.log"), props); + }); + + // set up server with security + String locators = "localhost[" + locatorPort + "]"; + server.invoke(()->{ + Properties props = new Properties(); + props.setProperty(MCAST_PORT, "0"); + props.setProperty(LOCATORS, locators); + props.setProperty(SECURITY_MANAGER, SampleSecurityManager.class.getName()); + props.setProperty(SampleSecurityManager.SECURITY_JSON, "com/gemstone/gemfire/management/internal/security/clientServer.json"); + props.setProperty(SECURITY_POST_PROCESSOR, PDXPostProcessor.class.getName()); + + // the following are needed for peer-to-peer authentication + props.setProperty(SECURITY_PEER_AUTH_INIT, UserPasswordAuthInit.class.getName()); + props.setProperty("security-username", "super-user"); + props.setProperty("security-password", "1234567"); + InternalDistributedSystem ds = getSystem(props); + + Cache cache = CacheFactory.create(ds); + Region region = cache.createRegionFactory(RegionShortcut.REPLICATE).create(REGION_NAME); + + CacheServer server = cache.addCacheServer(); + server.setPort(0); + server.start(); + + for(int i=0; i<5; i++){ + SimpleClass obj = new SimpleClass(i, (byte)i); + region.put("key"+i, obj); + } + }); + + // wait until the region bean is visible + locator.invoke(()->{ + Awaitility.await().pollInterval(500, TimeUnit.MICROSECONDS).atMost(5, TimeUnit.SECONDS).until(()->{ + Cache cache = CacheFactory.getAnyInstance(); + Object bean = ManagementService.getManagementService(cache).getDistributedRegionMXBean("/"+REGION_NAME); + return bean != null; + }); + }); + + // run gfsh command in this vm + CliUtil.isGfshVM = true; + String shellId = getClass().getSimpleName(); + HeadlessGfsh gfsh = new HeadlessGfsh(shellId, 30, "gfsh_files"); + + // connect to the jmx server + final CommandStringBuilder connectCommand = new CommandStringBuilder(CliStrings.CONNECT); + connectCommand.addOption(CliStrings.CONNECT__USERNAME, "dataUser"); + connectCommand.addOption(CliStrings.CONNECT__PASSWORD, "1234567"); + + String endpoint = "localhost[" + jmxPort + "]"; + connectCommand.addOption(CliStrings.CONNECT__JMX_MANAGER, endpoint); + + gfsh.executeCommand(connectCommand.toString()); + CommandResult result = (CommandResult)gfsh.getResult(); + + // get command + gfsh.executeCommand("get --key=key1 --region=AuthRegion"); + result = (CommandResult) gfsh.getResult(); + assertEquals(result.getStatus(), Status.OK); + assertTrue(result.getContent().toString().contains(SimpleClass.class.getName())); + + gfsh.executeCommand("query --query=\"select * from /AuthRegion\""); + result = (CommandResult)gfsh.getResult(); + + CliUtil.isGfshVM = false; + server.invoke(()-> { + PDXPostProcessor pp = (PDXPostProcessor) SecurityService.getSecurityService().getPostProcessor(); + // verify that the post processor is called 6 times. (5 for the query, 1 for the get) + assertEquals(pp.getCount(), 6); + }); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9d7a6960/geode-core/src/test/java/org/apache/geode/security/PDXPostProcessor.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/PDXPostProcessor.java b/geode-core/src/test/java/org/apache/geode/security/PDXPostProcessor.java new file mode 100644 index 0000000..0b03b66 --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/security/PDXPostProcessor.java @@ -0,0 +1,60 @@ +/* + * 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 com.gemstone.gemfire.security; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.Properties; + +import org.apache.geode.security.PostProcessor; + +import com.gemstone.gemfire.pdx.SimpleClass; +import com.gemstone.gemfire.pdx.internal.PdxInstanceImpl; + +public class PDXPostProcessor implements PostProcessor{ + public static byte[] BYTES = {1,0}; + + private boolean pdx = false; + private int count = 0; + + public void init(Properties props){ + pdx = Boolean.parseBoolean(props.getProperty("security-pdx")); + count = 0; + } + @Override + public Object processRegionValue(final Object principal, + final String regionName, + final Object key, + final Object value) { + count ++; + if(value instanceof byte[]){ + assertTrue(Arrays.equals(BYTES, (byte[])value)); + } + else if(pdx){ + assertTrue(value instanceof PdxInstanceImpl); + } + else { + assertTrue(value instanceof SimpleClass); + } + return value; + } + + public int getCount(){ + return count; + } +}
