From ea418643e59181bda33e92706ff0923d0f679587 Mon Sep 17 00:00:00 2001 From: Ryan Gribble Date: Tue, 24 Aug 2021 09:18:52 +1000 Subject: [PATCH] Add support for anonymous binding (#45) * allow ldap password to be null to support anonymous bind scenarios update description on config parameter to note that leaving blank will use anonymous bind update test helper to allow null passwords * Don't add sensitive values in constructor If the LDAP configuration hasn't yet been initialise this will throw an exception. * update configuration resource description to mention anonymous bind Co-authored-by: Shane --- .../Configuration/LdapConfigurationResource.cs | 2 +- .../TestHelpers/LdapConfigurationExtensions.cs | 2 +- .../Configuration/LdapConfigurationResource.cs | 2 +- .../Configuration/LdapConfigureCommands.cs | 16 +++++++++++++++- source/Server/Ldap/LdapContextProvider.cs | 2 +- source/Server/LdapAuthenticationProvider.cs | 8 ++------ 6 files changed, 21 insertions(+), 11 deletions(-) diff --git a/source/Client/Configuration/LdapConfigurationResource.cs b/source/Client/Configuration/LdapConfigurationResource.cs index 39d1c87..aeb411f 100644 --- a/source/Client/Configuration/LdapConfigurationResource.cs +++ b/source/Client/Configuration/LdapConfigurationResource.cs @@ -17,7 +17,7 @@ public LdapConfigurationResource() public const string UseSslDescription = "Sets whether to use Secure Socket Layer to connect to LDAP."; public const string IgnoreSslErrorsDescription = "Sets whether to ignore certificate validation errors."; public const string UsernameDescription = "Set the user DN to query LDAP."; - public const string PasswordDescription = "Set the password to query LDAP."; + public const string PasswordDescription = "Set the password to query LDAP (leave empty for anonymous bind)."; public const string UserBaseDnDescription = "Set the root distinguished name (DN) to query LDAP for Users."; public const string DefaultDomainDescription = "Set the default domain when none is given in the logon form. Optional."; public const string UserFilterDescription = "The filter to use when searching valid users."; diff --git a/source/Ldap.Integration.Tests/TestHelpers/LdapConfigurationExtensions.cs b/source/Ldap.Integration.Tests/TestHelpers/LdapConfigurationExtensions.cs index 73d8f93..909f6f0 100644 --- a/source/Ldap.Integration.Tests/TestHelpers/LdapConfigurationExtensions.cs +++ b/source/Ldap.Integration.Tests/TestHelpers/LdapConfigurationExtensions.cs @@ -18,7 +18,7 @@ internal static LdapConfiguration WithConnection(this LdapConfiguration configur configuration.Server = server ?? throw new ArgumentNullException(nameof(server)); configuration.Port = port; configuration.ConnectUsername = user ?? throw new ArgumentNullException(nameof(user)); - configuration.ConnectPassword = password.ToSensitiveString() ?? throw new ArgumentNullException(nameof(password)); + configuration.ConnectPassword = password?.ToSensitiveString(); return configuration; } diff --git a/source/Server/Configuration/LdapConfigurationResource.cs b/source/Server/Configuration/LdapConfigurationResource.cs index 9347759..796c9c6 100644 --- a/source/Server/Configuration/LdapConfigurationResource.cs +++ b/source/Server/Configuration/LdapConfigurationResource.cs @@ -12,7 +12,7 @@ public class LdapConfigurationResource : ExtensionConfigurationResource public const string SecurityProtocolDescription = "Sets the security protocol to use in securing the connection (None, StartTLS, or SSL)."; public const string IgnoreSslErrorsDescription = "Sets whether to ignore certificate validation errors."; public const string UsernameDescription = "Set the user DN to query LDAP."; - public const string PasswordDescription = "Set the password to query LDAP."; + public const string PasswordDescription = "Set the password to query LDAP (leave empty for anonymous bind)."; public const string UserBaseDnDescription = "Set the root distinguished name (DN) to query LDAP for Users."; public const string DefaultDomainDescription = "Set the default domain when none is given in the logon form. Optional."; public const string UserFilterDescription = "The filter to use when searching valid users. '*' is replaced with a normalized version of the username."; diff --git a/source/Server/Configuration/LdapConfigureCommands.cs b/source/Server/Configuration/LdapConfigureCommands.cs index 6e7bfc2..c40ae61 100644 --- a/source/Server/Configuration/LdapConfigureCommands.cs +++ b/source/Server/Configuration/LdapConfigureCommands.cs @@ -1,4 +1,5 @@ -using Octopus.Diagnostics; +using Octopus.Data.Model; +using Octopus.Diagnostics; using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; using System; using System.Collections.Generic; @@ -60,6 +61,19 @@ public IEnumerable GetOptions() ldapConfiguration.Value.SetConnectUsername(v); log.Info("LDAP Username set to: " + v); }); + yield return new ConfigureCommandOption("ldapPassword=", LdapConfigurationResource.PasswordDescription, v => + { + if (!string.IsNullOrEmpty(v)) + { + ldapConfiguration.Value.SetConnectPassword(v.ToSensitiveString()); + log.Info("LDAP Password set to provided value"); + } + else + { + ldapConfiguration.Value.SetConnectPassword(null); + log.Info("LDAP Password set to null (anonymous bind)"); + } + }); yield return new ConfigureCommandOption("ldapUserBaseDn=", LdapConfigurationResource.UserBaseDnDescription, v => { ldapConfiguration.Value.SetUserBaseDn(v); diff --git a/source/Server/Ldap/LdapContextProvider.cs b/source/Server/Ldap/LdapContextProvider.cs index 8e68ea1..afd6b2d 100644 --- a/source/Server/Ldap/LdapContextProvider.cs +++ b/source/Server/Ldap/LdapContextProvider.cs @@ -42,7 +42,7 @@ public LdapContext GetContext() if (ldapConfiguration.Value.GetSecurityProtocol() == SecurityProtocol.StartTLS) con.StartTls(); - con.Bind(ldapConfiguration.Value.GetConnectUsername(), ldapConfiguration.Value.GetConnectPassword().Value); + con.Bind(ldapConfiguration.Value.GetConnectUsername(), ldapConfiguration.Value.GetConnectPassword()?.Value); con.Constraints = new LdapConstraints( ldapConfiguration.Value.GetConstraintTimeLimit() * 1000, diff --git a/source/Server/LdapAuthenticationProvider.cs b/source/Server/LdapAuthenticationProvider.cs index e5208e0..0a4c6e1 100644 --- a/source/Server/LdapAuthenticationProvider.cs +++ b/source/Server/LdapAuthenticationProvider.cs @@ -1,4 +1,4 @@ -using Octopus.Data.Model; +using Octopus.Data.Model; using Octopus.Diagnostics; using Octopus.Server.Extensibility.Authentication.Extensions; using Octopus.Server.Extensibility.Authentication.Extensions.Identities; @@ -14,13 +14,9 @@ public class LdapAuthenticationProvider : IAuthenticationProviderWithGroupSuppor { private readonly ILdapConfigurationStore configurationStore; - public LdapAuthenticationProvider(ILdapConfigurationStore configurationStore, ILogWithContext log) + public LdapAuthenticationProvider(ILdapConfigurationStore configurationStore) { this.configurationStore = configurationStore; - var password = configurationStore.GetConnectPassword(); - - if (!string.IsNullOrEmpty(password?.Value)) - log.CurrentContext.WithSensitiveValue(password.Value); } public string IdentityProviderName => LdapAuthentication.ProviderName;