clicache/integration-test/ThinClientSecurityAuthzTestBaseN.cs (809 lines of code) (raw):

/* * 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().NewQuery<object>("SELECT DISTINCT * FROM " + region.FullPath).Execute(); } Assert.IsNotNull(queryResults); if (!CheckFlags(flags, OpFlags.CheckFail)) { Assert.AreEqual(numOps, queryResults.Size); } var querySet = new List<string>((int) 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 qs; if (pool != null) { qs = pool.GetQueryService(); } else { //qs = CacheHelper.DCache.GetQueryService(); 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(); } } } }