diff --git a/auth/token_issuer.go b/auth/token_issuer.go index 57d6369..2d5aecb 100644 --- a/auth/token_issuer.go +++ b/auth/token_issuer.go @@ -7,6 +7,7 @@ import ( "github.com/apprenda-kismatic/kubernetes-ldap/token" goldap "github.com/go-ldap/ldap" "github.com/golang/glog" + "strings" ) // LDAPTokenIssuer issues cryptographically secure tokens after authenticating the @@ -48,9 +49,25 @@ func (lti *LDAPTokenIssuer) ServeHTTP(resp http.ResponseWriter, req *http.Reques resp.Write([]byte(signedToken)) } +func (lti *LDAPTokenIssuer) getGroupsFromMembersOf(membersOf string) []string { + //memberOf: CN=Group1,CN=Users,DC=lab,DC=proofpoint,DC=com + + var groupsOf []string + + splitted_str := strings.Split(membersOf, ",") + for _, element := range splitted_str { + if strings.Contains(element, "CN=") { + groupsOf = append(groupsOf, strings.Replace(element, "CN=", "", 1)) + } + } + + return groupsOf +} + func (lti *LDAPTokenIssuer) createToken(ldapEntry *goldap.Entry) *token.AuthToken { return &token.AuthToken{ - Username: ldapEntry.DN, + Username: ldapEntry.GetAttributeValue("mail"), + Groups: lti.getGroupsFromMembersOf(ldapEntry.GetAttributeValue("memberOf")), Assertions: map[string]string{ "ldapServer": lti.LDAPServer, "userDN": ldapEntry.DN, diff --git a/auth/webhook.go b/auth/webhook.go index f04e3c6..7a9dfc3 100644 --- a/auth/webhook.go +++ b/auth/webhook.go @@ -50,6 +50,7 @@ func (tw *TokenWebhook) ServeHTTP(resp http.ResponseWriter, req *http.Request) { Authenticated: true, User: UserInfo{ Username: token.Username, + Groups: token.Groups, }, } diff --git a/cmd/kubernetes-ldap.go b/cmd/kubernetes-ldap.go index 3a7980c..72833a4 100755 --- a/cmd/kubernetes-ldap.go +++ b/cmd/kubernetes-ldap.go @@ -20,7 +20,7 @@ const ( usage = "kubernetes-ldap " ) -var flLdapAllowInsecure = flag.Bool("ldap-insecure", false, "Disable LDAP TLS") +var flLdapUseInsecure = flag.Bool("ldap-insecure", false, "Disable LDAP TLS") var flLdapHost = flag.String("ldap-host", "", "Host or IP of the LDAP server") var flLdapPort = flag.Uint("ldap-port", 389, "LDAP server port") var flBaseDN = flag.String("ldap-base-dn", "", "LDAP user base DN in the form 'dc=example,dc=com'") @@ -78,7 +78,7 @@ func main() { BaseDN: *flBaseDN, LdapServer: *flLdapHost, LdapPort: *flLdapPort, - AllowInsecure: *flLdapAllowInsecure, + UseInsecure: *flLdapUseInsecure, UserLoginAttribute: *flUserLoginAttribute, SearchUserDN: *flSearchUserDN, SearchUserPassword: *flSearchUserPassword, diff --git a/ldap/client.go b/ldap/client.go index af147e1..e994504 100644 --- a/ldap/client.go +++ b/ldap/client.go @@ -19,7 +19,7 @@ type Client struct { BaseDN string LdapServer string LdapPort uint - AllowInsecure bool + UseInsecure bool UserLoginAttribute string SearchUserDN string SearchUserPassword string @@ -41,6 +41,7 @@ func (c *Client) Authenticate(username, password string) (*ldap.Entry, error) { } else { err = conn.Bind(username, password) } + if err != nil { return nil, fmt.Errorf("Error binding user to LDAP server: %v", err) } @@ -59,7 +60,7 @@ func (c *Client) Authenticate(username, password string) (*ldap.Entry, error) { case len(res.Entries) > 1: return nil, fmt.Errorf("Multiple entries found for the search filter '%s': %+v", req.Filter, res.Entries) } - + // Now that we know the user exists within the BaseDN scope // let's do user bind to check credentials using the full DN instead of // the attribute used for search @@ -78,13 +79,13 @@ func (c *Client) Authenticate(username, password string) (*ldap.Entry, error) { func (c *Client) dial() (*ldap.Conn, error) { address := fmt.Sprintf("%s:%d", c.LdapServer, c.LdapPort) - if c.TLSConfig != nil { + if c.TLSConfig != nil && !c.UseInsecure { return ldap.DialTLS("tcp", address, c.TLSConfig) } // This will send passwords in clear text (LDAP doesn't obfuscate password in any way), // thus we use a flag to enable this mode - if c.TLSConfig == nil && c.AllowInsecure { + if c.UseInsecure { return ldap.Dial("tcp", address) } diff --git a/token/token.go b/token/token.go index 45b7e7c..1498fd1 100644 --- a/token/token.go +++ b/token/token.go @@ -22,6 +22,7 @@ var curveEll = elliptic.P256() // AuthToken contains information about the authenticated user type AuthToken struct { Username string + Groups []string Assertions map[string]string }