Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for insecure connection and manual TLS certificate validation #42

Merged
merged 6 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,9 @@ Alternatively, you can configure Vault connection using next environment variabl
- `VAULT_TOKEN` : Vault token. Used for token-based authentication. Default value is `root`.
- `VAULT_ROLEID` : Vault AppRole ID. Used for AppRole-based authentication.
- `VAULT_SECRET` : Vault AppRole secret. Used for AppRole-based authentication.
- `VAULT_INSECURE` : Allow insecure SSL connections to Vault. Default value is `false`.

## Configuration using IAuthMethodInfo
## Configuration using code

You can configure Vault connection using any supported auth method (look at https://github.com/rajanadar/VaultSharp#auth-methods):

Expand All @@ -128,6 +129,29 @@ config.AddVaultConfiguration(
"secret");
```

You can enable insecure TLS connections to Vault:

```csharp
builder.AddVaultConfiguration(
() => new VaultOptions("https://localhost:8200", "root", insecureConnection: true),
"test",
"secret",
this._logger);
```

Or manually validate TLS certificate:

```csharp
builder.AddVaultConfiguration(
() => new VaultOptions("https://localhost:8200", "root", additionalCharactersForConfigurationPath: new[] { '.' }, insecureConnection: false, serverCertificateCustomValidationCallback: (message, cert, chain, errors) =>
{
return true; //add your validation logic here
}),
"test",
"secret",
this._logger);
```

## Preparing secrets in Vault

You need to store your secrets with special naming rules.
Expand Down Expand Up @@ -169,7 +193,7 @@ There are two ways to create nested parameters.

## Limitations

- Currently, only token and AppRole based authentication is supported.
- Currently, only token and AppRole based authentication is supported from configuration. Other types of authentication can be used by code.
- TTL of the secrets is not controlled.

## Contributing
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace VaultSharp.Extensions.Configuration
namespace VaultSharp.Extensions.Configuration
{
#pragma warning disable CA2000

Expand Down Expand Up @@ -63,12 +63,15 @@ public static IConfigurationBuilder AddVaultConfiguration(
throw new ArgumentNullException(nameof(basePath));
}

var insecureOk = bool.TryParse(Environment.GetEnvironmentVariable(VaultEnvironmentVariableNames.InsecureConnection), out var insecure);

var vaultOptions = new VaultOptions(
Environment.GetEnvironmentVariable(VaultEnvironmentVariableNames.Address) ??
VaultConfigurationSource.DefaultVaultUrl,
Environment.GetEnvironmentVariable(VaultEnvironmentVariableNames.Token) ?? VaultConfigurationSource.DefaultVaultToken,
Environment.GetEnvironmentVariable(VaultEnvironmentVariableNames.Secret),
Environment.GetEnvironmentVariable(VaultEnvironmentVariableNames.RoleId));
Environment.GetEnvironmentVariable(VaultEnvironmentVariableNames.RoleId),
insecureOk && insecure);
configuration.Add(new VaultConfigurationSource(vaultOptions, basePath, mountPoint, logger));
return configuration;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace VaultSharp.Extensions.Configuration
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
Expand Down Expand Up @@ -74,6 +75,25 @@ public override void Load()
{
UseVaultTokenHeaderInsteadOfAuthorizationHeader = true,
Namespace = this.ConfigurationSource.Options.Namespace,

PostProcessHttpClientHandlerAction = handler =>
{
if (handler is HttpClientHandler clientHandler)
{
if (this.ConfigurationSource.Options.AcceptInsecureConnection)
{
#if NETSTANDARD2_0
clientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) => true;
#else
clientHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
#endif
}
else if (this.ConfigurationSource.Options.ServerCertificateCustomValidationCallback != null)
{
clientHandler.ServerCertificateCustomValidationCallback = this.ConfigurationSource.Options.ServerCertificateCustomValidationCallback;
}
}
}
};
this.vaultClient = new VaultClient(vaultClientSettings);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,10 @@ public static class VaultEnvironmentVariableNames
/// Environment variable name for Vault secret.
/// </summary>
public const string Secret = "VAULT_SECRET";

/// <summary>
/// Environment variable name for disabling server certificate validation for Vault client.
/// </summary>
public const string InsecureConnection = "VAULT_INSECURE";
}
}
35 changes: 32 additions & 3 deletions Source/VaultSharp.Extensions.Configuration/VaultOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ namespace VaultSharp.Extensions.Configuration
{
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using VaultSharp.V1.AuthMethods;

/// <summary>
Expand All @@ -22,6 +25,8 @@ public class VaultOptions
/// <param name="additionalCharactersForConfigurationPath">Additional characters for the Configuration path.</param>
/// <param name="namespace">Vault namespace.</param>
/// <param name="alwaysAddTrailingSlashToBasePath">Should a trailing slash be added to the base path. See AlwaysAddTrailingSlashToBasePath property for details </param>
/// <param name="insecureConnection">(Dangerous!) Ignore certificate validation. This implies self-signed certificates are accepted.</param>
/// <param name="serverCertificateCustomValidationCallback">An optional action to post-process the HttpClientHandler. Used to manually validate the server certificate. Ignored if AcceptInsecureConnection is true.</param>
public VaultOptions(
string vaultAddress,
string? vaultToken,
Expand All @@ -32,7 +37,9 @@ public VaultOptions(
bool omitVaultKeyName = false,
IEnumerable<char>? additionalCharactersForConfigurationPath = null,
string? @namespace = null,
bool alwaysAddTrailingSlashToBasePath = true)
bool alwaysAddTrailingSlashToBasePath = true,
bool insecureConnection = false,
Func<HttpRequestMessage, X509Certificate2?, X509Chain?, SslPolicyErrors, bool>? serverCertificateCustomValidationCallback = null)
{
this.VaultAddress = vaultAddress;
this.VaultToken = vaultToken;
Expand All @@ -44,6 +51,8 @@ public VaultOptions(
this.AdditionalCharactersForConfigurationPath = additionalCharactersForConfigurationPath ?? Array.Empty<char>();
this.Namespace = @namespace;
this.AlwaysAddTrailingSlashToBasePath = alwaysAddTrailingSlashToBasePath;
this.AcceptInsecureConnection = insecureConnection;
this.ServerCertificateCustomValidationCallback = serverCertificateCustomValidationCallback;
}

/// <summary>
Expand All @@ -57,6 +66,8 @@ public VaultOptions(
/// <param name="additionalCharactersForConfigurationPath">Additional characters for the Configuration path.</param>
/// <param name="namespace">Vault namespace.</param>
/// <param name="alwaysAddTrailingSlashToBasePath">Should a trailing slash be added to the base path. See AlwaysAddTrailingSlashToBasePath property for details </param>
/// <param name="insecureConnection">(Dangerous!) Ignore certificate validation. This implies self-signed certificates are accepted.</param>
/// <param name="serverCertificateCustomValidationCallback">An optional action to post-process the HttpClientHandler. Used to manually validate the server certificate. Ignored if AcceptInsecureConnection is true.</param>
public VaultOptions(
string vaultAddress,
IAuthMethodInfo authMethod,
Expand All @@ -65,7 +76,9 @@ public VaultOptions(
bool omitVaultKeyName = false,
IEnumerable<char>? additionalCharactersForConfigurationPath = null,
string? @namespace = null,
bool alwaysAddTrailingSlashToBasePath = true)
bool alwaysAddTrailingSlashToBasePath = true,
bool insecureConnection = false,
Func<HttpRequestMessage, X509Certificate2?, X509Chain?, SslPolicyErrors, bool>? serverCertificateCustomValidationCallback = null)
{
this.VaultAddress = vaultAddress;
this.AuthMethod = authMethod;
Expand All @@ -75,6 +88,8 @@ public VaultOptions(
this.AdditionalCharactersForConfigurationPath = additionalCharactersForConfigurationPath ?? Array.Empty<char>();
this.Namespace = @namespace;
this.AlwaysAddTrailingSlashToBasePath = alwaysAddTrailingSlashToBasePath;
this.AcceptInsecureConnection = insecureConnection;
this.ServerCertificateCustomValidationCallback = serverCertificateCustomValidationCallback;
}

/// <summary>
Expand Down Expand Up @@ -116,7 +131,7 @@ public VaultOptions(
/// <summary>
/// Gets a value indicating whether the Vault key should be ommited when generation Configuration key names.
/// </summary>
public bool OmitVaultKeyName { get; }
public bool OmitVaultKeyName { get; }

/// <summary>
/// Gets an array of characters that will be used as a path to form the Configuration.
Expand All @@ -134,5 +149,19 @@ public VaultOptions(
/// It is true by default. Set to false if you don't have permissions to list keys in the base path.
/// </summary>
public bool AlwaysAddTrailingSlashToBasePath { get; }

/// <summary>
/// Indicates whether we should disregard the certificate validation (for examples, servers behind Internet aren't likely to have a strong certs but we can't afford to use HTTP either)
/// Previously, the certificate behavior can be set globally, but subsequently removed in .NET Core and onwards due to security reasons.
/// We need to set the behavior to each HttpClient on a case-by-case basis. As such, this option is provided as a resolution.
/// If it is true, a custom PostProcessHttpClientHandlerAction will be injected to the VaultClientSettings to accept any server certificate.
/// Default value: false. Hashicorp also recommend using a proper CA to setup Vault access due to security concerns.
/// </summary>
public bool AcceptInsecureConnection { get; }

/// <summary>
/// An optional action to post-process the HttpClientHandler. Used to manually validate the server certificate. Ignored if AcceptInsecureConnection is true.
/// </summary>
public Func<HttpRequestMessage, X509Certificate2?, X509Chain?, SslPolicyErrors, bool>? ServerCertificateCustomValidationCallback { get; set;}
}
}
Loading