/// <summary>
        /// Returns a Token object of the Token that is currently being used to access Vault with.  This routine also exists within the VaultAuthentication Backend.
        /// </summary>
        /// <remarks>This routine and the one in VaultAuthenticationBackend should be kept in sync.</remarks>
        /// <returns>Token object of the current token used to access Vault Instance with.</returns>
        public async Task <Token> GetMyTokenInfo()
        {
            string path = "/v1/auth/token/lookup-self";

            try {
                VaultDataResponseObjectB vdro = await ParentVault._httpConnector.GetAsync_B(path, "GetMyTokenInfo");

                if (vdro.Success)
                {
                    return(await vdro.GetDotNetObject <Token>());
                }
                else
                {
                    throw new VaultUnexpectedCodePathException();
                }
            }

            // If Vault is telling us it is a bad token, then return null.
            catch (VaultForbiddenException e) {
                if (e.Message.Contains("bad token"))
                {
                    return(null);
                }
                else
                {
                    throw e;
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Calls the HTTP Post method, to send data to the Vault API server.
        /// This is the updated version.
        /// </summary>
        /// <param name="APIPath">The path to call on the Vault server.</param>
        /// <param name="callingRoutineName">String name of the routine that called this method.  Used for debugging and logging purposes only.</param>
        /// <param name="inputParamsJSON">JSON string of the parameters you want to put in the body of the HTTP call.  This is used to override the inputParams Dictionary.</param>
        /// <param name="expectReturnToHaveBody">Set to true to optimize the call by not retrieving the body from the response because it is not needed or expected to be empty.</param>
        /// <returns>VaultDataResponseObject with the results of the call.</returns>
        public async Task <VaultDataResponseObjectB> PostAsync_B(string APIPath,
                                                                 string callingRoutineName,
                                                                 string inputParamsJSON      = "",
                                                                 bool expectReturnToHaveBody = true)
        {
            HttpContent contentBody = new StringContent(inputParamsJSON);

            contentBody.Headers.ContentType = new MediaTypeHeaderValue("application/json");


            HttpResponseMessage response = await _httpClt.PostAsync(APIPath, contentBody);

            if (response.IsSuccessStatusCode)
            {
                VaultDataResponseObjectB vdr;
                if (!expectReturnToHaveBody)
                {
                    vdr = new VaultDataResponseObjectB(response.StatusCode);
                }
                else
                {
                    vdr = new VaultDataResponseObjectB(response);
                }
                return(vdr);
            }
            else
            {
                // Process errors.  This method will always throw an error.
                await HandleVaultErrors(response, APIPath, callingRoutineName);

                return(null);
            }
        }
Exemple #3
0
        /// <summary>
        /// Calls the HTTP PUT method, to send data to the Vault API server.
        /// </summary>
        /// <param name="APIPath">The path to call on the Vault server.</param>
        /// <param name="callingRoutineName">String name of the routine that called this method.  Used for debugging and logging purposes only.</param>
        /// <param name="inputParams">A Dictionary of key value pairs of parameters that should be sent in the body of the HTTP Call.  Should set to null if overriding
        /// with your own JSON string of parameters by setting the inputParamsJSON</param>
        /// <param name="inputParamsJSON">JSON string of the parameters you want to put in the body of the HTTP call.  This is used to override the inputParams Dictionary.</param>
        /// <returns>VaultDataResponseObject with the results of the call.</returns>
        public async Task <VaultDataResponseObjectB> PutAsync(string APIPath,
                                                              string callingRoutineName,
                                                              Dictionary <string, string> inputParams = null,
                                                              string inputParamsJSON = "")
        {
            if (inputParams != null)
            {
                inputParamsJSON = JsonConvert.SerializeObject(inputParams, Formatting.None);
            }


            HttpContent contentBody = new StringContent(inputParamsJSON);

            contentBody.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            string jsonResponse = "";

            HttpResponseMessage response = await _httpClt.PutAsync(APIPath, contentBody);

            if (response.IsSuccessStatusCode)
            {
                jsonResponse = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            }
            else
            {
                await HandleVaultErrors(response, APIPath, callingRoutineName);
            }


            VaultDataResponseObjectB vdr = new VaultDataResponseObjectB(response);

            return(vdr);
        }
        /// <summary>
        /// Attempts to read the sys mount config to determine if the path exists or not.  Returns true if the path exists, false otherwise
        /// </summary>
        /// <param name="mountPath">The name (path) of the backend to verify the existence of</param>
        /// <returns></returns>
        public async Task <bool> SysMountExists(string mountPath)
        {
            // Build Path
            string path = MountPointPath + pathMounts + mountPath + "/tune";

            try
            {
                VaultDataResponseObjectB vdro =
                    await ParentVault._httpConnector.GetAsync_B(path, "SysMountReadConfig", null);

                if (vdro.Success)
                {
                    return(true);
                }
            }
            catch (VaultInvalidDataException ve)
            {
                if (ve.Message.Contains("cannot fetch sysview for path"))
                {
                    return(false);
                }
                throw ve;
            }

            return(false);
        }
        /// <summary>
        /// Returns a Dictionary of objects and the permissions they contains, as well as an overall Capabilities object that summarizes the
        /// permissions that a Token has on the List of paths provided.
        /// <para>https://www.vaultproject.io/api/system/capabilities.html</para>
        /// </summary>
        /// <param name="tokenID">The Token to evaluate</param>
        /// <param name="paths">A list of paths to check the token against</param>
        /// <returns></returns>
        public async Task <Dictionary <string, List <string> > > GetTokenCapabilityOnPaths(string tokenID, List <string> paths)
        {
            string path = MountPointPath + "capabilities";

            // Add the token and paths parameters
            Dictionary <string, object> contentParams = new Dictionary <string, object>()
            {
                { "token", tokenID },
                { "paths", paths }
            };


            try {
                VaultDataResponseObjectB vdro = await ParentVault._httpConnector.PostAsync_B(path, "GetTokenCapabilityOnPaths", contentParams);

                if (vdro.Success)
                {
                    Dictionary <string, List <string> > capabilities = await vdro.GetDotNetObject <Dictionary <string, List <string> > >();

                    return(capabilities);
                }

                throw new ApplicationException("IdentitySecretEngine:ListEntitiesByName -> Arrived at unexpected code block.");
            }

            // 404 Errors mean there were no entities.  We just return an empty list.
            catch (VaultInvalidPathException) {
                return(null);
            }
        }
        /// <summary>
        /// Enables the provided Authentication backend.
        /// </summary>
        /// <param name="am">The AuthMethod object that represents the authentication engine to enable.</param>
        /// <returns>True if authentication engine was successfully enabled. False otherwise.
        /// Throws exception: VaultException with SpecificErrorCode set to BackendMountAlreadyExists if a mount already exists at that location.
        /// </returns>
        public async Task <bool> AuthEnable(AuthMethod am)
        {
            string path = MountPointPath + "auth/" + am.Name;

            Dictionary <string, string> contentParams = new Dictionary <string, string>();

            contentParams.Add("path", am.Path);
            contentParams.Add("description", am.Description);
            contentParams.Add("type", am.TypeAsString);

            string contentJSON = JsonConvert.SerializeObject(contentParams, Formatting.None);


            StringBuilder jsonConfig;
            string        json = "";

            if (am.Config != null)
            {
                jsonConfig = new StringBuilder(JsonConvert.SerializeObject(am.Config));
                jsonConfig.Insert(0, "\"config\":");

                // Combine the 2 JSON's, by stripping trailing closing brace from the content param JSON string.
                StringBuilder jsonParams = new StringBuilder(contentJSON, (contentJSON.Length + jsonConfig.Length + 20));
                jsonParams.Remove(jsonParams.Length - 1, 1);
                jsonParams.Append(",");

                // Remove the opening brace.
                jsonParams.Append(jsonConfig);
                jsonParams.Append("}");

                json = jsonParams.ToString();
            }
            else
            {
                json = contentJSON;
            }


            try {
                VaultDataResponseObjectB vdro = await ParentVault._httpConnector.PostAsync_B(path, "VaultSystemBackend:AuthEnable", json, false);

                return(vdro.Success);
            }
            catch (VaultInvalidDataException e) {
                if (e.Message.Contains("path is already in use"))
                {
                    VaultException ex =
                        new VaultException("The authentication backend mount point already exists.  Cannot enable another mount point at that location.");
                    ex.SpecificErrorCode = EnumVaultExceptionCodes.BackendMountAlreadyExists;
                    throw ex;
                }
                else
                {
                    throw e;
                }
            }
        }
        /// <summary>
        /// Deletes the backend Mount.
        /// </summary>
        /// <param name="name">Name of the mount to delete.</param>
        /// <returns>True if successful.  False otherwise.</returns>
        public async Task <bool> SysMountDelete(string name)
        {
            string path = MountPointPath + pathMounts + name;

            VaultDataResponseObjectB vdro = await ParentVault._httpConnector.DeleteAsync(path, "SysMountDelete");

            if (vdro.Success)
            {
                return(true);
            }

            return(false);
        }
        /// <summary>
        /// Creates or Updates a given policy object.
        /// </summary>
        /// <param name="policyContainerItem">The VaultPolicyContainer item that should be persisted into the Vault Instance Store.</param>
        /// <returns>True if successfully saved into Vault Instance.  False otherwise.</returns>
        public async Task <bool> SysPoliciesACLCreate(VaultPolicyContainer policyContainerItem)
        {
            // Build Path
            string path = MountPointPath + "policies/acl/" + policyContainerItem.Name;

            int count = policyContainerItem.PolicyPaths.Count;

            // If no policy paths defined, then return - nothing to do.
            if (count == 0)
            {
                return(false);
            }


            // Build the JSON - Lots of string escaping, etc.  fun!

            StringBuilder jsonBody = new StringBuilder();

            // Build the body of the JSON policy out.  We add the prefix part only if there is a body.
            foreach (VaultPolicyPathItem item in policyContainerItem.PolicyPaths.Values)
            {
                jsonBody.Append(item.ToVaultHCLPolicyFormat());
            }

            // If the VaultPolicyPathItem is still at new initialized state then throw error as there is no permission settings to send to Vault.
            if (jsonBody.Length == 0)
            {
                throw new ArgumentException(
                          "The PolicyContainer contained one or more VaultPolicyPathItem(s) at their initial state - undefined.  You must supply a VaultPolicyPathItem with at least one permission set.");
            }

            jsonBody.Insert(0, "{\"policy\": \"");

            // Issue the policy documents closing quote and then end the JSON.
            jsonBody.Append("\"}");

            //jsonBody.Append("}");

            string json = jsonBody.ToString();

            VaultDataResponseObjectB vdro = await ParentVault._httpConnector.PutAsync(path, "SysPoliciesACLCreate", null, json);

            if (vdro.Success)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
        /// <summary>
        /// Reads the configuration for the given backend mount point.
        /// </summary>
        /// <param name="mountPath">The Name(path) of the backend to read the configuration for.</param>
        /// <returns><see cref="VaultSysMountConfig"/>VaultSysMountConfig object containing the configuration settings.</returns>
        public async Task <VaultSysMountConfig> SysMountReadConfig(string mountPath)
        {
            // Build Path
            string path = MountPointPath + pathMounts + mountPath + "/tune";

            VaultDataResponseObjectB vdro = await ParentVault._httpConnector.GetAsync_B(path, "SysMountReadConfig", null);

            if (vdro.Success)
            {
                return(await vdro.GetDotNetObject <VaultSysMountConfig>());
            }

            return(null);
        }
        /// <summary>
        /// Disables (deletes? Not Sure) the specified audit device
        /// </summary>
        /// <param name="auditDeviceName">Name of the Audit device to delete.</param>
        /// <returns>True if audit device successfully deleted.  False otherwise.</returns>
        public async Task <bool> AuditDisable(string auditDeviceName)
        {
            string path = MountPointPath + "audit/" + auditDeviceName;

            VaultDataResponseObjectB vdro = await ParentVault._httpConnector.DeleteAsync(path, "SysAuditDisable");

            if (vdro.Success)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemple #11
0
        /// <summary>
        /// Performs an HTTP Delete operation.
        /// </summary>
        /// <param name="APIPath">The Vault path to call to perform a deletion on.</param>
        /// <param name="callingRoutineName">Routine that called this function</param>
        /// <returns>VaultDateResponseObject of the results of the operation.</returns>
        public async Task <VaultDataResponseObjectB> DeleteAsync(string APIPath, string callingRoutineName)
        {
            string fullURI = APIPath;
            HttpResponseMessage response = await _httpClt.DeleteAsync(fullURI);


            if (response.IsSuccessStatusCode)
            {
                VaultDataResponseObjectB vdr = new VaultDataResponseObjectB(response);
                return(vdr);
            }


            await HandleVaultErrors(response, fullURI, callingRoutineName);

            return(null);
        }
        /// <summary>
        /// Returns true if the authentication provider with the given name exists.  False otherwise.
        /// </summary>
        /// <param name="authName"></param>
        /// <returns></returns>
        public async Task <bool> AuthExists(string authName)
        {
            string path = MountPointPath + "auth";

            VaultDataResponseObjectB vdro = await ParentVault._httpConnector.GetAsync_B(path, "AuthExists");

            if (vdro.Success)
            {
                Dictionary <string, AuthMethod> methods = await vdro.GetDotNetObject <Dictionary <string, AuthMethod> >();

                // Now see if path exists - Auth names from vault have a trailing slash.
                if (methods.ContainsKey(authName + "/"))
                {
                    return(true);
                }
            }
            return(false);
        }
        /// <summary>
        /// Deletes a given policy.
        /// </summary>
        /// <param name="policyName">The name of the policy to delete.</param>
        /// <returns>True if successful in deleting.</returns>
        public async Task <bool> SysPoliciesACLDelete(string policyName)
        {
            // Build Path
            string path = MountPointPath + "policies/acl/" + policyName;


            try {
                VaultDataResponseObjectB vdro = await ParentVault._httpConnector.DeleteAsync(path, "SysPoliciesACLDelete");

                if (vdro.Success)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            catch (VaultInvalidPathException) { return(false); }
        }
Exemple #14
0
        /// <summary>
        /// Retrieves data from the Vault.
        /// </summary>
        /// <param name="APIPath">Path to the vault method you wish to execute.</param>
        /// <param name="callingRoutineName">Name of routine that is calling us - used during error reporting.</param>
        /// <param name="sendParameters">The parameters to send to the API method.</param>
        /// <returns>A VaultDataResponseObject containing the return data or error codes.</returns>
        public async Task <VaultDataResponseObjectB> GetAsync_B(string APIPath, string callingRoutineName, Dictionary <string, string> sendParameters = null)
        {
            string fullURI;


            // Build the fullURI string.  If it has parameters those are a part of it, otherwise it's just the APIPath
            if (sendParameters != null)
            {
                // Assume 30 characters per parameter item.
                StringBuilder sendParams = new StringBuilder("?", sendParameters.Count * 30);
                foreach (KeyValuePair <string, string> item in sendParameters)
                {
                    sendParams.Append(item.Key + "=" + item.Value + "&");
                }

                // Remove trailing &
                sendParams.Length--;

                fullURI = APIPath + sendParams.ToString();
            }
            else
            {
                fullURI = APIPath;
            }


            HttpResponseMessage response = await _httpClt.GetAsync(fullURI);

            if (response.IsSuccessStatusCode)
            {
                VaultDataResponseObjectB vdr = new VaultDataResponseObjectB(response);
                return(vdr);
            }
            else
            {
                // Process errors.  This method will always throw an error.
                await HandleVaultErrors(response, fullURI, callingRoutineName);

                return(null);
            }
        }
        /// <summary>
        /// Lists all authentication methods in the current Vault System.
        /// <returns>Dictionary\string,AuthMethod> containing all Authentication Methods</returns>
        /// </summary>
        public async Task <Dictionary <string, AuthMethod> > AuthListAll()
        {
            string path = MountPointPath + "auth";

            VaultDataResponseObjectB vdro = await ParentVault._httpConnector.GetAsync_B(path, "AuthListAll");

            if (vdro.Success)
            {
                Dictionary <string, AuthMethod> methods = await vdro.GetDotNetObject <Dictionary <string, AuthMethod> >();

                // We need to place the dictionary key into each objects path value.
                foreach (KeyValuePair <string, AuthMethod> kv in methods)
                {
                    kv.Value.Path = kv.Key;
                }

                return(methods);
            }

            throw new ApplicationException("KeyValueSecretEngine:ListSecrets  Arrived at unexpected code block.");
        }
        /// <summary>
        /// Creates a new audit device with the specified name.
        /// </summary>
        /// <param name="auditorName">A name to be given to the audit device</param>
        /// <param name="filePath">A full path and filename specification of where the audit entries should be written.</param>
        /// <param name="description">A description of the audit device.</param>
        /// <returns>True if successfully created.</returns>
        public async Task <bool> AuditEnableFileDevice(string auditorName, string filePath, string description = "Audit to file")
        {
            string path = MountPointPath + "audit/" + auditorName;

            Dictionary <string, string> contentParams = new Dictionary <string, string>()
            {
                { "description", description },
                { "type", "file" }
            };


            string inputVarsJSON = VaultSerializationHelper.ToJson(contentParams);     //JsonConvert.SerializeObject (contentParams, Formatting.None);
            Dictionary <string, string> optionsList = new Dictionary <string, string>()
            {
                //{ "path",@"c:\temp\avault.log" }
                { "path", filePath }
            };

            // Build entire JSON Body:  Input Params + Bulk Items List.
            string bulkJSON = JsonConvert.SerializeObject(new { options = optionsList }, Formatting.None);


            // Combine the 2 JSON's
            if (contentParams.Count > 0)
            {
                string newVarsJSON = inputVarsJSON.Substring(1, inputVarsJSON.Length - 2) + ",";
                bulkJSON = bulkJSON.Insert(1, newVarsJSON);
            }


            VaultDataResponseObjectB vdro = await ParentVault._httpConnector.PutAsync(path, "SysAuditEnableFileDevice", null, bulkJSON);

            return(vdro.Success);

            //TODO Cleanup
            //if ( vdro.HttpStatusCode == 204 ) { return true; }
            //else { return false; }
        }
        /// <summary>
        /// Returns a list of all ACL Policies in the Vault Instance
        /// </summary>
        /// <returns>List[string] of all ACL policies by name.</returns>
        public async Task <List <string> > SysPoliciesACLList()
        {
            // Build Path
            string path = MountPointPath + "policies/acl";

            // Setup List Parameters
            Dictionary <string, string> sendParams = new Dictionary <string, string>();

            sendParams.Add("list", "true");

            VaultDataResponseObjectB vdro = await ParentVault._httpConnector.GetAsync_B(path, "SysPoliciesACLList", sendParams);

            return(await vdro.GetDotNetObject <List <string> >("data.keys"));

            //TODO Cleanup

            /*
             *
             * string js = vdro.GetJSONPropertyValue (vdro.GetDataPackageAsJSON(), "keys");
             *
             * List<string> keys = VaultUtilityFX.ConvertJSON<List<string>> (js);
             * return keys;
             */
        }
        /// <summary>
        /// Updates the configuration of a given system mount point.  If description is null then it will not be updated.
        /// </summary>
        /// <param name="Name">The name of the mount to update</param>
        /// <param name="config"><see cref="VaultSysMountConfig"/>The backend's configuration changes</param>
        /// <param name="description">If set, the description will be updated.  </param>
        /// <returns>True if successfull.  False otherwise.</returns>
        public async Task <bool> SysMountUpdateConfig(string Name, VaultSysMountConfig config, string description = null)
        {
            string path = MountPointPath + pathMounts + Name + "/tune";

            Dictionary <string, string> content = new Dictionary <string, string>
            {
                { "default_lease_ttl", config.DefaultLeaseTTL },
                { "max_lease_ttl", config.MaxLeaseTTL },
                { "audit_non_hmac_request_keys", config.RequestKeysToNotAuditViaHMAC },
                { "audit_non_hmac_response_keys", config.ResponseKeysToNotAuditViaHMAC },
                { "listing_visibility", config.VisibilitySetting },
                { "passthrough_request_headers", config.PassThruRequestHeaders }
            };


            if (description != null)
            {
                content.Add("description", description);
            }

            VaultDataResponseObjectB vdro = await ParentVault._httpConnector.PostAsync_B(path, "SysMountUpdateConfig", content, false);

            return(vdro.Success);
        }
        /// <summary>
        /// Creates (Enables in Vault terminology) a new backend secrets engine with the given name, type and configuration settings.
        /// Throws:  [VaultInvalidDataException] when the mount point already exists.  SpecificErrorCode will be set to: [BackendMountAlreadyExists]
        /// <param name="mountPath">The root path to this secrets engine that it will be mounted at.  Is a part of every URL to this backend.</param>
        /// <param name="description">Brief human friendly name for the mount.</param>
        /// <param name="backendType">The type of secrets backend this mount is.  </param>
        /// <param name="config">The configuration to be applied to this mount.</param>
        /// <returns>Bool:  True if successful in creating the backend mount point.  False otherwise.</returns>
        /// </summary>
        public async Task <bool> SysMountCreate(string mountPath, string description, EnumSecretBackendTypes backendType, VaultSysMountConfig config = null)
        {
            // The keyname forms the last part of the path
            string path = MountPointPath + pathMounts + mountPath;


            // Build out the parameters dictionary.
            Dictionary <string, object> createParams = new Dictionary <string, object>();

            // Build Options Dictionary
            Dictionary <string, string> options = new Dictionary <string, string>();

            string typeName = "";

            switch (backendType)
            {
            case EnumSecretBackendTypes.Transit:
                typeName = "transit";
                break;

            case EnumSecretBackendTypes.Secret:
                typeName = "kv";
                break;

            case EnumSecretBackendTypes.AWS:
                typeName = "aws";
                throw new NotImplementedException();

            case EnumSecretBackendTypes.CubbyHole:
                typeName = "cubbyhole";
                throw new NotImplementedException();

            case EnumSecretBackendTypes.Generic:
                typeName = "generic";
                throw new NotImplementedException();

            case EnumSecretBackendTypes.PKI:
                typeName = "pki";
                throw new NotImplementedException();

            case EnumSecretBackendTypes.SSH:
                typeName = "ssh";
                throw new NotImplementedException();

            case EnumSecretBackendTypes.KeyValueV2:

                // It is the same type as a version 1, but it has an additional config value.
                typeName = "kv";
                options.Add("version", "2");
                break;
            }

            createParams.Add("type", typeName);
            createParams.Add("description", description);
            createParams.Add("options", options);

            if (config != null)
            {
                createParams.Add("config", config);
            }

            try {
                VaultDataResponseObjectB vdro = await ParentVault._httpConnector.PostAsync_B(path, "SysMountEnable", createParams, false);

                if (vdro.HttpStatusCode == 204)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            catch (VaultInvalidDataException e) {
                if (e.Message.Contains("path is already in use"))
                {
                    e.SpecificErrorCode = EnumVaultExceptionCodes.BackendMountAlreadyExists;
                }

                throw e;
            }
        }