Skip to content

Commit

Permalink
Fix ldap client upndomain (#8333)
Browse files Browse the repository at this point in the history
  • Loading branch information
michelvocks committed Feb 14, 2020
1 parent 644a9f1 commit 348b04e
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 12 deletions.
2 changes: 1 addition & 1 deletion builtin/credential/ldap/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func (b *backend) Login(ctx context.Context, req *logical.Request, username stri
}
}

userDN, err := ldapClient.GetUserDN(cfg.ConfigEntry, c, userBindDN)
userDN, err := ldapClient.GetUserDN(cfg.ConfigEntry, c, userBindDN, username)
if err != nil {
return nil, logical.ErrorResponse(err.Error()), nil, nil
}
Expand Down
68 changes: 67 additions & 1 deletion builtin/credential/ldap/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (
"testing"
"time"

goldap "github.com/go-ldap/ldap/v3"
"github.com/go-test/deep"
hclog "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/helper/testhelpers/ldap"
logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical"
Expand Down Expand Up @@ -397,7 +399,10 @@ func factory(t *testing.T) logical.Backend {
defaultLeaseTTLVal := time.Hour * 24
maxLeaseTTLVal := time.Hour * 24 * 32
b, err := Factory(context.Background(), &logical.BackendConfig{
Logger: nil,
Logger: hclog.New(&hclog.LoggerOptions{
Name: "FactoryLogger",
Level: hclog.Debug,
}),
System: &logical.StaticSystemView{
DefaultLeaseTTLVal: defaultLeaseTTLVal,
MaxLeaseTTLVal: maxLeaseTTLVal,
Expand Down Expand Up @@ -495,6 +500,66 @@ func TestBackend_basic_authbind(t *testing.T) {
})
}

func TestBackend_basic_authbind_upndomain(t *testing.T) {
b := factory(t)
cleanup, cfg := ldap.PrepareTestContainer(t, "latest")
defer cleanup()
cfg.UPNDomain = "planetexpress.com"

// Setup connection
client := &ldaputil.Client{
Logger: hclog.New(&hclog.LoggerOptions{
Name: "LDAPAuthTest",
Level: hclog.Debug,
}),
LDAP: ldaputil.NewLDAP(),
}
conn, err := client.DialLDAP(cfg)
if err != nil {
t.Fatal(err)
}
defer conn.Close()
if err := conn.Bind("cn=admin,cn=config", cfg.BindPassword); err != nil {
t.Fatal(err)
}

// Add userPrincipalName attribute type
userPrincipleNameTypeReq := goldap.NewModifyRequest("cn={0}core,cn=schema,cn=config", nil)
userPrincipleNameTypeReq.Add("olcAttributetypes", []string{"( 2.25.247072656268950430024439664556757516066 NAME ( 'userPrincipalName' ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 EQUALITY caseIgnoreMatch SINGLE-VALUE )"})
if err := conn.Modify(userPrincipleNameTypeReq); err != nil {
t.Fatal(err)
}

// Add new object class
userPrincipleNameObjClassReq := goldap.NewModifyRequest("cn={0}core,cn=schema,cn=config", nil)
userPrincipleNameObjClassReq.Add("olcObjectClasses", []string{"( 1.2.840.113556.6.2.6 NAME 'PrincipalNameClass' AUXILIARY MAY ( userPrincipalName ) )"})
if err := conn.Modify(userPrincipleNameObjClassReq); err != nil {
t.Fatal(err)
}

// Re-authenticate with the binddn user
if err := conn.Bind(cfg.BindDN, cfg.BindPassword); err != nil {
t.Fatal(err)
}

// Modify professor user and add userPrincipalName attribute
profDN := "cn=Hubert J. Farnsworth,ou=people,dc=planetexpress,dc=com"
modifyUserReq := goldap.NewModifyRequest(profDN, nil)
modifyUserReq.Add("objectClass", []string{"PrincipalNameClass"})
modifyUserReq.Add("userPrincipalName", []string{"professor@planetexpress.com"})
if err := conn.Modify(modifyUserReq); err != nil {
t.Fatal(err)
}

logicaltest.Test(t, logicaltest.TestCase{
CredentialBackend: b,
Steps: []logicaltest.TestStep{
testAccStepConfigUrlWithAuthBind(t, cfg),
testAccStepLoginNoAttachedPolicies(t, "professor", "professor"),
},
})
}

func TestBackend_basic_discover(t *testing.T) {
b := factory(t)
cleanup, cfg := ldap.PrepareTestContainer(t, "latest")
Expand Down Expand Up @@ -626,6 +691,7 @@ func testAccStepConfigUrlWithAuthBind(t *testing.T, cfg *ldaputil.ConfigEntry) l
"groupattr": cfg.GroupAttr,
"binddn": cfg.BindDN,
"bindpass": cfg.BindPassword,
"upndomain": cfg.UPNDomain,
"case_sensitive_names": true,
"token_policies": "abc,xyz",
"request_timeout": cfg.RequestTimeout,
Expand Down
6 changes: 4 additions & 2 deletions helper/testhelpers/ldap/ldaphelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"fmt"
"testing"

"github.com/hashicorp/go-hclog"
hclog "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/helper/testhelpers/docker"
"github.com/hashicorp/vault/sdk/helper/ldaputil"
"github.com/ory/dockertest"
Expand All @@ -17,7 +17,9 @@ func PrepareTestContainer(t *testing.T, version string) (cleanup func(), cfg *ld
}

dockerOptions := &dockertest.RunOptions{
Repository: "rroemhild/test-openldap",
// Currently set to "michelvocks" until https://github.com/rroemhild/docker-test-openldap/pull/14
// has been merged.
Repository: "michelvocks/docker-test-openldap",
Tag: version,
Privileged: true,
//Env: []string{"LDAP_DEBUG_LEVEL=384"},
Expand Down
13 changes: 9 additions & 4 deletions sdk/helper/ldaputil/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ func (c *Client) GetUserBindDN(cfg *ConfigEntry, conn Connection, username strin
}

filter := fmt.Sprintf("(%s=%s)", cfg.UserAttr, ldap.EscapeFilter(username))
if cfg.UPNDomain != "" {
filter = fmt.Sprintf("(userPrincipalName=%s@%s)", EscapeLDAPValue(username), cfg.UPNDomain)
}

if c.Logger.IsDebug() {
c.Logger.Debug("discovering user", "userdn", cfg.UserDN, "filter", filter)
}
Expand Down Expand Up @@ -150,11 +154,11 @@ func (c *Client) GetUserBindDN(cfg *ConfigEntry, conn Connection, username strin
/*
* Returns the DN of the object representing the authenticated user.
*/
func (c *Client) GetUserDN(cfg *ConfigEntry, conn Connection, bindDN string) (string, error) {
func (c *Client) GetUserDN(cfg *ConfigEntry, conn Connection, bindDN, username string) (string, error) {
userDN := ""
if cfg.UPNDomain != "" {
// Find the distinguished name for the user if userPrincipalName used for login
filter := fmt.Sprintf("(userPrincipalName=%s)", ldap.EscapeFilter(bindDN))
filter := fmt.Sprintf("(userPrincipalName=%s@%s)", EscapeLDAPValue(username), cfg.UPNDomain)
if c.Logger.IsDebug() {
c.Logger.Debug("searching upn", "userdn", cfg.UserDN, "filter", filter)
}
Expand All @@ -167,9 +171,10 @@ func (c *Client) GetUserDN(cfg *ConfigEntry, conn Connection, bindDN string) (st
if err != nil {
return userDN, errwrap.Wrapf("LDAP search failed for detecting user: {{err}}", err)
}
for _, e := range result.Entries {
userDN = e.DN
if len(result.Entries) != 1 {
return userDN, fmt.Errorf("LDAP search for userdn 0 or not unique")
}
userDN = result.Entries[0].DN
} else {
userDN = bindDN
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 348b04e

Please sign in to comment.