예제 #1
0
        private async Task PolicyCreateExamples()
        {
            // Create a policy with multiple sub path objects.
            VaultPolicyContainer VP = new VaultPolicyContainer("TestingABC");


            VaultPolicyPathItem vpi = new VaultPolicyPathItem("secret/TestA")
            {
                DeleteAllowed = true,
                ReadAllowed   = true,
                CreateAllowed = true
            };

            VP.AddPolicyPathObject(vpi);


            VaultPolicyPathItem vpi2 = new VaultPolicyPathItem("secret/TestB");

            vpi2.ListAllowed = true;
            VP.AddPolicyPathObject(vpi2);


            VaultPolicyPathItem vpi3 = new VaultPolicyPathItem("secret/TestC");

            vpi3.ListAllowed   = true;
            vpi3.DeleteAllowed = true;
            vpi3.ReadAllowed   = true;
            vpi3.SudoAllowed   = true;
//			VP.PolicyPaths.Add(vpi3);


            var rc = await _vaultSystemBackend.SysPoliciesACLCreate(VP);
        }
예제 #2
0
        /// <summary>
        /// Builds a policy for the full admins of the vault.
        /// </summary>
        /// <returns></returns>
        internal async Task <bool> BuildAdminPolicy()
        {
            // Create the Permission Paths

            // FullAdmins will have full control to the HashPath
            VaultPolicyPathItem hashPath = new VaultPolicyPathItem(true, VAULT_HASH_NAME, "/*");

            hashPath.CRUDAllowed = true;

            // FullAdmins will have full control to the AppKey Vault
            VaultPolicyPathItem appPath = new VaultPolicyPathItem(true, VAULT_KEYCRYPT_NAME, "/*");

            appPath.CRUDAllowed = true;



            // Now create the policy
            VaultPolicyContainer adminContainer = new VaultPolicyContainer("FullAdmin");

            adminContainer.AddPolicyPathObject(hashPath);
            adminContainer.AddPolicyPathObject(appPath);

            bool success = await _vaultSystemBackend.SysPoliciesACLCreate(adminContainer);


            List <string> adminPolicies = new List <string>();

            adminPolicies.Add(adminContainer.Name);

            // Associate the Admin Active Directory group to the policy.
            success = await _ldapAuthEngine.CreateGroupToPolicyMapping("_IT-SystemEngineers", adminPolicies);

            List <string> groups = await _ldapAuthEngine.ListGroups();


            return(success);
        }
예제 #3
0
        private async Task <(VaultPolicyContainer polContainer, VaultPolicyPathItem vppi)> SetupPolicy(string policyAppPath)
        {
            // B.  Lets create a policy for root path.
            VaultPolicyPathItem vppi = new VaultPolicyPathItem(_beName, policyAppPath);

            vppi.Denied = true;

            // C.  Create the Actual Policy container
            string polName = _uniqueKeys.GetKey("polCon");
            VaultPolicyContainer polCon1 = new VaultPolicyContainer(polName);

            polCon1.AddPolicyPathObject(vppi);

            // D.  Save Policy to Vault Instance.
            Assert.True(await _vaultSystemBackend.SysPoliciesACLCreate(polCon1), "SetupPolicy: A10:  Saving the initial policy to Vault Instance failed.");

            return(polCon1, vppi);
        }
예제 #4
0
        /// <summary>
        /// Creates the policies that this scenario needs.
        ///  - polRoleMaster - Has FC on everything
        ///  - polRole1 - full control on /path1 and everything below it.
        ///  - polRole2 - Read Only access on /path1 and everything below it.  No List capability
        ///  - polAppA  - Full control on /appData/appA
        ///  - polAppB  - Full control on /appData/appB
        ///  - polShared - Read Only access on /shared/*
        /// </summary>
        /// <returns></returns>
        private async Task CreatePoliciesController()
        {
            // (Create / Get existing) policyContainer objects.
            _polRoleMaster = await GetPolicy("polRoleMaster");

            _polRole1 = await GetPolicy("polRole1");

            _polRole2 = await GetPolicy("polRole2");

            _polRoleAppA = await GetPolicy("polRoleAppA");

            _polRoleAppB = await GetPolicy("polRoleAppB");

            _polSharedDB = await GetPolicy("polSharedDB");

            _polSharedEmail = await GetPolicy("polSharedEmail");

            _polCommon = await GetPolicy("appCommon");

            // RoleMaster Policy.
            // Has access to everything in the KV2 backend.
            VaultPolicyPathItem vpItem1 = new VaultPolicyPathItem(_beKV2Name + "/data/*");

            vpItem1.FullControl = true;
            _polRoleMaster.AddPolicyPathObject(vpItem1);
            if (!(await _vaultSystemBackend.SysPoliciesACLCreate(_polRoleMaster)))
            {
                Console.WriteLine("Unable to save the policies for the CreateRoles method");
            }

            // Role1 Policy.  FC on path1 and AppData
            VaultPolicyPathItem vppiR1P1 = new VaultPolicyPathItem(true, _beKV2Name, Constants.path1 + "/*");

            vppiR1P1.FullControl = true;
            VaultPolicyPathItem vppiR1PAppData = new VaultPolicyPathItem(true, _beKV2Name, Constants.appData + "/*");

            vppiR1PAppData.FullControl = true;

            _polRole1.AddPolicyPathObject(vppiR1P1);
            _polRole1.AddPolicyPathObject(vppiR1PAppData);
            if (!(await _vaultSystemBackend.SysPoliciesACLCreate(_polRole1)))
            {
                Console.WriteLine("Unable to save the policies for the Policy {0}", _polRole1.Name);
                throw new ApplicationException("Error saving Role1 Policies");
            }


            if (!(await _vaultSystemBackend.SysPoliciesACLCreate(_polRole1)))
            {
                Console.WriteLine("Unable to save the policies for the Policy {0}", _polRole1.Name);
            }


            // Role2 Policy.  RO on path1
            VaultPolicyPathItem vppiR2P1 = new VaultPolicyPathItem(true, _beKV2Name, Constants.path1 + "/*");

            vppiR2P1.ReadAllowed = true;
            _polRole2.AddPolicyPathObject(vppiR2P1);
            if (!(await _vaultSystemBackend.SysPoliciesACLCreate(_polRole2)))
            {
                Console.WriteLine("Unable to save the policies for the Policy {0}", _polRole2.Name);
            }

            VaultPolicyPathItem vpitemVar = new VaultPolicyPathItem(true, _beKV2Name, "appData/{{identity.entity.name}}/*");

            vpitemVar.FullControl = true;
            _polCommon.AddPolicyPathObject(vpitemVar);
            if (!(await _vaultSystemBackend.SysPoliciesACLCreate(_polCommon)))
            {
                Console.WriteLine("Unable to save the policies for the Policy {0}", _polCommon.Name);
            }

            // RoleAppA Policy.  FC on apps/AppA
            VaultPolicyPathItem vpItemA1 = new VaultPolicyPathItem(true, _beKV2Name, "appData/appA/*");

            vpItemA1.FullControl = true;
            _polRoleAppA.AddPolicyPathObject(vpItemA1);
            if (!(await _vaultSystemBackend.SysPoliciesACLCreate(_polRoleAppA)))
            {
                Console.WriteLine("Unable to save the policies for the Policy {0}", _polRoleAppA.Name);
            }

            // RoleAppB Policy.  FC on apps/AppB
            VaultPolicyPathItem vpItemB1 = new VaultPolicyPathItem(true, _beKV2Name, "appData/appB/*");

            vpItemB1.FullControl = true;
            _polRoleAppB.AddPolicyPathObject(vpItemB1);
            if (!(await _vaultSystemBackend.SysPoliciesACLCreate(_polRoleAppB)))
            {
                Console.WriteLine("Unable to save the policies for the Policy {0}", _polRoleAppB.Name);
            }

            // Shared DB Policy
            VaultPolicyPathItem vpITemDB = new VaultPolicyPathItem(true, _beKV2Name, "shared/dbConfig");

            _polSharedDB.AddPolicyPathObject(vpITemDB);
            vpITemDB.ReadAllowed = true;
            if (!(await _vaultSystemBackend.SysPoliciesACLCreate(_polSharedDB)))
            {
                Console.WriteLine("Unable to save the policies for the Policy {0}", _polSharedDB.Name);
            }


            // Shared Email Policy
            VaultPolicyPathItem vpItemEmail = new VaultPolicyPathItem(true, _beKV2Name, "shared/Email");

            vpItemEmail.ReadAllowed = true;
            _polSharedEmail.AddPolicyPathObject(vpItemEmail);
            if (!(await _vaultSystemBackend.SysPoliciesACLCreate(_polSharedEmail)))
            {
                Console.WriteLine("Unable to save the policies for the Policy {0}", _polSharedEmail.Name);
            }
        }
예제 #5
0
        /// <summary>
        /// Internal routine that processes the returned string from Vault and parses it into a VaultPolicyContainer object.
        /// </summary>
        /// <param name="data">The string data returned by Vault.</param>
        /// <param name="vp">VaultPolicyContainer object that should be filled in with the values from Vault.</param>
        /// <returns>True if successful.</returns>
        private bool ParseACLPaths(string data, VaultPolicyContainer vp)
        {
            string [] strDelimiters = { " ", "," };
            string [] pathObjects   = data.Split(strDelimiters, StringSplitOptions.RemoveEmptyEntries);

            bool         starting    = true;
            const string sPATH       = "|PATH|";
            const string sCAPA       = "|CAPA|";
            const string sLISTSTART  = "{";
            const string sLISTEND    = "}";
            const string sARRAYSTART = "[";
            const string sARRAYEND   = "]";

            const short iSTARTING    = 0;
            const short iPATHLIST    = 1;
            const short iPATHOPTIONS = 2;
            const short iCAP         = 200;

            List <string> keyWords = new List <string>()
            {
                sPATH,
                sCAPA,
                sLISTSTART,
                sLISTEND,
                sARRAYSTART,
                sARRAYEND
            };


            // We need to create a default object or else it will not compile.
            VaultPolicyPathItem newPathObj = new VaultPolicyPathItem("dummy/dummy2");

            // Used so we can determine what type of path the permission is being applied to.  Complicated.
            string KV2Path = "";


            short iStep = iSTARTING;

            // Now process thru the data elements.
            for (int i = 0; i < pathObjects.Length; i++)
            {
                switch (iStep)
                {
                case iSTARTING:

                    // PATH must be first value if starting.
                    if (pathObjects [i] == sPATH)
                    {
                        iStep++;
                        starting = true;

                        // Make sure the next item is not a keyword.
                        i++;
                        if (keyWords.Contains(pathObjects [i]))
                        {
                            throw new FormatException("Found path keyword, but no value supplied for path NAME");
                        }
                        else
                        {
                            VaultPolicyPathItem tempItem = new VaultPolicyPathItem(pathObjects [i]);
                            KV2Path = tempItem.KV2_PathID;

                            // If there is not a Policy permission object for this path in the Policy Container then use the new one.  Otherwise use existing.
                            if (!vp.PolicyPaths.TryGetValue(tempItem.Key, out newPathObj))
                            {
                                newPathObj = tempItem;
                                vp.AddPolicyPathObject(newPathObj);
                            }
                        }
                    }
                    else
                    {
                        string err = string.Join("", "First element must be the PATH identifier.  Found: ", pathObjects [i].ToString(), " instead.");
                        throw new FormatException(err);
                    }

                    break;

                case iPATHLIST:

                    // We should be looking for the iPATH List identifier - {
                    if ((pathObjects [i] == sLISTSTART) && (starting))
                    {
                        starting = false;

                        // Now see what type of parameter the next item is.
                        i++;
                        switch (pathObjects [i])
                        {
                        case sCAPA:

                            // It's a capabilities type.  Now add items until we reach the end of the capabilities list.
                            iStep = iCAP;

                            // The next item should be opening array.
                            if (pathObjects [++i] != sARRAYSTART)
                            {
                                throw new FormatException("Found the capabilities identifier, but did not find the opening array symbol - [");
                            }

                            break;
                        } // END switch pathObjects[i]
                    }     // END if sLISTSTART && starting

                    break;

                case iCAP:
                    if (pathObjects [i] == sLISTSTART)
                    {
                        iStep++;
                    }
                    else if (pathObjects [i] == sARRAYEND)
                    {
                        // Done with the capabilities.
                        iStep = iPATHOPTIONS;
                    }
                    else
                    {
                        // It must be a valid capability  AND we need to know what the path Prefix is so we can set the appropriate permission.
                        switch (pathObjects [i])
                        {
                        case "create":
                            newPathObj.CreateAllowed = true;
                            break;

                        case "read":
                            switch (KV2Path)
                            {
                            case "":
                            case "data":
                                newPathObj.ReadAllowed = true;
                                break;

                            case "metadata":
                                newPathObj.ExtKV2_ViewMetaData = true;
                                break;
                            }

                            newPathObj.ReadAllowed = true;
                            break;

                        case "update":
                            switch (KV2Path)
                            {
                            case "":
                            case "data":
                                newPathObj.UpdateAllowed = true;
                                break;

                            case "delete":
                                newPathObj.ExtKV2_DeleteAnyKeyVersion = true;
                                break;

                            case "undelete":
                                newPathObj.ExtKV2_UndeleteSecret = true;
                                break;

                            case "destroy":
                                newPathObj.ExtKV2_DestroySecret = true;
                                break;

                            default:
                                throw new DataException(
                                          "Trying to set Update Permission for a VaultPolicyPathItem object resulted in arriving at an unexpected code path.  Do not know what to do.  Aborting.");
                            }

                            break;

                        case "delete":
                            switch (KV2Path)
                            {
                            case "":
                            case "data":
                                newPathObj.DeleteAllowed = true;
                                break;

                            case "metadata":
                                newPathObj.ExtKV2_DeleteMetaData = true;
                                break;

                            default:
                                throw new DataException(
                                          "Trying to set Delete permission for a VaultPolicyPathItem object resulted in arriving at an unexpected code path.  Do not know what to do.  Aborting.");
                            }

                            break;

                        case "list":
                            switch (KV2Path)
                            {
                            case "":
                            case "data":
                                newPathObj.ListAllowed = true;
                                break;

                            case "metadata":
                                newPathObj.ExtKV2_ListMetaData = true;
                                break;

                            default:
                                throw new DataException(
                                          "Trying to set List permission for a VaultPolicyPathItem object resulted in arriving at an unexpected code path.  Do not know what to do.  Aborting.");
                            }

                            break;

                        case "sudo":
                            newPathObj.SudoAllowed = true;
                            break;

                        case "deny":
                            newPathObj.Denied = true;
                            break;
                        }
                    }

                    break;

                // Search for PATH options
                case iPATHOPTIONS:
                    if (pathObjects [i] == sLISTEND)
                    {
                        // Done with this path object.
                        iStep = iSTARTING;
                    }

                    break;
                } // END SWITCH istep
            }     // END of for loop.

            return(true);
        } // END of method.
예제 #6
0
        public async Task TestTemplatedPolicies()
        {
            string appBE = _uniqueKeys.GetKey("appTE");
            string kv2BE = _uniqueKeys.GetKey("kv2TE");


            // 1A - Setup backends needed for testing.
            // We need to setup a KV2 Secrets engine and also an AppRole Backend.
            // Create an Authentication method of App Role.	- This only needs to be done when the Auth method is created.
            AuthMethod am = new AuthMethod(appBE, EnumAuthMethods.AppRole);
            await _vaultSystemBackend.AuthEnable(am);

            // Create a KV2 Secret Mount if it does not exist.
            VaultSystemBackend vaultSystemBackend = new VaultSystemBackend(_vaultAgentAPI.TokenID, _vaultAgentAPI);
            await vaultSystemBackend.SysMountCreate(kv2BE, "ClientTest KeyValue 2 Secrets", EnumSecretBackendTypes.KeyValueV2);



            // 1B. Now we can connect to the backends.
            VaultAgentAPI vault = await VaultServerRef.ConnectVault("PolicyBECapa");

            //new VaultAgentAPI("capability", _vaultAgentAPI.IP, _vaultAgentAPI.Port, _vaultAgentAPI.TokenID);
            AppRoleAuthEngine authEngine   = (AppRoleAuthEngine)vault.ConnectAuthenticationBackend(EnumBackendTypes.A_AppRole, appBE, appBE);
            KV2SecretEngine   secretEngine =
                (KV2SecretEngine)vault.ConnectToSecretBackend(EnumSecretBackendTypes.KeyValueV2, "KV2 Secrets", kv2BE);
            IdentitySecretEngine idEngine = (IdentitySecretEngine)_vaultAgentAPI.ConnectToSecretBackend(EnumSecretBackendTypes.Identity);

            // 1C - Write out some values.
            TestContext.WriteLine("App Role Auth Backend:   {0}", authEngine.Name);
            TestContext.WriteLine("KV2 Secret Backend:      {0}", secretEngine.Name);


            // 2. Setup the policy to provide the permissions to test against.
            VaultPolicyContainer policyContainer = new VaultPolicyContainer("capa");


            // 3. Now create an App Role & Secret ID.  The app role in this case has no policies - it will get them from the Entity.
            string  roleName = _uniqueKeys.GetKey("role");
            AppRole appRole  = new AppRole(roleName);

            appRole = await authEngine.SaveRoleAndReturnRoleObject(appRole);

            AppRoleSecret secretID = await authEngine.CreateSecretID(appRole.Name);



            // 4.  Create an Entity and Entity Alias.
            // 4A.  Get Authentication backend accessor.
            Dictionary <string, AuthMethod> authMethods = await vaultSystemBackend.AuthListAll();

            AuthMethod authMethod = authMethods[authEngine.Name + "/"];

            Assert.IsNotNull(authMethod, "B10:  Expected to find the authentication backend.  But did not.");
            string mountAccessor = authMethod.Accessor;

            // 4B.  Create an entity for the app role.
            string name   = _uniqueKeys.GetKey("EAR");
            Entity entity = new Entity(roleName);

            entity.Policies.Add(policyContainer.Name);

            // 4C.  Now save entity
            entity = await idEngine.SaveEntity(entity);

            Assert.IsNotNull(entity, "B20:  Expected to receive an Entity object");


            // 4D. Write out some values
            TestContext.WriteLine("Entity Name:      {0}", entity.Name);
            TestContext.WriteLine("Entity ID:        {0}", entity.Id);


            // 5. Create an alias that ties the Entity we just created to the AppRole in the authentication backend.
            Guid roleID    = new Guid(appRole.RoleID);
            Guid aliasGuid = await idEngine.SaveAlias(entity.Id, mountAccessor, appRole.RoleID);

            Assert.AreNotEqual(aliasGuid.ToString(), Guid.Empty.ToString());

            // 5B.  Re-read the entity - it should now contain the alias.
            Entity fullEntity = await idEngine.ReadEntity(entity.Id);

            Assert.AreEqual(1, fullEntity.Aliases.Count, "B30:  Expected the full entity to now contain the alias ID.");


            // 6.  Now define the policy and save to Vault.
            policyContainer.PolicyPaths.Clear();
            string appPath1           = "app/{{identity.entity.aliases." + mountAccessor + ".name}}/*";
            VaultPolicyPathItem vppi1 = new VaultPolicyPathItem(kv2BE, "data/" + appPath1);
            VaultPolicyPathItem vppi2 = new VaultPolicyPathItem(kv2BE, "data/app/appA/subItem/*");
            VaultPolicyPathItem vppi3 = new VaultPolicyPathItem(kv2BE, "data/shared/common/*");
            VaultPolicyPathItem vppi4 = new VaultPolicyPathItem(kv2BE, "data/shared/info/*");

            vppi1.FullControl = true;
            vppi2.FullControl = true;
            vppi3.CRUDAllowed = true;
            vppi4.ReadAllowed = true;


            policyContainer.AddPolicyPathObject(vppi1);
            policyContainer.AddPolicyPathObject(vppi2);
            policyContainer.AddPolicyPathObject(vppi3);
            policyContainer.AddPolicyPathObject(vppi4);

            await _vaultSystemBackend.SysPoliciesACLCreate(policyContainer);


            // 7.  Now we can login to get a token..  Validate the entity policy has been set on token.
            Token token = await authEngine.Login(appRole.RoleID, secretID.ID);

            Assert.IsNotNull("B40:  A valid token was not received.");

            CollectionAssert.Contains(token.IdentityPolicies, policyContainer.Name, "B100:  Did not find the policy that should have been applied from the entity.");


            // 8.  Now we can finally test the capabilities of that token.
            List <string> paths    = new List <string>();
            string        pathBase = kv2BE + "/data/app/" + fullEntity.Aliases[0].Name + "/config";
            string        metaBase = kv2BE + "/metadata/app" + fullEntity.Aliases[0].Name + "/config";
            string        path1    = pathBase;
            string        path2    = pathBase + "/subItem";
            string        path3    = kv2BE + "/data/shared/common/testEntry";

            paths.Add(path1);
            paths.Add(path2);
            paths.Add(path3);


            Dictionary <string, List <string> > permissions;

            permissions = await _vaultSystemBackend.GetTokenCapabilityOnPaths(token.ID, paths);


            // 9. Validate the permission results.
            Assert.AreEqual(3, permissions.Count, "B130:  Expected to receive 3 permission objects back.");
            Assert.AreEqual(6, permissions[path1].Count, "B140:  Expected the item: " + path1 + " to contain 6 permissions.");
            Assert.AreEqual(6, permissions[path2].Count, "B150:  Expected the item: " + path2 + " to contain 6 permissions.");
            Assert.AreEqual(4, permissions[path3].Count, "B160:  Expected the item: " + path3 + " to contain 3 permissions.");

            CollectionAssert.Contains(permissions[path3], "create", "B170:  Expected the permission to be create for path: " + path3);
            CollectionAssert.Contains(permissions[path3], "read", "B171:  Expected the permission to be read for path: " + path3);
            CollectionAssert.Contains(permissions[path3], "update", "B172:  Expected the permission to be update for path: " + path3);
            CollectionAssert.Contains(permissions[path3], "delete", "B173:  Expected the permission to be read for path: " + path3);


            // 10. Try to create a secret at path 1
            string    secName1 = _uniqueKeys.GetKey("sec1");
            KV2Secret secret1  = new KV2Secret("config", "app/" + fullEntity.Aliases[0].Name);

            secret1.Attributes.Add("version", "v12.2");
            Assert.True(await secretEngine.SaveSecret(secret1, KV2EnumSecretSaveOptions.AlwaysAllow), "B200:  Save of secret did not work.  Check permissions.");


            // 11. Create and delete a secret at path3.
            KV2Secret secret2 = new KV2Secret("options", "shared/common/testEntry");

            secret2.Attributes.Add("color", "blue");
            secret2.Attributes.Add("size", "Large");
            Assert.True(await secretEngine.SaveSecret(secret2, KV2EnumSecretSaveOptions.AlwaysAllow), "B210:  Save of secret2 failed.");

            // Now delete it.
            Assert.True(await secretEngine.DeleteSecretVersion(secret2));
        }
예제 #7
0
        public async Task TestCapabilitiesFunctionality()
        {
            string appBE = _uniqueKeys.GetKey("appBE");
            string kv2BE = _uniqueKeys.GetKey("kv2BE");


            // 1 - Setup backends needed for testing.
            // We need to setup a KV2 Secrets engine and also an AppRole Backend.
            // Create an Authentication method of App Role.	- This only needs to be done when the Auth method is created.
            AuthMethod am = new AuthMethod(appBE, EnumAuthMethods.AppRole);
            await _vaultSystemBackend.AuthEnable(am);

            // Create a KV2 Secret Mount if it does not exist.
            await _vaultSystemBackend.SysMountCreate(kv2BE, "ClientTest KeyValue 2 Secrets", EnumSecretBackendTypes.KeyValueV2);


            // Now we create secret backend
            VaultAgentAPI vault = await VaultServerRef.ConnectVault("PolicyBeCapa2");

            AppRoleAuthEngine authEngine   = (AppRoleAuthEngine)vault.ConnectAuthenticationBackend(EnumBackendTypes.A_AppRole, appBE, appBE);
            KV2SecretEngine   secretEngine =
                (KV2SecretEngine)vault.ConnectToSecretBackend(EnumSecretBackendTypes.KeyValueV2, "KV2 Secrets", kv2BE);


            // 2. Setup the policy to provide the permissions to test against.
            VaultPolicyContainer policyContainer = new VaultPolicyContainer("capa");

            VaultPolicyPathItem vppi1 = new VaultPolicyPathItem(kv2BE, "data/app/appA/*");
            VaultPolicyPathItem vppi2 = new VaultPolicyPathItem(kv2BE + "data/app/appA/subItem/*");
            VaultPolicyPathItem vppi3 = new VaultPolicyPathItem(kv2BE + "metadata/app/appA/*");
            VaultPolicyPathItem vppi4 = new VaultPolicyPathItem(kv2BE + "data/shared/*");

            vppi1.FullControl = true;
            vppi2.FullControl = true;
            vppi3.ReadAllowed = true;
            vppi4.ReadAllowed = true;

            policyContainer.AddPolicyPathObject(vppi1);
            policyContainer.AddPolicyPathObject(vppi2);
            policyContainer.AddPolicyPathObject(vppi3);
            policyContainer.AddPolicyPathObject(vppi4);

            await _vaultSystemBackend.SysPoliciesACLCreate(policyContainer);


            // 3. Now create an App Role & Secret ID
            string  roleName = _uniqueKeys.GetKey("role");
            AppRole appRole  = new AppRole(roleName);

            appRole.Policies.Add(policyContainer.Name);
            appRole = await authEngine.SaveRoleAndReturnRoleObject(appRole);

            AppRoleSecret secretID = await authEngine.CreateSecretID(appRole.Name);


            // 4.  Now we can create a token against that
            Token token = await authEngine.Login(appRole.RoleID, secretID.ID);


            // 5.  Now we can finally test the capabilities of that token.
            List <string> paths = new List <string>();
            string        path1 = kv2BE + "/data/app/appA/subItem";
            string        path2 = kv2BE + "/data/app/appB/subItem";
            string        path3 = kv2BE + "/noaccess/app/appA";
            string        path4 = kv2BE + "/data/noaccess/app/appA/subItem";

            paths.Add(path1);
            paths.Add(path2);
            paths.Add(path3);
            paths.Add(path4);



            Dictionary <string, List <string> > permissions;

            permissions = await _vaultSystemBackend.GetTokenCapabilityOnPaths(token.ID, paths);

            // 6. Validate the results.
            Assert.AreEqual(4, permissions.Count, "A10:  Expected to receive 4 permission objects back.");
            Assert.AreEqual(6, permissions[path1].Count, "A20:  Expected the item: " + path1 + " to contain 6 permissions.");
            Assert.AreEqual(1, permissions[path2].Count, "A30:  Expected the item: " + path2 + " to contain 1 deny permission.");
            CollectionAssert.Contains(permissions[path2], "deny", "A35:  Expected the permission to be deny for path: " + path2);
            Assert.AreEqual(1, permissions[path3].Count, "A40:  Expected the item: " + path3 + " to contain 1 deny permission.");
            CollectionAssert.Contains(permissions[path3], "deny", "A35:  Expected the permission to be deny for path: " + path3);
            Assert.AreEqual(1, permissions[path4].Count, "A40:  Expected the item: " + path4 + " to contain 1 deny permission.");
            CollectionAssert.Contains(permissions[path4], "deny", "A35:  Expected the permission to be deny for path: " + path4);
        }