http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/integration-test/ThinClientSecurityAuthzTestBaseN.cs ---------------------------------------------------------------------- diff --git a/clicache/integration-test/ThinClientSecurityAuthzTestBaseN.cs b/clicache/integration-test/ThinClientSecurityAuthzTestBaseN.cs new file mode 100644 index 0000000..a66c41d --- /dev/null +++ b/clicache/integration-test/ThinClientSecurityAuthzTestBaseN.cs @@ -0,0 +1,1061 @@ +/* + * 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. + */ + +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Apache.Geode.Client.UnitTests +{ + using NUnit.Framework; + using Apache.Geode.DUnitFramework; + using Apache.Geode.Client.Tests; + using Apache.Geode.Client; + //using Region = Apache.Geode.Client.IRegion<Object, Object>; + using AssertionException = Apache.Geode.Client.AssertionException; + public abstract class ThinClientSecurityAuthzTestBase : ThinClientRegionSteps + { + #region Protected members + + protected const string SubregionName = "AuthSubregion"; + protected const string CacheXml1 = "cacheserver_notify_subscription.xml"; + protected const string CacheXml2 = "cacheserver_notify_subscription2.xml"; + + #endregion + + #region Private methods + + private static string IndicesToString(int[] indices) + { + string str = string.Empty; + if (indices != null && indices.Length > 0) + { + str += indices[0]; + for (int index = 1; index < indices.Length; ++index) + { + str += ','; + str += indices[index]; + } + } + return str; + } + + private IRegion<TKey, TValue> CreateSubregion<TKey, TValue>(IRegion<TKey, TValue> region) + { + Util.Log("CreateSubregion " + SubregionName); + IRegion<TKey, TValue> subregion = region.GetSubRegion(SubregionName); + if (subregion == null) + { + //subregion = region.CreateSubRegion(SubregionName, region.Attributes); + subregion = CacheHelper.GetRegion<TKey, TValue>(region.FullPath).CreateSubRegion(SubregionName, region.Attributes); + } + return subregion; + } + + private bool CheckFlags(OpFlags flags, OpFlags checkFlag) + { + return ((flags & checkFlag) == checkFlag); + } + + protected void DoOp(OperationCode op, int[] indices, + OpFlags flags, ExpectedResult expectedResult) + { + DoOp(op, indices, flags, expectedResult, null, false); + } + + protected void DoOp(OperationCode op, int[] indices, + OpFlags flags, ExpectedResult expectedResult, Properties<string, string> creds, bool isMultiuser) + { + IRegion<object, object> region; + if(isMultiuser) + region = CacheHelper.GetRegion<object, object>(RegionName, creds); + else + region = CacheHelper.GetRegion<object, object>(RegionName); + + if (CheckFlags(flags, OpFlags.UseSubRegion)) + { + IRegion<object, object> subregion = null; + if (CheckFlags(flags, OpFlags.NoCreateSubRegion)) + { + subregion = region.GetSubRegion(SubregionName); + if (CheckFlags(flags, OpFlags.CheckNoRegion)) + { + Assert.IsNull(subregion); + return; + } + else + { + Assert.IsNotNull(subregion); + } + } + else + { + subregion = CreateSubregion(region); + if (isMultiuser) + subregion = region.GetSubRegion(SubregionName); + } + Assert.IsNotNull(subregion); + region = subregion; + } + else if (CheckFlags(flags, OpFlags.CheckNoRegion)) + { + Assert.IsNull(region); + return; + } + else + { + Assert.IsNotNull(region); + } + string valPrefix; + if (CheckFlags(flags, OpFlags.UseNewVal)) + { + valPrefix = NValuePrefix; + } + else + { + valPrefix = ValuePrefix; + } + int numOps = indices.Length; + Util.Log("Got DoOp for op: " + op + ", numOps: " + numOps + + ", indices: " + IndicesToString(indices)); + bool exceptionOccured = false; + bool breakLoop = false; + for (int indexIndex = 0; indexIndex < indices.Length; ++indexIndex) + { + if (breakLoop) + { + break; + } + int index = indices[indexIndex]; + string key = KeyPrefix + index; + string expectedValue = (valPrefix + index); + try + { + switch (op) + { + case OperationCode.Get: + Object value = null; + if (CheckFlags(flags, OpFlags.LocalOp)) + { + int sleepMillis = 100; + int numTries = 30; + bool success = false; + while (!success && numTries-- > 0) + { + if (!isMultiuser && region.ContainsValueForKey(key)) + { + value = region[key]; + success = expectedValue.Equals(value.ToString()); + if (CheckFlags(flags, OpFlags.CheckFail)) + { + success = !success; + } + } + else + { + value = null; + success = CheckFlags(flags, OpFlags.CheckFail); + } + if (!success) + { + Thread.Sleep(sleepMillis); + } + } + } + else + { + if (!isMultiuser) + { + if (CheckFlags(flags, OpFlags.CheckNoKey)) + { + Assert.IsFalse(region.GetLocalView().ContainsKey(key)); + } + else + { + Assert.IsTrue(region.GetLocalView().ContainsKey(key)); + region.GetLocalView().Invalidate(key); + } + } + try + { + value = region[key]; + } + catch (Client.KeyNotFoundException ) + { + Util.Log("KeyNotFoundException while getting key. should be ok as we are just testing auth"); + } + } + if (!isMultiuser && value != null) + { + if (CheckFlags(flags, OpFlags.CheckFail)) + { + Assert.AreNotEqual(expectedValue, value.ToString()); + } + else + { + Assert.AreEqual(expectedValue, value.ToString()); + } + } + break; + case OperationCode.Put: + region[key] = expectedValue; + break; + case OperationCode.Destroy: + if (!isMultiuser && !region.GetLocalView().ContainsKey(key)) + { + // Since DESTROY will fail unless the value is present + // in the local cache, this is a workaround for two cases: + // 1. When the operation is supposed to succeed then in + // the current AuthzCredentialGenerators the clients having + // DESTROY permission also has CREATE/UPDATE permission + // so that calling region.Put() will work for that case. + // 2. When the operation is supposed to fail with + // NotAuthorizedException then in the current + // AuthzCredentialGenerators the clients not + // having DESTROY permission are those with reader role that have + // GET permission. + // + // If either of these assumptions fails, then this has to be + // adjusted or reworked accordingly. + if (CheckFlags(flags, OpFlags.CheckNotAuthz)) + { + value = region[key]; + Assert.AreEqual(expectedValue, value.ToString()); + } + else + { + region[key] = expectedValue; + } + } + if ( !isMultiuser && CheckFlags(flags, OpFlags.LocalOp)) + { + region.GetLocalView().Remove(key); //Destroyed replaced by Remove() API + } + else + { + region.Remove(key); //Destroyed replaced by Remove API + } + break; + //TODO: Need to fix Stack overflow exception.. + case OperationCode.RegisterInterest: + if (CheckFlags(flags, OpFlags.UseList)) + { + breakLoop = true; + // Register interest list in this case + List<CacheableKey> keyList = new List<CacheableKey>(numOps); + for (int keyNumIndex = 0; keyNumIndex < numOps; ++keyNumIndex) + { + int keyNum = indices[keyNumIndex]; + keyList.Add(KeyPrefix + keyNum); + } + region.GetSubscriptionService().RegisterKeys(keyList.ToArray()); + } + else if (CheckFlags(flags, OpFlags.UseRegex)) + { + breakLoop = true; + region.GetSubscriptionService().RegisterRegex(KeyPrefix + "[0-" + (numOps - 1) + ']'); + } + else if (CheckFlags(flags, OpFlags.UseAllKeys)) + { + breakLoop = true; + region.GetSubscriptionService().RegisterAllKeys(); + } + break; + //TODO: Need to fix Stack overflow exception.. + case OperationCode.UnregisterInterest: + if (CheckFlags(flags, OpFlags.UseList)) + { + breakLoop = true; + // Register interest list in this case + List<CacheableKey> keyList = new List<CacheableKey>(numOps); + for (int keyNumIndex = 0; keyNumIndex < numOps; ++keyNumIndex) + { + int keyNum = indices[keyNumIndex]; + keyList.Add(KeyPrefix + keyNum); + } + region.GetSubscriptionService().UnregisterKeys(keyList.ToArray()); + } + else if (CheckFlags(flags, OpFlags.UseRegex)) + { + breakLoop = true; + region.GetSubscriptionService().UnregisterRegex(KeyPrefix + "[0-" + (numOps - 1) + ']'); + } + else if (CheckFlags(flags, OpFlags.UseAllKeys)) + { + breakLoop = true; + region.GetSubscriptionService().UnregisterAllKeys(); + } + break; + case OperationCode.Query: + breakLoop = true; + ISelectResults<object> queryResults; + + if (!isMultiuser) + { + queryResults = (ResultSet<object>)region.Query<object>( + "SELECT DISTINCT * FROM " + region.FullPath); + } + else + { + queryResults = CacheHelper.getMultiuserCache(creds).GetQueryService<object, object>().NewQuery("SELECT DISTINCT * FROM " + region.FullPath).Execute(); + } + Assert.IsNotNull(queryResults); + if (!CheckFlags(flags, OpFlags.CheckFail)) + { + Assert.AreEqual(numOps, queryResults.Size); + } + //CacheableHashSet querySet = new CacheableHashSet(queryResults.Size); + List<string> querySet = new List<string>(queryResults.Size); + ResultSet<object> rs = queryResults as ResultSet<object>; + foreach ( object result in rs) + { + querySet.Add(result.ToString()); + } + for (int keyNumIndex = 0; keyNumIndex < numOps; ++keyNumIndex) + { + int keyNum = indices[keyNumIndex]; + string expectedVal = valPrefix + keyNumIndex; + if (CheckFlags(flags, OpFlags.CheckFail)) + { + Assert.IsFalse(querySet.Contains(expectedVal)); + } + else + { + Assert.IsTrue(querySet.Contains(expectedVal)); + } + } + break; + case OperationCode.RegionDestroy: + breakLoop = true; + if ( !isMultiuser && CheckFlags(flags, OpFlags.LocalOp)) + { + region.GetLocalView().DestroyRegion(); + } + else + { + region.DestroyRegion(); + } + break; + + case OperationCode.GetServerKeys: + breakLoop = true; + ICollection<object> serverKeys = region.Keys; + break; + + //TODO: Need to fix System.ArgumentOutOfRangeException: Index was out of range. Know issue with GetAll() + case OperationCode.GetAll: + //ICacheableKey[] keymap = new ICacheableKey[5]; + List<object> keymap = new List<object>(); + for (int i = 0; i < 5; i++) + { + keymap.Add(i); + //CacheableInt32 item = CacheableInt32.Create(i); + //Int32 item = i; + // NOTE: GetAll should operate right after PutAll + //keymap[i] = item; + } + Dictionary<Object, Object> entrymap = new Dictionary<Object, Object>(); + //CacheableHashMap entrymap = CacheableHashMap.Create(); + region.GetAll(keymap, entrymap, null, false); + if (entrymap.Count < 5) + { + Assert.Fail("DoOp: Got fewer entries for op " + op); + } + break; + case OperationCode.PutAll: + // NOTE: PutAll should operate right before GetAll + //CacheableHashMap entrymap2 = CacheableHashMap.Create(); + Dictionary<Object, Object> entrymap2 = new Dictionary<object, object>(); + for (int i = 0; i < 5; i++) + { + //CacheableInt32 item = CacheableInt32.Create(i); + Int32 item = i; + entrymap2.Add(item, item); + } + region.PutAll(entrymap2); + break; + case OperationCode.RemoveAll: + Dictionary<Object, Object> entrymap3 = new Dictionary<object, object>(); + for (int i = 0; i < 5; i++) + { + //CacheableInt32 item = CacheableInt32.Create(i); + Int32 item = i; + entrymap3.Add(item, item); + } + region.PutAll(entrymap3); + ICollection<object> keys = new LinkedList<object>(); + for (int i = 0; i < 5; i++) + { + Int32 item = i; + keys.Add(item); + } + region.RemoveAll(keys); + break; + case OperationCode.ExecuteCQ: + Pool/*<object, object>*/ pool = CacheHelper.DCache.GetPoolManager().Find("__TESTPOOL1_"); + QueryService<object, object> qs; + if (pool != null) + { + qs = pool.GetQueryService<object, object>(); + } + else + { + //qs = CacheHelper.DCache.GetQueryService<object, object>(); + qs = null; + + } + CqAttributesFactory<object, object> cqattrsfact = new CqAttributesFactory<object, object>(); + CqAttributes<object, object> cqattrs = cqattrsfact.Create(); + CqQuery<object, object> cq = qs.NewCq("cq_security", "SELECT * FROM /" + region.Name, cqattrs, false); + qs.ExecuteCqs(); + qs.StopCqs(); + qs.CloseCqs(); + break; + + case OperationCode.ExecuteFunction: + if (!isMultiuser) + { + Pool/*<object, object>*/ pool2 = CacheHelper.DCache.GetPoolManager().Find("__TESTPOOL1_"); + if (pool2 != null) + { + Client.FunctionService<object>.OnServer(pool2).Execute("securityTest"); + Client.FunctionService<object>.OnRegion<object, object>(region).Execute("FireNForget"); + } + else + { + expectedResult = ExpectedResult.Success; + } + } + else + { + //FunctionService fs = CacheHelper.getMultiuserCache(creds).GetFunctionService(); + //Execution exe = fs.OnServer(); + IRegionService userCache = CacheHelper.getMultiuserCache(creds); + Apache.Geode.Client.Execution<object> exe = Client.FunctionService<object>.OnServer(userCache); + exe.Execute("securityTest"); + exe = Client.FunctionService<object>.OnServers(userCache); + Client.FunctionService<object>.OnRegion<object, object>(region); + Client.FunctionService<object>.OnRegion<object, object>(userCache.GetRegion<object, object>(region.Name)).Execute("FireNForget"); + } + break; + default: + Assert.Fail("DoOp: Unhandled operation " + op); + break; + } + + if (expectedResult != ExpectedResult.Success) + { + Assert.Fail("Expected an exception while performing operation"); + } + } + catch (AssertionException ex) + { + Util.Log("DoOp: failed assertion: {0}", ex); + throw; + } + catch (NotAuthorizedException ex) + { + exceptionOccured = true; + if (expectedResult == ExpectedResult.NotAuthorizedException) + { + Util.Log( + "DoOp: Got expected NotAuthorizedException when doing operation [" + + op + "] with flags [" + flags + "]: " + ex.Message); + continue; + } + else + { + Assert.Fail("DoOp: Got unexpected NotAuthorizedException when " + + "doing operation: " + ex.Message); + } + } + catch (Exception ex) + { + exceptionOccured = true; + if (expectedResult == ExpectedResult.OtherException) + { + Util.Log("DoOp: Got expected exception when doing operation: " + + ex.GetType() + "::" + ex.Message); + continue; + } + else + { + Assert.Fail("DoOp: Got unexpected exception when doing operation: " + ex); + } + } + } + + if (!exceptionOccured + && expectedResult != ExpectedResult.Success) + { + Assert.Fail("Expected an exception while performing operation"); + } + Util.Log(" doop done"); + } + + protected void ExecuteOpBlock(List<OperationWithAction> opBlock, + string authInit, Properties<string, string> extraAuthProps, Properties<string, string> extraAuthzProps, + TestCredentialGenerator gen, Random rnd, bool isMultiuser, bool ssl,bool withPassword) + { + foreach (OperationWithAction currentOp in opBlock) + { + // Start client with valid credentials as specified in + // OperationWithAction + OperationCode opCode = currentOp.OpCode; + OpFlags opFlags = currentOp.Flags; + int clientNum = currentOp.ClientNum; + if (clientNum > m_clients.Length) + { + Assert.Fail("ExecuteOpBlock: Unknown client number " + clientNum); + } + ClientBase client = m_clients[clientNum - 1]; + Util.Log("ExecuteOpBlock: performing operation number [" + + currentOp.OpNum + "]: " + currentOp); + Properties<string, string> clientProps = null; + if (!CheckFlags(opFlags, OpFlags.UseOldConn)) + { + Properties<string, string> opCredentials; + int newRnd = rnd.Next(100) + 1; + string currentRegionName = '/' + RegionName; + if (CheckFlags(opFlags, OpFlags.UseSubRegion)) + { + currentRegionName += ('/' + SubregionName); + } + string credentialsTypeStr; + OperationCode authOpCode = currentOp.AuthzOperationCode; + int[] indices = currentOp.Indices; + CredentialGenerator cGen = gen.GetCredentialGenerator(); + Properties<string, string> javaProps = null; + if (CheckFlags(opFlags, OpFlags.CheckNotAuthz) || + CheckFlags(opFlags, OpFlags.UseNotAuthz)) + { + opCredentials = gen.GetDisallowedCredentials( + new OperationCode[] { authOpCode }, + new string[] { currentRegionName }, indices, newRnd); + credentialsTypeStr = " unauthorized " + authOpCode; + } + else + { + opCredentials = gen.GetAllowedCredentials(new OperationCode[] { + opCode, authOpCode }, new string[] { currentRegionName }, + indices, newRnd); + credentialsTypeStr = " authorized " + authOpCode; + } + if (cGen != null) + { + javaProps = cGen.JavaProperties; + } + clientProps = SecurityTestUtil.ConcatProperties( + opCredentials, extraAuthProps, extraAuthzProps); + // Start the client with valid credentials but allowed or disallowed to + // perform an operation + Util.Log("ExecuteOpBlock: For client" + clientNum + + credentialsTypeStr + " credentials: " + opCredentials); + + if(!isMultiuser) + client.Call(SecurityTestUtil.CreateClientSSL, RegionName, + CacheHelper.Locators, authInit, clientProps, ssl, withPassword); + else + client.Call(SecurityTestUtil.CreateClientMU, RegionName, + CacheHelper.Locators, authInit, (Properties<string, string>)null, true); + } + ExpectedResult expectedResult; + if (CheckFlags(opFlags, OpFlags.CheckNotAuthz)) + { + expectedResult = ExpectedResult.NotAuthorizedException; + } + else if (CheckFlags(opFlags, OpFlags.CheckException)) + { + expectedResult = ExpectedResult.OtherException; + } + else + { + expectedResult = ExpectedResult.Success; + } + + // Perform the operation from selected client + if (!isMultiuser) + client.Call(DoOp, opCode, currentOp.Indices, opFlags, expectedResult); + else + client.Call(DoOp, opCode, currentOp.Indices, opFlags, expectedResult, clientProps, true); + } + } + + protected List<AuthzCredentialGenerator> GetAllGeneratorCombos(bool isMultiUser) + { + List<AuthzCredentialGenerator> generators = + new List<AuthzCredentialGenerator>(); + foreach (AuthzCredentialGenerator.ClassCode authzClassCode in + Enum.GetValues(typeof(AuthzCredentialGenerator.ClassCode))) + { + List<CredentialGenerator> cGenerators = + SecurityTestUtil.getAllGenerators(isMultiUser); + foreach (CredentialGenerator cGen in cGenerators) + { + AuthzCredentialGenerator authzGen = AuthzCredentialGenerator + .Create(authzClassCode); + if (authzGen != null) + { + if (authzGen.Init(cGen)) + { + generators.Add(authzGen); + } + } + } + } + return generators; + } + + protected void RunOpsWithFailoverSSL(OperationWithAction[] opCodes, + string testName, bool withPassword) + { + RunOpsWithFailover(opCodes, testName, false, true,withPassword); + } + + protected void RunOpsWithFailover(OperationWithAction[] opCodes, + string testName) + { + RunOpsWithFailover(opCodes, testName, false); + } + + protected void RunOpsWithFailover(OperationWithAction[] opCodes, + string testName, bool isMultiUser) + { + RunOpsWithFailover(opCodes, testName, isMultiUser, false, false); + } + + protected void RunOpsWithFailover(OperationWithAction[] opCodes, + string testName, bool isMultiUser, bool ssl, bool withPassword) + { + CacheHelper.SetupJavaServers(true, CacheXml1, CacheXml2); + CacheHelper.StartJavaLocator(1, "GFELOC", null, ssl); + Util.Log("Locator started"); + + foreach (AuthzCredentialGenerator authzGen in GetAllGeneratorCombos(isMultiUser)) + { + CredentialGenerator cGen = authzGen.GetCredentialGenerator(); + Properties<string, string> extraAuthProps = cGen.SystemProperties; + Properties<string, string> javaProps = cGen.JavaProperties; + Properties<string, string> extraAuthzProps = authzGen.SystemProperties; + string authenticator = cGen.Authenticator; + string authInit = cGen.AuthInit; + string accessor = authzGen.AccessControl; + TestAuthzCredentialGenerator tgen = new TestAuthzCredentialGenerator(authzGen); + + Util.Log(testName + ": Using authinit: " + authInit); + Util.Log(testName + ": Using authenticator: " + authenticator); + Util.Log(testName + ": Using accessor: " + accessor); + + // Start servers with all required properties + string serverArgs = SecurityTestUtil.GetServerArgs(authenticator, + accessor, null, SecurityTestUtil.ConcatProperties(extraAuthProps, + extraAuthzProps), javaProps); + + // Perform all the ops on the clients + List<OperationWithAction> opBlock = new List<OperationWithAction>(); + Random rnd = new Random(); + for (int opNum = 0; opNum < opCodes.Length; ++opNum) + { + // Start client with valid credentials as specified in + // OperationWithAction + OperationWithAction currentOp = opCodes[opNum]; + if (currentOp == OperationWithAction.OpBlockEnd || + currentOp == OperationWithAction.OpBlockNoFailover) + { + // End of current operation block; execute all the operations + // on the servers with/without failover + if (opBlock.Count > 0) + { + // Start the first server and execute the operation block + CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1, serverArgs, ssl); + Util.Log("Cacheserver 1 started."); + CacheHelper.StopJavaServer(2, false); + ExecuteOpBlock(opBlock, authInit, extraAuthProps, + extraAuthzProps, tgen, rnd, isMultiUser, ssl, withPassword); + if (currentOp == OperationWithAction.OpBlockNoFailover) + { + CacheHelper.StopJavaServer(1); + } + else + { + // Failover to the second server and run the block again + CacheHelper.StartJavaServerWithLocators(2, "GFECS2", 1, serverArgs, ssl); + Util.Log("Cacheserver 2 started."); + CacheHelper.StopJavaServer(1); + ExecuteOpBlock(opBlock, authInit, extraAuthProps, + extraAuthzProps, tgen, rnd, isMultiUser, ssl, withPassword); + } + opBlock.Clear(); + } + } + else + { + currentOp.OpNum = opNum; + opBlock.Add(currentOp); + } + } + // Close all clients here since we run multiple iterations for pool and non pool configs + foreach (ClientBase client in m_clients) + { + client.Call(Close); + } + } + CacheHelper.StopJavaLocator(1, true, ssl); + CacheHelper.ClearEndpoints(); + CacheHelper.ClearLocators(); + } + + #endregion + + /// <summary> + /// This class specifies flags that can be used to alter the behaviour of + /// operations being performed by the <see cref="DoOp"/> method. + /// </summary> + [Flags] + public enum OpFlags + { + /// <summary> + /// Default behaviour. + /// </summary> + None = 0x0, + + /// <summary> + /// Check that the operation should fail. + /// </summary> + CheckFail = 0x1, + + /// <summary> + /// Check that the operation should throw <c>NotAuthorizedException</c>. + /// </summary> + CheckNotAuthz = 0x2, + + /// <summary> + /// Do the connection with unauthorized credentials but do not check that the + /// operation throws <c>NotAuthorizedException</c>. + /// </summary> + UseNotAuthz = 0x4, + + /// <summary> + /// Check that the region should not be available. + /// </summary> + CheckNoRegion = 0x8, + + /// <summary> + /// Check that the operation should throw an exception other than the + /// <c>NotAuthorizedException</c>. + /// </summary> + CheckException = 0x10, + + /// <summary> + /// Check for values starting with <c>NValuePrefix</c> instead of + /// <c>ValuePrefix</c>. + /// </summary> + UseNewVal = 0x20, + + /// <summary> + /// Register a regular expression. + /// </summary> + UseRegex = 0x40, + + /// <summary> + /// Register a list of keys. + /// </summary> + UseList = 0x80, + + /// <summary> + /// Register all keys. + /// </summary> + UseAllKeys = 0x100, + + /// <summary> + /// Perform the local version of the operation (if applicable). + /// </summary> + LocalOp = 0x200, + + /// <summary> + /// Check that the key for the operation should not be present. + /// </summary> + CheckNoKey = 0x400, + + /// <summary> + /// Use the sub-region for performing the operation. + /// </summary> + UseSubRegion = 0x800, + + /// <summary> + /// Do not try to create the sub-region. + /// </summary> + NoCreateSubRegion = 0x1000, + + /// <summary> + /// Do not re-connect using new credentials rather use the previous + /// connection. + /// </summary> + UseOldConn = 0x2000, + } + + /// <summary> + /// This class encapsulates an <see cref="OperationCode"/> with associated flags, the + /// client to perform the operation, and the number of operations to perform. + /// </summary> + public class OperationWithAction + { + /// <summary> + /// The operation to be performed. + /// </summary> + private OperationCode m_opCode; + + /// <summary> + /// The operation for which authorized or unauthorized credentials have to be + /// generated. This is the same as {@link #opCode} when not specified. + /// </summary> + private OperationCode m_authzOpCode; + + /// <summary> + /// The client number on which the operation has to be performed. + /// </summary> + private int m_clientNum; + + /// <summary> + /// Bitwise or'd <see cref="OpFlags"/> to change/specify the behaviour of + /// the operations. + /// </summary> + private OpFlags m_flags; + + /// <summary> + /// Indices of the keys array to be used for operations. The keys used + /// will be concatenation of <c>KeyPrefix</c> and <c>index</c> integer. + /// </summary> + private int[] m_indices; + + /// <summary> + /// An index for the operation used for logging. + /// </summary> + private int m_opNum; + + /// <summary> + /// Indicates end of an operation block which can be used for testing with + /// failover. + /// </summary> + public static readonly OperationWithAction OpBlockEnd = new OperationWithAction( + OperationCode.Get, 4); + + /// <summary> + /// Indicates end of an operation block which should not be used for testing + /// with failover. + /// </summary> + public static readonly OperationWithAction OpBlockNoFailover = + new OperationWithAction(OperationCode.Get, 5); + + private void SetIndices(int numOps) + { + this.m_indices = new int[numOps]; + for (int index = 0; index < numOps; ++index) + { + this.m_indices[index] = index; + } + } + + public OperationWithAction(OperationCode opCode) + { + this.m_opCode = opCode; + this.m_authzOpCode = opCode; + this.m_clientNum = 1; + this.m_flags = OpFlags.None; + SetIndices(4); + this.m_opNum = 0; + } + + public OperationWithAction(OperationCode opCode, int clientNum) + { + this.m_opCode = opCode; + this.m_authzOpCode = opCode; + this.m_clientNum = clientNum; + this.m_flags = OpFlags.None; + SetIndices(4); + this.m_opNum = 0; + } + + public OperationWithAction(OperationCode opCode, int clientNum, OpFlags flags, + int numOps) + { + this.m_opCode = opCode; + this.m_authzOpCode = opCode; + this.m_clientNum = clientNum; + this.m_flags = flags; + SetIndices(numOps); + this.m_opNum = 0; + } + + public OperationWithAction(OperationCode opCode, + OperationCode deniedOpCode, int clientNum, OpFlags flags, int numOps) + { + this.m_opCode = opCode; + this.m_authzOpCode = deniedOpCode; + this.m_clientNum = clientNum; + this.m_flags = flags; + SetIndices(numOps); + this.m_opNum = 0; + } + + public OperationWithAction(OperationCode opCode, int clientNum, + OpFlags flags, int[] indices) + { + this.m_opCode = opCode; + this.m_authzOpCode = opCode; + this.m_clientNum = clientNum; + this.m_flags = flags; + this.m_indices = indices; + this.m_opNum = 0; + } + + public OperationWithAction(OperationCode opCode, OperationCode authzOpCode, + int clientNum, OpFlags flags, int[] indices) + { + this.m_opCode = opCode; + this.m_authzOpCode = authzOpCode; + this.m_clientNum = clientNum; + this.m_flags = flags; + this.m_indices = indices; + this.m_opNum = 0; + } + + public OperationCode OpCode + { + get + { + return this.m_opCode; + } + } + + public OperationCode AuthzOperationCode + { + get + { + return this.m_authzOpCode; + } + } + + public int ClientNum + { + get + { + return this.m_clientNum; + } + } + + public OpFlags Flags + { + get + { + return this.m_flags; + } + } + + public int[] Indices + { + get + { + return this.m_indices; + } + } + + public int OpNum + { + get + { + return this.m_opNum; + } + set + { + this.m_opNum = value; + } + } + + public override string ToString() + { + return "opCode:" + this.m_opCode + ",authOpCode:" + this.m_authzOpCode + + ",clientNum:" + this.m_clientNum + ",flags:" + this.m_flags + + ",numOps:" + this.m_indices.Length + ",indices:" + + IndicesToString(this.m_indices); + } + } + + /// <summary> + /// Simple interface to generate credentials with authorization based on key + /// indices also. This is utilized by the post-operation authorization tests + /// <c>ThinClientAuthzObjectModTests</c> where authorization depends on + /// the actual keys being used for the operation. + /// </summary> + public interface TestCredentialGenerator + { + /// <summary> + /// Get allowed credentials for the given set of operations in the given + /// regions and indices of keys. + /// </summary> + Properties<string, string> GetAllowedCredentials(OperationCode[] opCodes, + string[] regionNames, int[] keyIndices, int num); + + /// <summary> + /// Get disallowed credentials for the given set of operations in the given + /// regions and indices of keys. + /// </summary> + Properties<string, string> GetDisallowedCredentials(OperationCode[] opCodes, + string[] regionNames, int[] keyIndices, int num); + + /// <summary> + /// Get the <see cref="CredentialGenerator"/> if any. + /// </summary> + /// <returns></returns> + CredentialGenerator GetCredentialGenerator(); + } + + /// <summary> + /// Contains a <c>AuthzCredentialGenerator</c> and implements the + /// <c>TestCredentialGenerator</c> interface. + /// </summary> + protected class TestAuthzCredentialGenerator : TestCredentialGenerator + { + private AuthzCredentialGenerator authzGen; + + public TestAuthzCredentialGenerator(AuthzCredentialGenerator authzGen) + { + this.authzGen = authzGen; + } + + public Properties<string, string> GetAllowedCredentials(OperationCode[] opCodes, + string[] regionNames, int[] keyIndices, int num) + { + + return this.authzGen.GetAllowedCredentials(opCodes, regionNames, num); + } + + public Properties<string, string> GetDisallowedCredentials(OperationCode[] opCodes, + string[] regionNames, int[] keyIndices, int num) + { + + return this.authzGen.GetDisallowedCredentials(opCodes, regionNames, num); + } + + public CredentialGenerator GetCredentialGenerator() + { + + return authzGen.GetCredentialGenerator(); + } + } + } +}
http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/integration-test/ThinClientSecurityAuthzTestsMUN.cs ---------------------------------------------------------------------- diff --git a/clicache/integration-test/ThinClientSecurityAuthzTestsMUN.cs b/clicache/integration-test/ThinClientSecurityAuthzTestsMUN.cs new file mode 100644 index 0000000..3d697bb --- /dev/null +++ b/clicache/integration-test/ThinClientSecurityAuthzTestsMUN.cs @@ -0,0 +1,1051 @@ +/* + * 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. + */ + +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Apache.Geode.Client.UnitTests +{ + using NUnit.Framework; + using Apache.Geode.DUnitFramework; + using Apache.Geode.Client.Tests; + using Apache.Geode.Client; + + public class MyCqListener2<TKey, TResult> : ICqListener<TKey, TResult> + { + private int m_create = 0; + private int m_update = 0; + private int m_id = 0; + + public MyCqListener2(int id) + { + this.m_id = id; + } + + public int Creates + { + get { return m_create; } + } + + public int Updates + { + get { return m_update; } + } + + #region ICqListener Members + + void ICqListener<TKey, TResult>.Close() + { + Util.Log("CqListener closed with ID = " + m_id); + } + + void ICqListener<TKey, TResult>.OnError(CqEvent<TKey, TResult> ev) + { + Util.Log("CqListener OnError called "); + } + + void ICqListener<TKey, TResult>.OnEvent(CqEvent<TKey, TResult> ev) + { + Util.Log("CqListener OnEvent ops = " + ev.getBaseOperation()); + if (ev.getBaseOperation() == CqOperationType.OP_TYPE_CREATE) + m_create++; + else if (ev.getBaseOperation() == CqOperationType.OP_TYPE_UPDATE) + m_update++; + } + + #endregion + } + + [TestFixture] + [Category("group4")] + [Category("unicast_only")] + [Category("generics")] + public class ThinClientSecurityAuthzTestsMU : ThinClientSecurityAuthzTestBase + { + #region Private members + IRegion<object, object> region; + IRegion<object, object> region1; + private UnitProcess m_client1; + private UnitProcess m_client2; + private UnitProcess m_client3; + private TallyListener<object, object> m_listener; + private TallyWriter<object, object> m_writer; + private string/*<object>*/ keys = "Key"; + private string value = "Value"; + + + #endregion + + protected override ClientBase[] GetClients() + { + m_client1 = new UnitProcess(); + m_client2 = new UnitProcess(); + m_client3 = new UnitProcess(); + return new ClientBase[] { m_client1, m_client2, m_client3 }; + } + + public void CreateRegion(string locators, bool caching, + bool listener, bool writer) + { + Util.Log(" in CreateRegion " + listener + " : " + writer); + if (listener) + { + m_listener = new TallyListener<object, object>(); + } + else + { + m_listener = null; + } + IRegion<object, object> region = null; + region = CacheHelper.CreateTCRegion_Pool<object, object>(RegionName, true, caching, + m_listener, locators, "__TESTPOOL1_", true); + + if (writer) + { + m_writer = new TallyWriter<object, object>(); + } + else + { + m_writer = null; + } + Util.Log("region created "); + AttributesMutator<object, object> at = region.AttributesMutator; + at.SetCacheWriter(m_writer); + } + + public void DoPut() + { + region = CacheHelper.GetRegion<object, object>(RegionName); + region[keys.ToString()] = value; + } + + public void CheckAssert() + { + Assert.AreEqual(true, m_writer.IsWriterInvoked, "Writer Should be invoked"); + Assert.AreEqual(false, m_listener.IsListenerInvoked, "Listener Should not be invoked"); + Assert.IsFalse(region.ContainsKey(keys.ToString()), "Key should have been found in the region"); + } + + public void DoLocalPut() + { + region1 = CacheHelper.GetRegion<object, object>(RegionName); + region1.GetLocalView()[m_keys[2]] = m_vals[2]; + //this check is no loger valid as ContainsKey goes on server + //Assert.IsTrue(region1.ContainsKey(m_keys[2]), "Key should have been found in the region"); + Assert.AreEqual(true, m_writer.IsWriterInvoked, "Writer Should be invoked"); + Assert.AreEqual(true, m_listener.IsListenerInvoked, "Listener Should be invoked"); + + //try Update + try + { + Util.Log("Trying UpdateEntry"); + m_listener.ResetListenerInvokation(); + UpdateEntry(RegionName, m_keys[2], m_nvals[2], false); + Assert.Fail("Should have got NotAuthorizedException during updateEntry"); + } + catch (NotAuthorizedException) + { + Util.Log("NotAuthorizedException Caught"); + Util.Log("Success"); + } + catch (Exception other) + { + Util.Log("Stack trace: {0} ", other.StackTrace); + Util.Log("Got exception : {0}", other.Message); + } + Assert.AreEqual(true, m_writer.IsWriterInvoked, "Writer should be invoked"); + Assert.AreEqual(false, m_listener.IsListenerInvoked, "Listener should not be invoked"); + //Assert.IsTrue(region1.ContainsKey(m_keys[2]), "Key should have been found in the region"); + VerifyEntry(RegionName, m_keys[2], m_vals[2]); + m_writer.SetWriterFailed(); + + //test CacheWriter + try + { + Util.Log("Testing CacheWriterException"); + UpdateEntry(RegionName, m_keys[2], m_nvals[2], false); + Assert.Fail("Should have got NotAuthorizedException during updateEntry"); + } + catch (CacheWriterException) + { + Util.Log("CacheWriterException Caught"); + Util.Log("Success"); + } + + } + + [TestFixtureTearDown] + public override void EndTests() + { + CacheHelper.StopJavaServers(); + base.EndTests(); + } + + [TearDown] + public override void EndTest() + { + try + { + if (m_clients != null) + { + foreach (ClientBase client in m_clients) + { + client.Call(CacheHelper.Close); + } + } + CacheHelper.Close(); + CacheHelper.ClearEndpoints(); + } + finally + { + CacheHelper.StopJavaServers(); + } + base.EndTest(); + } + + protected const string RegionName_CQ = "Portfolios"; + static QueryService<object, object> gQueryService = null; + + static string [] QueryStrings = { + "select * from /Portfolios p where p.ID < 1", + "select * from /Portfolios p where p.ID < 2", + "select * from /Portfolios p where p.ID = 2", + "select * from /Portfolios p where p.ID >= 3",//this should pass + "select * from /Portfolios p where p.ID = 4",//this should pass + "select * from /Portfolios p where p.ID = 5", + "select * from /Portfolios p where p.ID = 6", + "select * from /Portfolios p where p.ID = 7" + }; + + public void registerCQ(Properties<string, string> credentials, bool durableCQ) + { + Util.Log("registerCQ"); + + try + { + Serializable.RegisterTypeGeneric(Portfolio.CreateDeserializable, CacheHelper.DCache); + Serializable.RegisterTypeGeneric(Position.CreateDeserializable, CacheHelper.DCache); + Util.Log("registerCQ portfolio registered"); + } + catch (IllegalStateException) + { + Util.Log("registerCQ portfolio NOT registered"); + // ignore since we run multiple iterations for pool and non pool configs + } + + // VJR: TODO fix cache.GetQueryService to also be generic + gQueryService = CacheHelper.getMultiuserCache(credentials).GetQueryService<object, object>(); + + for (int i = 0; i < QueryStrings.Length; i++) + { + CqAttributesFactory<object, object> cqAttrFact = new CqAttributesFactory<object, object>(); + cqAttrFact.AddCqListener(new MyCqListener2<object, object>(i)); + CqQuery<object, object> cq = gQueryService.NewCq("cq_" + i, QueryStrings[i], cqAttrFact.Create(), durableCQ); + cq.Execute(); + } + Util.Log("registerCQ Done."); + } + + public void doCQPut(Properties<string, string> credentials) + { + Util.Log("doCQPut"); + + try + { + Serializable.RegisterTypeGeneric(Portfolio.CreateDeserializable, CacheHelper.DCache); + Serializable.RegisterTypeGeneric(Position.CreateDeserializable, CacheHelper.DCache); + Util.Log("doCQPut portfolio registered"); + } + catch (IllegalStateException) + { + Util.Log("doCQPut portfolio NOT registered"); + // ignore since we run multiple iterations for pool and non pool configs + } + //IRegion<object, object> region = CacheHelper.GetVerifyRegion(RegionName_CQ, credentials); + + IRegionService userRegionService = CacheHelper.getMultiuserCache(credentials); + IRegion<object, object>[] regions = userRegionService.RootRegions<object, object>(); + + IRegion<object, object> region = null; + + Console.Out.WriteLine("Number of regions " + regions.Length); + for (int i = 0; i < regions.Length; i++) + { + if (regions[i].Name.Equals(RegionName_CQ)) + { + region = regions[i]; + break; + } + } + + for (int i = 0; i < QueryStrings.Length; i++) + { + string key = "port1-" + i; + + Portfolio p = new Portfolio(i); + + region[key] = p; + } + + IRegionService rgServ = region.RegionService; + + Cache cache = rgServ as Cache; + + Assert.IsNull(cache); + + Thread.Sleep(20000); + Util.Log("doCQPut Done."); + } + + public void verifyCQEvents(bool whetherResult, CqOperationType opType ) + { + Util.Log("verifyCQEvents " + gQueryService); + Assert.IsNotNull(gQueryService); + + CqQuery<object, object> cq = gQueryService.GetCq("cq_" + 3); + ICqListener<object, object>[] cqL = cq.GetCqAttributes().getCqListeners(); + MyCqListener2<object, object> mcqL = (MyCqListener2<object, object>)cqL[0]; + + Util.Log("got result for cq listener3 " + cq.Name + " : " + mcqL.Creates); + + if (opType == CqOperationType.OP_TYPE_CREATE) + { + if (whetherResult) + Assert.AreEqual(1, mcqL.Creates, "CQ listener 3 should get one create event "); + else + Assert.AreEqual(0, mcqL.Creates, "CQ listener 3 should not get any create event "); + } + else if (opType == CqOperationType.OP_TYPE_UPDATE) + { + if (whetherResult) + Assert.AreEqual(1, mcqL.Updates, "CQ listener 3 should get one update event "); + else + Assert.AreEqual(0, mcqL.Updates, "CQ listener 3 should not get any update event "); + } + + cq = gQueryService.GetCq("cq_" + 4); + cqL = cq.GetCqAttributes().getCqListeners(); + mcqL = (MyCqListener2<object, object>)cqL[0]; + + Util.Log("got result for cq listener4 " + cq.Name + " : " + mcqL.Creates); + + if (opType == CqOperationType.OP_TYPE_CREATE) + { + if (whetherResult) + Assert.AreEqual(1, mcqL.Creates, "CQ listener 4 should get one create event "); + else + Assert.AreEqual(0, mcqL.Creates, "CQ listener 4 should not get any create event "); + } + else if (opType == CqOperationType.OP_TYPE_UPDATE) + { + if (whetherResult) + Assert.AreEqual(1, mcqL.Updates, "CQ listener 4 should get one update event "); + else + Assert.AreEqual(0, mcqL.Updates, "CQ listener 4 should not get any update event "); + } + + cq = gQueryService.GetCq("cq_" + 0); + cqL = cq.GetCqAttributes().getCqListeners(); + mcqL = (MyCqListener2<object, object>)cqL[0]; + + Util.Log("got result for cq listener0 " + cq.Name + " : " + mcqL.Creates); + + Assert.AreEqual(0, mcqL.Creates, "CQ listener 0 should get one create event "); + + + // CacheHelper.getMultiuserCache(null).Close(); + + gQueryService = null; + + } + + void runCQTest() + { + CacheHelper.SetupJavaServers(true, "remotequeryN.xml"); + + CacheHelper.StartJavaLocator(1, "GFELOC"); + Util.Log("Locator started"); + + DummyAuthorization3 da = new DummyAuthorization3(); + + string authenticator = da.Authenticator; + string authInit = da.AuthInit; + string accessorPP = da.AuthenticatorPP; + + Util.Log("testAllowPutsGets: Using authinit: " + authInit); + Util.Log("testAllowPutsGets: Using authenticator: " + authenticator); + Util.Log("testAllowPutsGets: Using accessorPP: " + accessorPP); + + // Start servers with all required properties + string serverArgs = SecurityTestUtil.GetServerArgs(authenticator, + null, accessorPP, null, null); + + // Start the two servers. + CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1, serverArgs); + Util.Log("Cacheserver 1 started."); + CacheHelper.StartJavaServerWithLocators(2, "GFECS2", 1, serverArgs); + Util.Log("Cacheserver 2 started."); + + // Start client1 with valid CREATE credentials, this index will be used to authorzie the user + Properties<string, string> createCredentials = da.GetValidCredentials(4); + + Util.Log("runCQTest: "); + m_client1.Call(SecurityTestUtil.CreateClientMU2, RegionName_CQ, + CacheHelper.Locators, authInit, (Properties<string, string>)null, true, true); + + m_client2.Call(SecurityTestUtil.CreateClientMU, RegionName_CQ, + CacheHelper.Locators, authInit, (Properties<string, string>)null, true); + + // Perform some put operations from client1 + m_client1.Call(registerCQ, createCredentials, false); + + // Verify that the gets succeed + m_client2.Call(doCQPut, createCredentials); + + m_client1.Call(verifyCQEvents, true, CqOperationType.OP_TYPE_CREATE); + + m_client1.Call(CloseUserCache, false); + m_client1.Call(Close); + m_client2.Call(Close); + + CacheHelper.StopJavaServer(1); + // CacheHelper.StopJavaServer(2); + + + CacheHelper.StopJavaLocator(1); + + CacheHelper.ClearEndpoints(); + CacheHelper.ClearLocators(); + } + + public void CloseUserCache(bool keepAlive) + { + Util.Log("CloseUserCache keepAlive: " + keepAlive); + CacheHelper.CloseUserCache(keepAlive); + } + + private static string DurableClientId1 = "DurableClientId1"; + //private static string DurableClientId2 = "DurableClientId2"; + + void runDurableCQTest(bool logicalCacheClose, bool durableCQ, bool whetherResult) + { + CacheHelper.SetupJavaServers(true, "remotequeryN.xml"); + + CacheHelper.StartJavaLocator(1, "GFELOC"); + Util.Log("Locator started"); + + DummyAuthorization3 da = new DummyAuthorization3(); + + string authenticator = da.Authenticator; + string authInit = da.AuthInit; + string accessorPP = da.AuthenticatorPP; + + Util.Log("testAllowPutsGets: Using authinit: " + authInit); + Util.Log("testAllowPutsGets: Using authenticator: " + authenticator); + Util.Log("testAllowPutsGets: Using accessorPP: " + accessorPP); + + // Start servers with all required properties + string serverArgs = SecurityTestUtil.GetServerArgs(authenticator, + null, accessorPP, null, null); + + // Start the two servers. + CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1, serverArgs); + Util.Log("Cacheserver 1 started."); + CacheHelper.StartJavaServerWithLocators(2, "GFECS2", 1, serverArgs); + Util.Log("Cacheserver 2 started."); + + // Start client1 with valid CREATE credentials, this index will be used to authorzie the user + Properties<string, string> createCredentials = da.GetValidCredentials(4); + + Util.Log("runCQTest: "); + /* + regionName, string endpoints, string locators, + authInit, Properties credentials, bool pool, bool locator, bool isMultiuser, bool notificationEnabled, string durableClientId) + */ + m_client1.Call(SecurityTestUtil.CreateMUDurableClient, RegionName_CQ, + CacheHelper.Locators, authInit, DurableClientId1, true, true ); + + m_client2.Call(SecurityTestUtil.CreateClientMU, RegionName_CQ, + CacheHelper.Locators, authInit, (Properties<string, string>)null, true); + + m_client1.Call(ReadyForEvents2); + + // Perform some put operations from client1 + m_client1.Call(registerCQ, createCredentials, durableCQ); + + + Properties<string, string> createCredentials2 = da.GetValidCredentials(3); + // Verify that the gets succeed + m_client2.Call(doCQPut, createCredentials2); + + //close cache client-1 + m_client1.Call(verifyCQEvents, true, CqOperationType.OP_TYPE_CREATE); + + Thread.Sleep(10000); + + Util.Log("Before calling CloseUserCache: " + logicalCacheClose); + if (logicalCacheClose) + m_client1.Call(CloseUserCache, logicalCacheClose); + + m_client1.Call(CloseKeepAlive); + //put again from other client + m_client2.Call(doCQPut, createCredentials2); + + //client-1 will up again + m_client1.Call(SecurityTestUtil.CreateMUDurableClient, RegionName_CQ, + CacheHelper.Locators, authInit, DurableClientId1, true, true); + + // Perform some put operations from client1 + m_client1.Call(registerCQ, createCredentials, durableCQ); + + m_client1.Call(ReadyForEvents2); + Thread.Sleep(20000); + m_client1.Call(verifyCQEvents, whetherResult, CqOperationType.OP_TYPE_UPDATE); + + + m_client1.Call(Close); + + m_client2.Call(Close); + + CacheHelper.StopJavaServer(1); + // CacheHelper.StopJavaServer(2); + + + CacheHelper.StopJavaLocator(1); + + CacheHelper.ClearEndpoints(); + CacheHelper.ClearLocators(); + } + + void runAllowPutsGets() + { + CacheHelper.SetupJavaServers(true, CacheXml1, CacheXml2); + + CacheHelper.StartJavaLocator(1, "GFELOC"); + Util.Log("Locator started"); + + foreach (AuthzCredentialGenerator authzGen in GetAllGeneratorCombos(true)) + { + CredentialGenerator cGen = authzGen.GetCredentialGenerator(); + Properties<string, string> extraAuthProps = cGen.SystemProperties; + Properties<string, string> javaProps = cGen.JavaProperties; + Properties<string, string> extraAuthzProps = authzGen.SystemProperties; + string authenticator = cGen.Authenticator; + string authInit = cGen.AuthInit; + string accessor = authzGen.AccessControl; + + Util.Log("testAllowPutsGets: Using authinit: " + authInit); + Util.Log("testAllowPutsGets: Using authenticator: " + authenticator); + Util.Log("testAllowPutsGets: Using accessor: " + accessor); + + // Start servers with all required properties + string serverArgs = SecurityTestUtil.GetServerArgs(authenticator, + accessor, null, SecurityTestUtil.ConcatProperties(extraAuthProps, + extraAuthzProps), javaProps); + + // Start the two servers. + CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1, serverArgs); + Util.Log("Cacheserver 1 started."); + CacheHelper.StartJavaServerWithLocators(2, "GFECS2", 1, serverArgs); + Util.Log("Cacheserver 2 started."); + + // Start client1 with valid CREATE credentials + Properties<string, string> createCredentials = authzGen.GetAllowedCredentials( + new OperationCode[] { OperationCode.Put }, + new string[] { RegionName }, 1); + javaProps = cGen.JavaProperties; + Util.Log("AllowPutsGets: For first client PUT credentials: " + + createCredentials); + m_client1.Call(SecurityTestUtil.CreateClientMU, RegionName, + CacheHelper.Locators, authInit, (Properties<string, string>)null, true); + + // Start client2 with valid GET credentials + Properties<string, string> getCredentials = authzGen.GetAllowedCredentials( + new OperationCode[] { OperationCode.Get }, + new string[] { RegionName }, 2); + javaProps = cGen.JavaProperties; + Util.Log("AllowPutsGets: For second client GET credentials: " + + getCredentials); + m_client2.Call(SecurityTestUtil.CreateClientMU, RegionName, + CacheHelper.Locators, authInit, (Properties<string, string>)null, true); + + // Perform some put operations from client1 + m_client1.Call(DoPutsMU, 10 , createCredentials, true); + + // Verify that the gets succeed + m_client2.Call(DoGetsMU, 10, getCredentials, true); + + m_client1.Call(DoPutsTx, 10, true, ExpectedResult.Success, getCredentials, true); + + m_client2.Call(DoGets, 10, true, ExpectedResult.Success, getCredentials, true); + + m_client1.Call(Close); + m_client2.Call(Close); + + CacheHelper.StopJavaServer(1); + CacheHelper.StopJavaServer(2); + } + + CacheHelper.StopJavaLocator(1); + + CacheHelper.ClearEndpoints(); + CacheHelper.ClearLocators(); + } + + void runDisallowPutsGets() + { + CacheHelper.SetupJavaServers(true, CacheXml1, CacheXml2); + + CacheHelper.StartJavaLocator(1, "GFELOC"); + Util.Log("Locator started"); + + foreach (AuthzCredentialGenerator authzGen in GetAllGeneratorCombos(true)) + { + CredentialGenerator cGen = authzGen.GetCredentialGenerator(); + Properties<string, string> extraAuthProps = cGen.SystemProperties; + Properties<string, string> javaProps = cGen.JavaProperties; + Properties<string, string> extraAuthzProps = authzGen.SystemProperties; + string authenticator = cGen.Authenticator; + string authInit = cGen.AuthInit; + string accessor = authzGen.AccessControl; + + Util.Log("DisallowPutsGets: Using authinit: " + authInit); + Util.Log("DisallowPutsGets: Using authenticator: " + authenticator); + Util.Log("DisallowPutsGets: Using accessor: " + accessor); + + // Check that we indeed can obtain valid credentials not allowed to do + // gets + Properties<string, string> createCredentials = authzGen.GetAllowedCredentials( + new OperationCode[] { OperationCode.Put }, + new string[] { RegionName }, 1); + Properties<string, string> createJavaProps = cGen.JavaProperties; + Properties<string, string> getCredentials = authzGen.GetDisallowedCredentials( + new OperationCode[] { OperationCode.Get }, + new string[] { RegionName }, 2); + Properties<string, string> getJavaProps = cGen.JavaProperties; + if (getCredentials == null || getCredentials.Size == 0) + { + Util.Log("DisallowPutsGets: Unable to obtain valid credentials " + + "with no GET permission; skipping this combination."); + continue; + } + + // Start servers with all required properties + string serverArgs = SecurityTestUtil.GetServerArgs(authenticator, + accessor, null, SecurityTestUtil.ConcatProperties(extraAuthProps, + extraAuthzProps), javaProps); + + // Start the two servers. + CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1, serverArgs); + Util.Log("Cacheserver 1 started."); + CacheHelper.StartJavaServerWithLocators(2, "GFECS2", 1, serverArgs); + Util.Log("Cacheserver 2 started."); + + // Start client1 with valid CREATE credentials + createCredentials = authzGen.GetAllowedCredentials( + new OperationCode[] { OperationCode.Put }, + new string[] { RegionName }, 1); + javaProps = cGen.JavaProperties; + Util.Log("DisallowPutsGets: For first client PUT credentials: " + + createCredentials); + m_client1.Call(SecurityTestUtil.CreateClientMU, RegionName, + CacheHelper.Locators, authInit, (Properties<string, string>)null, true); + + // Start client2 with invalid GET credentials + getCredentials = authzGen.GetDisallowedCredentials( + new OperationCode[] { OperationCode.Get }, + new string[] { RegionName }, 2); + javaProps = cGen.JavaProperties; + Util.Log("DisallowPutsGets: For second client invalid GET " + + "credentials: " + getCredentials); + m_client2.Call(SecurityTestUtil.CreateClientMU, RegionName, + CacheHelper.Locators, authInit, (Properties<string, string>)null, true); + + // Perform some put operations from client1 + m_client1.Call(DoPutsMU, 10, createCredentials, true); + + // Verify that the gets throw exception + m_client2.Call(DoGetsMU, 10, getCredentials, true, ExpectedResult.NotAuthorizedException); + + // Try to connect client2 with reader credentials + getCredentials = authzGen.GetAllowedCredentials( + new OperationCode[] { OperationCode.Get }, + new string[] { RegionName }, 5); + javaProps = cGen.JavaProperties; + Util.Log("DisallowPutsGets: For second client valid GET " + + "credentials: " + getCredentials); + m_client2.Call(SecurityTestUtil.CreateClientMU, RegionName, + CacheHelper.Locators, authInit, (Properties<string, string>)null, true); + + // Verify that the gets succeed + m_client2.Call(DoGetsMU, 10, getCredentials, true); + + // Verify that the puts throw exception + m_client2.Call(DoPutsMU, 10, getCredentials, true, ExpectedResult.NotAuthorizedException); + + m_client1.Call(Close); + m_client2.Call(Close); + + CacheHelper.StopJavaServer(1); + CacheHelper.StopJavaServer(2); + } + + CacheHelper.StopJavaLocator(1); + + CacheHelper.ClearEndpoints(); + CacheHelper.ClearLocators(); + } + + void runInvalidAccessor() + { + CacheHelper.SetupJavaServers(true, CacheXml1, CacheXml2); + CacheHelper.StartJavaLocator(1, "GFELOC"); + Util.Log("Locator started"); + + foreach (AuthzCredentialGenerator authzGen in GetAllGeneratorCombos(true)) + { + CredentialGenerator cGen = authzGen.GetCredentialGenerator(); + Util.Log("NIl:792:Current credential is = {0}", cGen); + + //if (cGen.GetClassCode() == CredentialGenerator.ClassCode.LDAP) + // continue; + + Properties<string, string> extraAuthProps = cGen.SystemProperties; + Properties<string, string> javaProps = cGen.JavaProperties; + Properties<string, string> extraAuthzProps = authzGen.SystemProperties; + string authenticator = cGen.Authenticator; + string authInit = cGen.AuthInit; + string accessor = authzGen.AccessControl; + + Util.Log("InvalidAccessor: Using authinit: " + authInit); + Util.Log("InvalidAccessor: Using authenticator: " + authenticator); + + // Start server1 with invalid accessor + string serverArgs = SecurityTestUtil.GetServerArgs(authenticator, + "com.gemstone.none", null, SecurityTestUtil.ConcatProperties(extraAuthProps, + extraAuthzProps), javaProps); + CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1, serverArgs); + Util.Log("Cacheserver 1 started."); + + // Client creation should throw exceptions + Properties<string, string> createCredentials = authzGen.GetAllowedCredentials( + new OperationCode[] { OperationCode.Put }, + new string[] { RegionName }, 3); + javaProps = cGen.JavaProperties; + Util.Log("InvalidAccessor: For first client PUT credentials: " + + createCredentials); + m_client1.Call(SecurityTestUtil.CreateClientMU, RegionName, + CacheHelper.Locators, authInit, (Properties<string, string>)null, true); + + // Now perform some put operations from client1 + m_client1.Call(DoPutsMU, 10, createCredentials, true, ExpectedResult.OtherException); + + Properties<string, string> getCredentials = authzGen.GetAllowedCredentials( + new OperationCode[] { OperationCode.Get }, + new string[] { RegionName }, 7); + javaProps = cGen.JavaProperties; + Util.Log("InvalidAccessor: For second client GET credentials: " + + getCredentials); + m_client2.Call(SecurityTestUtil.CreateClientMU, RegionName, + CacheHelper.Locators, authInit, (Properties<string, string>)null, true); + + // Now perform some put operations from client1 + m_client2.Call(DoGetsMU, 10, getCredentials, true, ExpectedResult.OtherException); + + // Now start server2 that has valid accessor + Util.Log("InvalidAccessor: Using accessor: " + accessor); + serverArgs = SecurityTestUtil.GetServerArgs(authenticator, + accessor, null, SecurityTestUtil.ConcatProperties(extraAuthProps, + extraAuthzProps), javaProps); + CacheHelper.StartJavaServerWithLocators(2, "GFECS2", 1, serverArgs); + Util.Log("Cacheserver 2 started."); + CacheHelper.StopJavaServer(1); + + // Client creation should be successful now + m_client1.Call(SecurityTestUtil.CreateClientMU, RegionName, + CacheHelper.Locators, authInit, (Properties<string, string>)null, true); + m_client2.Call(SecurityTestUtil.CreateClientMU, RegionName, + CacheHelper.Locators, authInit, (Properties<string, string>)null, true); + + // Now perform some put operations from client1 + m_client1.Call(DoPutsMU, 10, createCredentials, true); + + // Verify that the gets succeed + m_client2.Call(DoGetsMU, 10, getCredentials, true); + + m_client1.Call(Close); + m_client2.Call(Close); + + CacheHelper.StopJavaServer(2); + } + + CacheHelper.StopJavaLocator(1); + + CacheHelper.ClearEndpoints(); + CacheHelper.ClearLocators(); + } + + void runAllOpsWithFailover() + { + OperationWithAction[] allOps = { + // Test CREATE and verify with a GET + new OperationWithAction(OperationCode.Put, 3, OpFlags.CheckNotAuthz, 4), + new OperationWithAction(OperationCode.Put), + new OperationWithAction(OperationCode.Get, 3, OpFlags.CheckNoKey + | OpFlags.CheckNotAuthz, 4), + new OperationWithAction(OperationCode.Get, 2, OpFlags.CheckNoKey, 4), + // OPBLOCK_END indicates end of an operation block; the above block of + // three operations will be first executed on server1 and then on + // server2 after failover + + OperationWithAction.OpBlockEnd, + + // Test GetServerKeys (KEY_SET) operation. + new OperationWithAction(OperationCode.GetServerKeys), + new OperationWithAction(OperationCode.GetServerKeys, 3, OpFlags.CheckNotAuthz, 4), + + OperationWithAction.OpBlockEnd, + + // Test UPDATE and verify with a GET + new OperationWithAction(OperationCode.Put, 3, OpFlags.UseNewVal + | OpFlags.CheckNotAuthz, 4), + new OperationWithAction(OperationCode.Put, 1, OpFlags.UseNewVal, 4), + new OperationWithAction(OperationCode.Get, 2, OpFlags.UseOldConn + | OpFlags.UseNewVal, 4), + + OperationWithAction.OpBlockEnd, + + // Test DESTROY and verify with a GET and that key should not exist + new OperationWithAction(OperationCode.Destroy, 3, OpFlags.UseNewVal + | OpFlags.CheckNotAuthz, 4), + new OperationWithAction(OperationCode.Destroy), + new OperationWithAction(OperationCode.Get, 2, OpFlags.UseOldConn + | OpFlags.CheckFail, 4), + // Repopulate the region + new OperationWithAction(OperationCode.Put, 1, OpFlags.UseNewVal, 4), + + OperationWithAction.OpBlockEnd, + + // Check QUERY + new OperationWithAction(OperationCode.Put), + new OperationWithAction(OperationCode.Query, 3, + OpFlags.CheckNotAuthz, 4), + new OperationWithAction(OperationCode.Query), + + OperationWithAction.OpBlockEnd, + + // UPDATE and test with GET + new OperationWithAction(OperationCode.Put), + new OperationWithAction(OperationCode.Get, 2, OpFlags.UseOldConn + | OpFlags.LocalOp, 4), + + // UPDATE and test with GET for no updates + new OperationWithAction(OperationCode.Put, 1, OpFlags.UseOldConn + | OpFlags.UseNewVal, 4), + new OperationWithAction(OperationCode.Get, 2, OpFlags.UseOldConn + | OpFlags.LocalOp, 4), + OperationWithAction.OpBlockEnd, + + /// PutAll, GetAll, ExecuteCQ and ExecuteFunction ops + new OperationWithAction(OperationCode.PutAll), + // NOTE: GetAll depends on previous PutAll so it should happen right after. + new OperationWithAction(OperationCode.GetAll), + new OperationWithAction(OperationCode.RemoveAll), + //new OperationWithAction(OperationCode.ExecuteCQ), + new OperationWithAction(OperationCode.ExecuteFunction), + + OperationWithAction.OpBlockEnd, + + // UPDATE and test with GET + new OperationWithAction(OperationCode.Put, 2), + new OperationWithAction(OperationCode.Get, 1, OpFlags.UseOldConn + | OpFlags.LocalOp, 4), + + // UPDATE and test with GET for no updates + new OperationWithAction(OperationCode.Put, 2, OpFlags.UseOldConn + | OpFlags.UseNewVal, 4), + new OperationWithAction(OperationCode.Get, 1, OpFlags.UseOldConn + | OpFlags.LocalOp, 4), + + OperationWithAction.OpBlockEnd, + + // UPDATE and test with GET + new OperationWithAction(OperationCode.Put), + new OperationWithAction(OperationCode.Get, 2, OpFlags.UseOldConn + | OpFlags.LocalOp, 4), + + // UPDATE and test with GET for no updates + new OperationWithAction(OperationCode.Put, 1, OpFlags.UseOldConn + | OpFlags.UseNewVal, 4), + new OperationWithAction(OperationCode.Get, 2, OpFlags.UseOldConn + | OpFlags.LocalOp, 4), + + OperationWithAction.OpBlockEnd, + + // Do REGION_DESTROY of the sub-region and check with GET + new OperationWithAction(OperationCode.Put, 1, OpFlags.UseSubRegion, + 8), + new OperationWithAction(OperationCode.RegionDestroy, 3, + OpFlags.UseSubRegion | OpFlags.CheckNotAuthz, 1), + new OperationWithAction(OperationCode.RegionDestroy, 1, + OpFlags.UseSubRegion, 1), + new OperationWithAction(OperationCode.Get, 2, OpFlags.UseSubRegion + | OpFlags.CheckNoKey | OpFlags.CheckException, 8), + + // Do REGION_DESTROY of the region and check with GET + new OperationWithAction(OperationCode.RegionDestroy, 3, + OpFlags.CheckNotAuthz, 1), + new OperationWithAction(OperationCode.RegionDestroy, 1, OpFlags.None, + 1), + new OperationWithAction(OperationCode.Get, 2, OpFlags.UseOldConn + | OpFlags.CheckNoKey | OpFlags.CheckException, 8), + + // Skip failover for region destroy since it shall fail + // without restarting the server + OperationWithAction.OpBlockNoFailover + }; + RunOpsWithFailover(allOps, "AllOpsWithFailover", true); + } + + void runThinClientWriterExceptionTest() + { + CacheHelper.SetupJavaServers(true, CacheXml1); + CacheHelper.StartJavaLocator(1, "GFELOC"); + Util.Log("Locator started"); + + foreach (AuthzCredentialGenerator authzGen in GetAllGeneratorCombos(true)) + { + for (int i = 1; i <= 2; ++i) + { + CredentialGenerator cGen = authzGen.GetCredentialGenerator(); + //TODO: its not working for multiuser mode.. need to fix later + if (cGen.GetClassCode() == CredentialGenerator.ClassCode.PKCS) + continue; + Properties<string, string> extraAuthProps = cGen.SystemProperties; + Properties<string, string> javaProps = cGen.JavaProperties; + Properties<string, string> extraAuthzProps = authzGen.SystemProperties; + string authenticator = cGen.Authenticator; + string authInit = cGen.AuthInit; + string accessor = authzGen.AccessControl; + + Util.Log("ThinClientWriterException: Using authinit: " + authInit); + Util.Log("ThinClientWriterException: Using authenticator: " + authenticator); + Util.Log("ThinClientWriterException: Using accessor: " + accessor); + + // Start servers with all required properties + string serverArgs = SecurityTestUtil.GetServerArgs(authenticator, + accessor, null, SecurityTestUtil.ConcatProperties(extraAuthProps, + extraAuthzProps), javaProps); + + // Start the server. + CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1, serverArgs); + Util.Log("Cacheserver 1 started."); + + // Start client1 with valid CREATE credentials + Properties<string, string> createCredentials = authzGen.GetDisallowedCredentials( + new OperationCode[] { OperationCode.Put }, + new string[] { RegionName }, 1); + javaProps = cGen.JavaProperties; + Util.Log("DisallowPuts: For first client PUT credentials: " + + createCredentials); + m_client1.Call(SecurityTestUtil.CreateClientR0, RegionName, + CacheHelper.Locators, authInit, createCredentials); + + Util.Log("Creating region in client1 , no-ack, no-cache, with listener and writer"); + m_client1.Call(CreateRegion, CacheHelper.Locators, + true, true, true); + m_client1.Call(RegisterAllKeys, new string[] { RegionName }); + + try + { + Util.Log("Trying put Operation"); + m_client1.Call(DoPut); + Util.Log(" Put Operation Successful"); + Assert.Fail("Should have got NotAuthorizedException during put"); + } + catch (NotAuthorizedException) + { + Util.Log("NotAuthorizedException Caught"); + Util.Log("Success"); + } + catch (Exception other) + { + Util.Log("Stack trace: {0} ", other.StackTrace); + Util.Log("Got exception : {0}", + other.Message); + } + m_client1.Call(CheckAssert); + // Do LocalPut + m_client1.Call(DoLocalPut); + + m_client1.Call(Close); + + CacheHelper.StopJavaServer(1); + } + } + CacheHelper.StopJavaLocator(1); + CacheHelper.ClearEndpoints(); + CacheHelper.ClearLocators(); + } + + #region Tests + + [Test] + public void TestCQ() + { + runCQTest(); + } + + [Test] + public void TestDurableCQ() + { + //for all run real cache will be true + //logical cache true/false and durable cq true/false combination.... + //result..whether events should be there or not + runDurableCQTest(false, true, true);//no usercache close as it will close user's durable cq + runDurableCQTest(true, false, false); + runDurableCQTest(false, true, true); + runDurableCQTest(false, false, false); + } + + [Test] + public void AllowPutsGets() + { + runAllowPutsGets(); + } + + [Test] + public void DisallowPutsGets() + { + runDisallowPutsGets(); + } + + [Test] + public void AllOpsWithFailover() + { + runAllOpsWithFailover(); + } + + [Test] + public void ThinClientWriterExceptionTest() + { + runThinClientWriterExceptionTest(); + } + #endregion + } +}