From b501e0370311e2824bcd121f740c8571f9999922 Mon Sep 17 00:00:00 2001 From: Darren Hague Date: Fri, 11 Nov 2016 18:08:27 +0000 Subject: [PATCH] Multi-domain login --- pkg/api/keystone/keystone.go | 28 ++++++++++++++++++++-------- pkg/login/auth.go | 7 ++++++- pkg/login/keystone.go | 12 ++++++++++-- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/pkg/api/keystone/keystone.go b/pkg/api/keystone/keystone.go index 8057314527111..818a15cc461cd 100644 --- a/pkg/api/keystone/keystone.go +++ b/pkg/api/keystone/keystone.go @@ -14,6 +14,7 @@ import ( m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" "io" + "strings" ) const ( @@ -84,19 +85,20 @@ func getNewToken(c *middleware.Context) (string, error) { log.Warn("Password stored in cleartext!") } + user, domain := UserDomain(username) + keystoneProject := strings.Replace(project, "@"+domain, "", 1) auth := Auth_data{ - Username: username, - Project: project, + Username: user, + Project: keystoneProject, Password: keystonePasswordObj.(string), - Domain: setting.KeystoneDefaultDomain, + Domain: domain, Server: setting.KeystoneURL, } if err := AuthenticateScoped(&auth); err != nil { - if setting.KeystoneCookieCredentials { - c.SetCookie(middleware.SESS_KEY_PASSWORD, "", -1, setting.AppSubUrl+"/", nil, middleware.IsSecure(c), true) - } else { - c.Session.Set(middleware.SESS_KEY_PASSWORD, nil) - } + c.SetCookie(setting.CookieUserName, "", -1, setting.AppSubUrl+"/", nil, middleware.IsSecure(c), true) + c.SetCookie(setting.CookieRememberName, "", -1, setting.AppSubUrl+"/", nil, middleware.IsSecure(c), true) + c.SetCookie(middleware.SESS_KEY_PASSWORD, "", -1, setting.AppSubUrl+"/", nil, middleware.IsSecure(c), true) + c.Session.Destory(c) return "", err } @@ -195,3 +197,13 @@ func decryptPassword(base64ciphertext string) string { stream.XORKeyStream(password, ciphertext[aes.BlockSize:]) return string(password) } + +func UserDomain(username string) (string, string) { + user := username + domain := setting.KeystoneDefaultDomain + if at_idx := strings.IndexRune(username, '@'); at_idx > 0 { + domain = username[at_idx+1:] + user = username[:at_idx] + } + return user, domain +} diff --git a/pkg/login/auth.go b/pkg/login/auth.go index d229cf95143c5..6183dc9db71d9 100644 --- a/pkg/login/auth.go +++ b/pkg/login/auth.go @@ -4,6 +4,7 @@ import ( "errors" "crypto/subtle" + "github.com/grafana/grafana/pkg/api/keystone" "github.com/grafana/grafana/pkg/bus" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" @@ -42,8 +43,12 @@ func AuthenticateUser(query *LoginUserQuery) error { } if setting.KeystoneEnabled { + user, domain := keystone.UserDomain(query.Username) + if domain == setting.KeystoneDefaultDomain { + query.Username = user + } auther := NewKeystoneAuthenticator(setting.KeystoneURL, - setting.KeystoneDefaultDomain, + domain, setting.KeystoneDefaultRole, setting.KeystoneGlobalAdminRoles, setting.KeystoneAdminRoles, diff --git a/pkg/login/keystone.go b/pkg/login/keystone.go index fe4c3c38cc07a..9c7c6b9a65dcc 100644 --- a/pkg/login/keystone.go +++ b/pkg/login/keystone.go @@ -56,9 +56,10 @@ func (a *keystoneAuther) login(query *LoginUserQuery) error { } func (a *keystoneAuther) authenticate(username, password string) error { + user, _ := keystone.UserDomain(username) auth := keystone.Auth_data{ Server: a.server, - Username: username, + Username: user, Password: password, Domain: a.domainname, } @@ -109,10 +110,14 @@ func (a *keystoneAuther) updateGrafanaUserPermissions(userid int64, isAdmin bool } func (a *keystoneAuther) getGrafanaOrgFor(orgname string) (*m.Org, error) { + + log.Debug("getGrafanaOrgFor( %v )", orgname) + // get org from grafana db orgQuery := m.GetOrgByNameQuery{Name: orgname} if err := bus.Dispatch(&orgQuery); err != nil { if err == m.ErrOrgNotFound { + log.Debug("orgname %s not found - create it", orgname) return a.createGrafanaOrg(orgname) } else { return nil, err @@ -209,6 +214,7 @@ func (a *keystoneAuther) syncOrgRoles(username, password string, user *m.User) e // add missing org roles for project, _ := range a.project_list { if grafanaOrg, err := a.getGrafanaOrgFor(project); err != nil { + log.Error(3, "Couldn't find Grafana org %s", project) return err } else { if _, exists := handledOrgIds[grafanaOrg.Id]; exists { @@ -284,6 +290,7 @@ func (a *keystoneAuther) syncOrgRoles(username, password string, user *m.User) e } func (a *keystoneAuther) getProjectList(username, password string) error { + log.Trace("getProjectList() with username %s", username) projects_data := keystone.Projects_data{ Token: a.token, Server: a.server, @@ -306,12 +313,13 @@ func (a *keystoneAuther) getProjectList(username, password string) error { for _, role := range auth.Roles { roles = append(roles, role.Name) } - a.project_list[project] = roles + a.project_list[project+"@"+a.domainname] = roles } return nil } func (a *keystoneAuther) getRole(user_roles []string) m.RoleType { + log.Trace("getRole(%v)", user_roles) role_map := make(map[string]bool) for _, role := range user_roles { role_map[role] = true