| /* |
| * 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 static org.apache.geode.cache.Region.SEPARATOR; |
| import static org.apache.geode.security.SecurityTestUtils.NOTAUTHZ_EXCEPTION; |
| import static org.apache.geode.security.SecurityTestUtils.NO_EXCEPTION; |
| import static org.apache.geode.security.SecurityTestUtils.OTHER_EXCEPTION; |
| import static org.apache.geode.security.SecurityTestUtils.closeCache; |
| import static org.apache.geode.security.SecurityTestUtils.concatProperties; |
| import static org.apache.geode.security.SecurityTestUtils.createCacheClient; |
| import static org.apache.geode.test.dunit.Assert.fail; |
| import static org.apache.geode.test.dunit.IgnoredException.addIgnoredException; |
| import static org.apache.geode.test.dunit.LogWriterUtils.getLogWriter; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Properties; |
| import java.util.Random; |
| |
| import org.junit.Test; |
| import org.junit.experimental.categories.Category; |
| |
| import org.apache.geode.DeltaTestImpl; |
| import org.apache.geode.cache.operations.OperationContext.OperationCode; |
| import org.apache.geode.internal.AvailablePortHelper; |
| import org.apache.geode.internal.cache.TestObjectWithIdentifier; |
| import org.apache.geode.security.generator.AuthzCredentialGenerator; |
| import org.apache.geode.security.generator.CredentialGenerator; |
| import org.apache.geode.test.dunit.VM; |
| import org.apache.geode.test.junit.categories.SecurityTest; |
| |
| /** |
| * @since GemFire 6.1 |
| */ |
| @Category({SecurityTest.class}) |
| public class DeltaClientPostAuthorizationDUnitTest extends ClientAuthorizationTestCase { |
| |
| private static final int PAUSE = 5 * 1000; // TODO: replace with Awaitility |
| |
| private final DeltaTestImpl[] deltas = new DeltaTestImpl[8]; |
| |
| @Override |
| public final void preSetUpClientAuthorizationTestBase() throws Exception { |
| setUpDeltas(); |
| addIgnoredException("Unexpected IOException"); |
| addIgnoredException("SocketException"); |
| } |
| |
| @Override |
| public final void preTearDownClientAuthorizationTestBase() throws Exception { |
| closeCache(); |
| } |
| |
| @Test |
| public void testPutPostOpNotifications() throws Exception { |
| OperationWithAction[] allOps = allOps(); |
| |
| AuthzCredentialGenerator gen = getXmlAuthzGenerator(); |
| CredentialGenerator cGen = gen.getCredentialGenerator(); |
| Properties extraAuthProps = cGen.getSystemProperties(); |
| Properties javaProps = cGen.getJavaProperties(); |
| Properties extraAuthzProps = gen.getSystemProperties(); |
| String authenticator = cGen.getAuthenticator(); |
| String authInit = cGen.getAuthInit(); |
| String accessor = gen.getAuthorizationCallback(); |
| TestAuthzCredentialGenerator tgen = new TestAuthzCredentialGenerator(gen); |
| |
| getLogWriter().info("testAllOpsNotifications: Using authinit: " + authInit); |
| getLogWriter().info("testAllOpsNotifications: Using authenticator: " + authenticator); |
| getLogWriter().info("testAllOpsNotifications: Using accessor: " + accessor); |
| |
| // Start servers with all required properties |
| Properties serverProps = |
| buildProperties(authenticator, accessor, true, extraAuthProps, extraAuthzProps); |
| |
| // Get ports for the servers |
| int[] randomAvailableTCPPorts = AvailablePortHelper.getRandomAvailableTCPPorts(2); |
| int port1 = randomAvailableTCPPorts[0]; |
| int port2 = randomAvailableTCPPorts[1]; |
| |
| // Perform all the ops on the clients |
| List opBlock = new ArrayList(); |
| Random rnd = new Random(); |
| |
| for (int opNum = 0; opNum < allOps.length; ++opNum) { |
| // Start client with valid credentials as specified in OperationWithAction |
| OperationWithAction currentOp = allOps[opNum]; |
| if (currentOp.equals(OperationWithAction.OPBLOCK_END) |
| || currentOp.equals(OperationWithAction.OPBLOCK_NO_FAILOVER)) { |
| |
| // End of current operation block; execute all the operations on the servers with failover |
| if (opBlock.size() > 0) { |
| // Start the first server and execute the operation block |
| server1.invoke( |
| () -> ClientAuthorizationTestCase.createCacheServer(port1, serverProps, javaProps)); |
| server2.invoke(() -> closeCache()); |
| |
| executeOpBlock(opBlock, port1, port2, authInit, extraAuthProps, extraAuthzProps, tgen, |
| rnd); |
| |
| if (!currentOp.equals(OperationWithAction.OPBLOCK_NO_FAILOVER)) { |
| // Failover to the second server and run the block again |
| server2.invoke( |
| () -> ClientAuthorizationTestCase.createCacheServer(port2, serverProps, javaProps)); |
| server1.invoke(() -> closeCache()); |
| |
| executeOpBlock(opBlock, port1, port2, authInit, extraAuthProps, extraAuthzProps, tgen, |
| rnd); |
| } |
| |
| opBlock.clear(); |
| } |
| |
| } else { |
| currentOp.setOpNum(opNum); |
| opBlock.add(currentOp); |
| } |
| } |
| } |
| |
| @Override |
| protected void executeOpBlock(final List<OperationWithAction> opBlock, final int port1, |
| final int port2, final String authInit, final Properties extraAuthProps, |
| final Properties extraAuthzProps, final TestCredentialGenerator credentialGenerator, |
| final Random random) throws InterruptedException { |
| for (OperationWithAction currentOp : opBlock) { |
| // Start client with valid credentials as specified in OperationWithAction |
| OperationCode opCode = currentOp.getOperationCode(); |
| int opFlags = currentOp.getFlags(); |
| int clientNum = currentOp.getClientNum(); |
| VM clientVM = null; |
| boolean useThisVM = false; |
| |
| switch (clientNum) { |
| case 1: |
| clientVM = client1; |
| break; |
| case 2: |
| clientVM = client2; |
| break; |
| case 3: |
| useThisVM = true; |
| break; |
| default: |
| fail("executeOpBlock: Unknown client number " + clientNum); |
| break; |
| } |
| |
| getLogWriter().info("executeOpBlock: performing operation number [" + currentOp.getOpNum() |
| + "]: " + currentOp); |
| |
| if ((opFlags & OpFlags.USE_OLDCONN) == 0) { |
| Properties opCredentials; |
| int newRnd = random.nextInt(100) + 1; |
| String currentRegionName = SEPARATOR + regionName; |
| if ((opFlags & OpFlags.USE_SUBREGION) > 0) { |
| currentRegionName += (SEPARATOR + SUBREGION_NAME); |
| } |
| |
| String credentialsTypeStr; |
| OperationCode authOpCode = currentOp.getAuthzOperationCode(); |
| int[] indices = currentOp.getIndices(); |
| CredentialGenerator cGen = credentialGenerator.getCredentialGenerator(); |
| final Properties javaProps = cGen == null ? null : cGen.getJavaProperties(); |
| |
| if ((opFlags & OpFlags.CHECK_NOTAUTHZ) > 0 || (opFlags & OpFlags.USE_NOTAUTHZ) > 0) { |
| opCredentials = credentialGenerator.getDisallowedCredentials( |
| new OperationCode[] {authOpCode}, new String[] {currentRegionName}, indices, newRnd); |
| credentialsTypeStr = " unauthorized " + authOpCode; |
| |
| } else { |
| opCredentials = |
| credentialGenerator.getAllowedCredentials(new OperationCode[] {opCode, authOpCode}, |
| new String[] {currentRegionName}, indices, newRnd); |
| credentialsTypeStr = " authorized " + authOpCode; |
| } |
| |
| Properties clientProps = |
| concatProperties(new Properties[] {opCredentials, extraAuthProps, extraAuthzProps}); |
| |
| // Start the client with valid credentials but allowed or disallowed to perform an operation |
| getLogWriter().info("executeOpBlock: For client" + clientNum + credentialsTypeStr |
| + " credentials: " + opCredentials); |
| boolean setupDynamicRegionFactory = (opFlags & OpFlags.ENABLE_DRF) > 0; |
| if (useThisVM) { |
| createCacheClient(authInit, clientProps, javaProps, new int[] {port1, port2}, 0, |
| setupDynamicRegionFactory, NO_EXCEPTION); |
| |
| } else { |
| clientVM.invoke(() -> createCacheClient(authInit, clientProps, javaProps, |
| new int[] {port1, port2}, 0, setupDynamicRegionFactory, NO_EXCEPTION)); |
| } |
| } |
| |
| int expectedResult; |
| if ((opFlags & OpFlags.CHECK_NOTAUTHZ) > 0) { |
| expectedResult = NOTAUTHZ_EXCEPTION; |
| } else if ((opFlags & OpFlags.CHECK_EXCEPTION) > 0) { |
| expectedResult = OTHER_EXCEPTION; |
| } else { |
| expectedResult = NO_EXCEPTION; |
| } |
| |
| // Perform the operation from selected client |
| if (useThisVM) { |
| doOp(opCode, currentOp.getIndices(), opFlags, expectedResult); |
| } else { |
| int[] indices = currentOp.getIndices(); |
| clientVM.invoke(() -> DeltaClientPostAuthorizationDUnitTest.doOp(opCode, indices, |
| opFlags, expectedResult)); |
| } |
| } |
| } |
| |
| private void setUpDeltas() { |
| for (int i = 0; i < 8; i++) { |
| deltas[i] = new DeltaTestImpl(0, "0", (double) 0, new byte[0], |
| new TestObjectWithIdentifier("0", 0)); |
| } |
| deltas[1].setIntVar(5); |
| deltas[2].setIntVar(5); |
| deltas[3].setIntVar(5); |
| deltas[4].setIntVar(5); |
| deltas[5].setIntVar(5); |
| deltas[6].setIntVar(5); |
| deltas[7].setIntVar(5); |
| |
| deltas[2].resetDeltaStatus(); |
| deltas[2].setByteArr(new byte[] {1, 2, 3, 4, 5}); |
| deltas[3].setByteArr(new byte[] {1, 2, 3, 4, 5}); |
| deltas[4].setByteArr(new byte[] {1, 2, 3, 4, 5}); |
| deltas[5].setByteArr(new byte[] {1, 2, 3, 4, 5}); |
| // deltas[6].setByteArr(new byte[] { 1, 2, 3, 4, 5 }); |
| // deltas[7].setByteArr(new byte[] { 1, 2, 3, 4, 5 }); |
| |
| deltas[3].resetDeltaStatus(); |
| deltas[3].setDoubleVar(5.0); |
| deltas[4].setDoubleVar(5.0); |
| deltas[5].setDoubleVar(5.0); |
| deltas[6].setDoubleVar(5.0); |
| deltas[7].setDoubleVar(5.0); |
| |
| deltas[4].resetDeltaStatus(); |
| deltas[4].setStr("str changed"); |
| deltas[5].setStr("str changed"); |
| deltas[6].setStr("str changed"); |
| // deltas[7].setStr("str changed"); |
| |
| deltas[5].resetDeltaStatus(); |
| deltas[5].setIntVar(100); |
| deltas[5].setTestObj(new TestObjectWithIdentifier("CHANGED", 100)); |
| deltas[6].setTestObj(new TestObjectWithIdentifier("CHANGED", 100)); |
| deltas[7].setTestObj(new TestObjectWithIdentifier("CHANGED", 100)); |
| |
| deltas[6].resetDeltaStatus(); |
| deltas[6].setByteArr(new byte[] {1, 2, 3}); |
| deltas[7].setByteArr(new byte[] {1, 2, 3}); |
| |
| deltas[7].resetDeltaStatus(); |
| deltas[7].setStr("delta string"); |
| } |
| |
| private OperationWithAction[] allOps() { |
| return new OperationWithAction[] { |
| // Test CREATE and verify with a GET |
| new OperationWithAction(OperationCode.REGISTER_INTEREST, OperationCode.GET, 2, |
| OpFlags.USE_REGEX | OpFlags.REGISTER_POLICY_NONE, 8), |
| new OperationWithAction(OperationCode.REGISTER_INTEREST, OperationCode.GET, 3, |
| OpFlags.USE_REGEX | OpFlags.REGISTER_POLICY_NONE | OpFlags.USE_NOTAUTHZ, 8), |
| new OperationWithAction(OperationCode.PUT), |
| new OperationWithAction(OperationCode.GET, 2, OpFlags.USE_OLDCONN | OpFlags.LOCAL_OP, 4), |
| new OperationWithAction(OperationCode.GET, 3, |
| OpFlags.USE_OLDCONN | OpFlags.LOCAL_OP | OpFlags.CHECK_FAIL, 4), |
| |
| // OPBLOCK_END indicates end of an operation block that needs to be executed on each server |
| // when doing failover |
| OperationWithAction.OPBLOCK_END, |
| |
| // Test UPDATE and verify with a GET |
| new OperationWithAction(OperationCode.REGISTER_INTEREST, OperationCode.GET, 2, |
| OpFlags.USE_REGEX | OpFlags.REGISTER_POLICY_NONE, 8), |
| new OperationWithAction(OperationCode.REGISTER_INTEREST, OperationCode.GET, 3, |
| OpFlags.USE_REGEX | OpFlags.REGISTER_POLICY_NONE | OpFlags.USE_NOTAUTHZ, 8), |
| new OperationWithAction(OperationCode.PUT, 1, OpFlags.USE_OLDCONN | OpFlags.USE_NEWVAL, 4), |
| new OperationWithAction(OperationCode.GET, 2, |
| OpFlags.USE_OLDCONN | OpFlags.LOCAL_OP | OpFlags.USE_NEWVAL, 4), |
| new OperationWithAction(OperationCode.GET, 3, |
| OpFlags.USE_OLDCONN | OpFlags.LOCAL_OP | OpFlags.USE_NEWVAL | OpFlags.CHECK_FAIL, 4), |
| |
| OperationWithAction.OPBLOCK_END}; |
| } |
| } |