9
9
"strings"
10
10
"sync"
11
11
12
+ goldap "github.com/go-ldap/ldap/v3"
12
13
"github.com/hashicorp/cap/ldap"
13
14
"github.com/hashicorp/go-secure-stdlib/strutil"
14
15
"github.com/hashicorp/vault/sdk/framework"
@@ -69,6 +70,14 @@ type backend struct {
69
70
mu sync.RWMutex
70
71
}
71
72
73
+ func (b * backend ) maybeLogDebug (msg string , args ... interface {}) {
74
+ if b .Logger ().IsDebug () {
75
+ b .Logger ().Debug (msg , args ... )
76
+ }
77
+ }
78
+
79
+ // Login authenticates a user against the LDAP server using the provided username and password.
80
+ // It returns the effective username, policies associated with the user, a response containing
72
81
func (b * backend ) Login (ctx context.Context , req * logical.Request , username string , password string , usernameAsAlias bool ) (string , []string , * logical.Response , []string , error ) {
73
82
cfg , err := b .Config (ctx , req )
74
83
if err != nil {
@@ -84,9 +93,7 @@ func (b *backend) Login(ctx context.Context, req *logical.Request, username stri
84
93
85
94
ldapClient , err := ldap .NewClient (ctx , ldaputil .ConvertConfig (cfg .ConfigEntry ))
86
95
if err != nil {
87
- if b .Logger ().IsDebug () {
88
- b .Logger ().Debug ("error creating client" , "error" , err )
89
- }
96
+ b .maybeLogDebug ("error creating client" , "error" , err )
90
97
return "" , nil , logical .ErrorResponse (err .Error ()), nil , nil
91
98
}
92
99
@@ -97,17 +104,16 @@ func (b *backend) Login(ctx context.Context, req *logical.Request, username stri
97
104
if err != nil {
98
105
if strings .Contains (err .Error (), "discovery of user bind DN failed" ) ||
99
106
strings .Contains (err .Error (), "unable to bind user" ) {
100
- if b .Logger ().IsDebug () {
101
- b .Logger ().Debug ("error getting user bind DN" , "error" , err )
102
- }
107
+ b .maybeLogDebug ("error getting user bind DN" , username , "error" , err )
103
108
return "" , nil , logical .ErrorResponse (errUserBindFailed ), nil , logical .ErrInvalidCredentials
104
109
}
105
110
106
111
return "" , nil , logical .ErrorResponse (err .Error ()), nil , nil
107
112
}
108
113
109
- if b .Logger ().IsDebug () {
110
- b .Logger ().Debug ("user binddn fetched" , "username" , username , "binddn" , c .UserDN )
114
+ b .maybeLogDebug ("user binddn fetched" , "username" , username , "binddn" , c .UserDN )
115
+ if c .UserDN == "" {
116
+ return "" , nil , logical .ErrorResponse ("user bind DN is empty after authentication" ), nil , nil
111
117
}
112
118
113
119
ldapGroups := c .Groups
@@ -119,36 +125,59 @@ func (b *backend) Login(ctx context.Context, req *logical.Request, username stri
119
125
"no LDAP groups found in groupDN %q; only policies from locally-defined groups available" ,
120
126
cfg .GroupDN )
121
127
122
- if b .Logger ().IsDebug () {
123
- b .Logger ().Debug (errString )
124
- }
128
+ b .maybeLogDebug (errString )
125
129
}
126
130
127
131
for _ , warning := range c .Warnings {
128
- if b .Logger ().IsDebug () {
129
- b .Logger ().Debug (string (warning ))
132
+ b .maybeLogDebug (string (warning ))
133
+ }
134
+
135
+ canonicalUsername := username
136
+ if usernameAsAlias {
137
+ // expect to get the username from UserDN in the case where we are setting the
138
+ // entity alias to be the username.
139
+ parsed , err := goldap .ParseDN (c .UserDN )
140
+ if err != nil {
141
+ b .Logger ().Error ("Invalid DN after authentication" , "user_dn" , c .UserDN , "error" , err )
142
+ return "" , nil , logical .ErrorResponse ("invalid DN after authentication" ), nil , nil
143
+ }
144
+
145
+ b .maybeLogDebug ("User DN parsed" , "parsed" , parsed , "username" , username )
146
+ var found bool
147
+ for _ , rdn := range parsed .RDNs {
148
+ if found {
149
+ b .maybeLogDebug ("Found canonical username" , "canonicalUsername" , canonicalUsername , "cfg.userAttr" , cfg .UserAttr )
150
+ break
151
+ }
152
+ for _ , attr := range rdn .Attributes {
153
+ b .maybeLogDebug ("Handling RDN" , "attr.Type" , attr .Type , "attr.Value" , attr .Value , "cfg.UserAttr" , cfg .UserAttr )
154
+ if strings .EqualFold (attr .Type , cfg .UserAttr ) {
155
+ b .maybeLogDebug ("Found user attribute in RDN" , "attr.Type" , attr .Type , "attr.Value" , attr .Value )
156
+ canonicalUsername = attr .Value
157
+ found = true
158
+ break
159
+ }
160
+ }
130
161
}
131
162
}
132
163
133
164
var allGroups []string
134
- canonicalUsername := username
135
- cs := * cfg .CaseSensitiveNames
165
+
166
+ cs := cfg . CaseSensitiveNames != nil && * cfg .CaseSensitiveNames
136
167
if ! cs {
137
- canonicalUsername = strings .ToLower (username )
168
+ canonicalUsername = strings .ToLower (canonicalUsername )
138
169
}
170
+
139
171
// Import the custom added groups from ldap backend
140
172
user , err := b .User (ctx , req .Storage , canonicalUsername )
141
173
if err == nil && user != nil && user .Groups != nil {
142
- if b .Logger ().IsDebug () {
143
- b .Logger ().Debug ("adding local groups" , "num_local_groups" , len (user .Groups ), "local_groups" , user .Groups )
144
- }
145
174
allGroups = append (allGroups , user .Groups ... )
146
175
}
147
176
// Merge local and LDAP groups
148
177
allGroups = append (allGroups , ldapGroups ... )
149
178
150
179
canonicalGroups := allGroups
151
- // If not case sensitive, lowercase all
180
+ // If not case- sensitive, lowercase all
152
181
if ! cs {
153
182
canonicalGroups = make ([]string , len (allGroups ))
154
183
for i , v := range allGroups {
@@ -171,19 +200,23 @@ func (b *backend) Login(ctx context.Context, req *logical.Request, username stri
171
200
policies = strutil .RemoveDuplicates (policies , true )
172
201
173
202
if usernameAsAlias {
174
- return username , policies , ldapResponse , allGroups , nil
203
+ b .maybeLogDebug ("UsernameAlias is set" , "canonicalUsername" , canonicalUsername , "policies" , policies , "groups" , allGroups )
204
+ return canonicalUsername , policies , ldapResponse , allGroups , nil
175
205
}
176
206
177
207
userAttrValues := c .UserAttributes [cfg .UserAttr ]
178
208
if len (userAttrValues ) == 0 {
179
- if b .Logger ().IsDebug () {
180
- b .Logger ().Debug ("missing entity alias attribute value" )
181
- }
209
+ b .Logger ().Error ("missing entity alias attribute value" )
182
210
return "" , nil , logical .ErrorResponse ("missing entity alias attribute value" ), nil , nil
183
211
}
184
- entityAliasAttribute := userAttrValues [0 ]
185
212
186
- return entityAliasAttribute , policies , ldapResponse , allGroups , nil
213
+ effectiveUsername := userAttrValues [0 ]
214
+ if effectiveUsername == "" {
215
+ b .Logger ().Error ("empty entity alias attribute value" )
216
+ return "" , nil , logical .ErrorResponse ("empty entity alias attribute value" ), nil , nil
217
+ }
218
+
219
+ return effectiveUsername , policies , ldapResponse , allGroups , nil
187
220
}
188
221
189
222
const backendHelp = `
0 commit comments