-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
VAULT 18227/introduce cap ldap library #22185
Conversation
CI Results: |
@@ -14,7 +14,7 @@ import ( | |||
// but through an interface. | |||
type Connection interface { | |||
Bind(username, password string) error | |||
Close() | |||
Close() error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed as a result of updating the go-ldap/ldap
library to v3.4.5
when cap/ldap
was installed.
@@ -53,9 +53,6 @@ to search and change entry passwords in LDAP. | |||
string for authentication. The constructed UPN will appear as `[binddn]@[upndomain]`. For | |||
example, if `upndomain=example.com` and `binddn=admin`, the UPN string `[email protected]` | |||
will be used to log in to Active Directory. | |||
- `connection_timeout` `(integer: 30 or string: "30s")` - Timeout, in seconds, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to Deprecated Parameters
and added a note.
"github.com/hashicorp/vault/sdk/helper/docker" | ||
"github.com/hashicorp/vault/sdk/helper/ldaputil" | ||
) | ||
|
||
func PrepareTestContainer(t *testing.T, version string) (cleanup func(), cfg *ldaputil.ConfigEntry) { | ||
// Skipping on ARM, as this image can't run on ARM architecture | ||
if strings.Contains(runtime.GOARCH, "arm") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was able to run these tests locally on my Mac M1, but if this causes test failures I'll revert these changes.
entityAliasAttribute, err := ldapClient.GetUserAliasAttributeValue(cfg.ConfigEntry, c, username) | ||
if err != nil { | ||
return "", nil, logical.ErrorResponse(err.Error()), nil, nil | ||
} | ||
if entityAliasAttribute == "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation of this can be found here.
I believe it boils down to finding the 'CN' (common name) attribute.
|
||
// Clean connection | ||
defer c.Close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of the code deleted below is implemented via the Authenticate
method found in cap/ldap.
We do need to specify options to also get groups
and attributes
.
@@ -76,82 +77,25 @@ func (b *backend) Login(ctx context.Context, req *logical.Request, username stri | |||
return "", nil, logical.ErrorResponse("password cannot be of zero length when passwordless binds are being denied"), nil, nil | |||
} | |||
|
|||
ldapClient := ldaputil.Client{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👋🏼
if strings.Contains(err.Error(), "discovery of user bind DN failed") || | ||
strings.Contains(err.Error(), "unable to bind user") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A little manual, as the cap/ldap
library doesn't have any exported error types we can leverage.
Build Results: |
I'm happy to see cap/ldap get adopted by Vault! I just have one question/suggestion, but otherwise it looks good. |
builtin/credential/ldap/backend.go
Outdated
return "", nil, logical.ErrorResponse(err.Error()), nil, nil | ||
} | ||
if entityAliasAttribute == "" { | ||
cn := c.UserAttributes["cn"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this is quite correct. It appears that
Client.GetUserAliasAttributeValue(...)
retrieves cfg.UserAttr
which could be
really any attribute name (of course it's typically cn
or uid
). So perhaps
this should be something like userAttrValues := c.UserAttributes[cfg.UserAttr]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, thanks for catching this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking this on, @raymonstah! Looking good. Left a few questions/suggestions.
return "", nil, logical.ErrorResponse(err.Error()), nil, nil | ||
} | ||
if entityAliasAttribute == "" { | ||
userAttrValues := c.UserAttributes[cfg.UserAttr] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UUIC c.UserAttributes[cfg.UserAttr]
is set from cap/ldap getUserBindDN()
? Would be worth double-checking that the cap/ldap implementation would result in the same entity alias as the prior code in GetUserAliasAttributeValue()
. We've have entity alias changes result in privilege escalation in the past so worth a look!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it seems like the cap/ldap implementation doesn't apply the userfilter
but I'm not sure if that would matter since the userfilter
would've already been applied from the search to get the user bind dn.
But based on the existing client,
vault/sdk/helper/ldaputil/client.go
Line 149 in be83f12
cfg.UserAttr, // Return only needed attributes |
cfg.UserAttr
as well.
sdk/helper/ldaputil/config.go
Outdated
StartTLS: cfg.StartTLS, | ||
BindDN: cfg.BindDN, | ||
BindPassword: cfg.BindPassword, | ||
AllowEmptyPasswordBinds: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering if this should be cfg.DenyNullBind
instead of true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I think that's correct. or more accurately, !cfg.DenyNullBind
. Updated!
Closing, until pagination gets added to |
…-cap-ldap-library
…-cap-ldap-library
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM given that our tests are passing. Thanks for following up on this @raymonstah!
sdk/helper/ldaputil/client.go
Outdated
@@ -24,6 +24,7 @@ import ( | |||
"github.com/hashicorp/go-secure-stdlib/tlsutil" | |||
) | |||
|
|||
// Deprecated: Use ldap.Client instead |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking we'll want to leave this as not deprecated. It's still used in a couple of different plugins (openldap example) for secrets engine use cases. I don't think cap/ldap will ever replace the usage given that it's targeted at authentication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a minor bit about go.sum
Co-authored-by: Sarah Chavis <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ty!
Summary
Introduces the cap/ldap package as an alternative to the existing LDAP client. This allows for better security updates, patches, etc in one library to improve DRY-ness across our repos that leverage LDAP. Internally, this addresses VAULT-18227.
Note:
Since the cap/ldap package doesn't differentiate between
connection_timeout
andrequest_timeout
like Vault does, this also introduces a change where it takes the minimum timeout between the two values, and uses that as the timeout for both. As a result, this PR also deprecates theconnection_timeout
field introduced in #20144. As a result,ldaputil.Client
has also been deprecated, sincecap/ldap.Client
can be used to replace it.Testing
Configuration
Valid credentials
Wrong username
Wrong Password