/// <summary>
        /// <para>
        ///     Adds the secrets of a HashiCorp Vault KeyValue engine to the secret store.
        /// </para>
        /// <para>
        ///     See more information on HashiCorp: <a href="https://www.vaultproject.io/docs" />.
        /// </para>
        /// </summary>
        /// <param name="builder">The builder to add the HashiCorp secrets from the KeyValue Vault to.</param>
        /// <param name="settings"></param>
        /// <param name="secretPath">The secret path where the secret provider should look for secrets.</param>
        /// <param name="configureOptions">The function to set the additional options to configure the HashiCorp Vault KeyValue.</param>
        /// <param name="name">The unique name to register this HashiCorp provider in the secret store.</param>
        /// <param name="mutateSecretName">The optional function to mutate the secret name before looking it up.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown when the <paramref name="builder"/>, <paramref name="settings"/> or <paramref name="secretPath"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///     Thrown when the <paramref name="settings"/> doesn't have a valid Vault server URI or a missing authentication method,
        ///     or the <paramref name="secretPath"/> is blank.
        /// </exception>
        public static SecretStoreBuilder AddHashiCorpVault(
            this SecretStoreBuilder builder,
            VaultClientSettings settings,
            string secretPath,
            Action <HashiCorpVaultOptions> configureOptions,
            string name,
            Func <string, string> mutateSecretName)
        {
            Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the HashiCorp Vault secret provider");
            Guard.NotNull(settings, nameof(settings), "Requires HashiCorp Vault settings to correctly connect to the running HashiCorp Vault");
            Guard.NotNullOrWhitespace(settings.VaultServerUriWithPort, nameof(settings.VaultServerUriWithPort), "Requires a non-blank HashiCorp Vault settings to have a valid URI with HTTP port");
            Guard.NotNull(settings.AuthMethodInfo, nameof(settings.AuthMethodInfo), "Requires the HashiCorp Vault settings to have an authentication method configured");
            Guard.NotNullOrWhitespace(secretPath, nameof(secretPath), "Requires a secret path to look for secret values");
            Guard.For <ArgumentException>(() => !Uri.IsWellFormedUriString(settings.VaultServerUriWithPort, UriKind.RelativeOrAbsolute), "Requires a HashiCorp Vault server URI with HTTP port");

            var options = new HashiCorpVaultOptions();

            configureOptions?.Invoke(options);

            return(AddHashiCorpVault(builder, settings, secretPath, options, configureSecretProviderOptions: secretProviderOptions =>
            {
                secretProviderOptions.Name = name;
                secretProviderOptions.MutateSecretName = mutateSecretName;
            }));
        }
        public void SetMountPoint_WithBlankValue_Throws(string mountPoint)
        {
            // Arrange
            var options = new HashiCorpVaultOptions();

            // Act / Assert
            Assert.ThrowsAny <ArgumentException>(() => options.KeyValueMountPoint = mountPoint);
        }
        public void SetSecretEngineVersion_WithOutOfBoundsVersion_Throws()
        {
            // Arrange
            var options = new HashiCorpVaultOptions();

            // Act / Assert
            Assert.ThrowsAny <ArgumentException>(
                () => options.KeyValueVersion = VaultKeyValueSecretEngineVersion.V1 | VaultKeyValueSecretEngineVersion.V2);
        }
Пример #4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="HashiCorpSecretProvider"/> class.
        /// </summary>
        /// <param name="settings">The configuration and authentication settings to successfully connect to the HashiCorp Vault instance.</param>
        /// <param name="secretPath">The HashiCorp secret path available in the KeyValue engine where this secret provider should look for secrets.</param>
        /// <param name="options">The additional options to configure the HashiCorp Vault KeyValue.</param>
        /// <param name="logger">The logger instance to write diagnostic messages and track HashiCorp Vault dependencies.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown when the <paramref name="settings"/>,
        ///     or <paramref name="secretPath"/> is blank,
        ///     or <paramref name="options"/> is <c>null</c>
        ///     or the <paramref name="settings"/> doesn't contain a authentication method.</exception>
        /// <exception cref="ArgumentException">Thrown the <paramref name="settings"/> doesn't contain a valid Vault URI.</exception>
        public HashiCorpSecretProvider(
            VaultClientSettings settings,
            string secretPath,
            HashiCorpVaultOptions options,
            ILogger <HashiCorpSecretProvider> logger)
        {
            Guard.NotNull(settings, nameof(settings), "Requires HashiCorp settings to successfully connect to the Vault");
            Guard.NotNull(settings.AuthMethodInfo, nameof(settings.AuthMethodInfo), "Requires a authentication method to connect to the HashiCorp Vault");
            Guard.NotNullOrWhitespace(secretPath, nameof(secretPath), "Requires a path where the HashiCorp Vault KeyValue secret engine should look for secrets");
            Guard.For <ArgumentException>(() => !Uri.IsWellFormedUriString(settings.VaultServerUriWithPort, UriKind.RelativeOrAbsolute), "Requires a HashiCorp Vault server URI with HTTP port");

            Options     = options;
            SecretPath  = secretPath;
            VaultClient = new VaultClient(settings);
            Logger      = logger ?? NullLogger <HashiCorpSecretProvider> .Instance;
        }
        private static SecretStoreBuilder AddHashiCorpVault(
            SecretStoreBuilder builder,
            VaultClientSettings settings,
            string secretPath,
            HashiCorpVaultOptions options,
            Action <SecretProviderOptions> configureSecretProviderOptions)
        {
            AddHashiCorpCriticalExceptions(builder);

            return(builder.AddProvider(serviceProvider =>
            {
                var logger = serviceProvider.GetService <ILogger <HashiCorpSecretProvider> >();
                var provider = new HashiCorpSecretProvider(settings, secretPath, options, logger);

                return provider;
            }, configureSecretProviderOptions));
        }
        private static SecretStoreBuilder AddHashiCorpVault(
            SecretStoreBuilder builder,
            VaultClientSettings settings,
            string secretPath,
            HashiCorpVaultOptions options,
            Func <string, string> mutateSecretName)
        {
            // Thrown when the HashiCorp Vault's authentication and/or authorization fails.
            builder.AddCriticalException <VaultApiException>(exception =>
            {
                return(exception.HttpStatusCode == HttpStatusCode.BadRequest ||
                       exception.HttpStatusCode == HttpStatusCode.Forbidden);
            });

            return(builder.AddProvider(serviceProvider =>
            {
                var logger = serviceProvider.GetService <ILogger <HashiCorpSecretProvider> >();
                var provider = new HashiCorpSecretProvider(settings, secretPath, options, logger);

                return provider;
            }, mutateSecretName));
        }