Add logic mapping applying a mapping

pull/10616/head
Michael Desa 2018-01-11 12:36:13 -05:00
parent b3f917e56c
commit a61eb73a19
2 changed files with 502 additions and 0 deletions

111
server/mapping.go Normal file
View File

@ -0,0 +1,111 @@
package server
import (
"strings"
"github.com/influxdata/chronograf"
"github.com/influxdata/chronograf/oauth2"
"github.com/influxdata/chronograf/roles"
)
func MappedRole(o *chronograf.Organization, p oauth2.Principal) *chronograf.Role {
roles := []*chronograf.Role{}
for _, mapping := range o.Mappings {
role := applyMapping(mapping, p)
if role != nil {
role.Organization = o.ID
roles = append(roles, role)
}
}
return maxRole(roles)
}
func applyMapping(m chronograf.Mapping, p oauth2.Principal) *chronograf.Role {
switch m.Provider {
case chronograf.MappingWildcard, p.Issuer:
default:
return nil
}
switch m.Scheme {
case chronograf.MappingWildcard, "oauth2":
default:
return nil
}
if m.Group == chronograf.MappingWildcard {
return &chronograf.Role{
Name: m.GrantedRole,
}
}
groups := strings.Split(p.Group, ",")
match := matchGroup(m.Group, groups)
if match {
return &chronograf.Role{
Name: m.GrantedRole,
}
}
return nil
}
func matchGroup(match string, groups []string) bool {
for _, group := range groups {
if match == group {
return true
}
}
return false
}
func maxRole(roles []*chronograf.Role) *chronograf.Role {
var max *chronograf.Role
for _, role := range roles {
max = maximumRole(max, role)
}
return max
}
func maximumRole(r1, r2 *chronograf.Role) *chronograf.Role {
if r1 == nil {
return r2
}
if r2 == nil {
return r2
}
if r1.Name == roles.AdminRoleName {
return r1
}
if r2.Name == roles.AdminRoleName {
return r2
}
if r1.Name == roles.EditorRoleName {
return r1
}
if r2.Name == roles.EditorRoleName {
return r2
}
if r1.Name == roles.ViewerRoleName {
return r1
}
if r2.Name == roles.ViewerRoleName {
return r2
}
if r1.Name == roles.MemberRoleName {
return r1
}
if r2.Name == roles.MemberRoleName {
return r2
}
return nil
}

391
server/mapping_test.go Normal file
View File

@ -0,0 +1,391 @@
package server_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/influxdata/chronograf"
"github.com/influxdata/chronograf/oauth2"
"github.com/influxdata/chronograf/roles"
"github.com/influxdata/chronograf/server"
)
func TestMappedRole(t *testing.T) {
type args struct {
org *chronograf.Organization
principal oauth2.Principal
}
type wants struct {
role *chronograf.Role
}
tests := []struct {
name string
args args
wants wants
}{
{
name: "single mapping all wildcards",
args: args{
org: &chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.ViewerRoleName,
Organization: "cool",
},
},
},
{
name: "two mapping all wildcards",
args: args{
org: &chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.EditorRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.EditorRoleName,
Organization: "cool",
},
},
},
{
name: "two mapping all wildcards, different order",
args: args{
org: &chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.EditorRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.EditorRoleName,
Organization: "cool",
},
},
},
{
name: "two mappings with explicit principal",
args: args{
principal: oauth2.Principal{
Subject: "billieta@influxdata.com",
Issuer: "google",
Group: "influxdata.com",
},
org: &chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: "oauth2",
Group: chronograf.MappingWildcard,
GrantedRole: roles.MemberRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.MemberRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.MemberRoleName,
Organization: "cool",
},
},
},
{
name: "different two mapping all wildcards",
args: args{
org: &chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.MemberRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.ViewerRoleName,
Organization: "cool",
},
},
},
{
name: "different two mapping all wildcards, different ordering",
args: args{
org: &chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.MemberRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.ViewerRoleName,
Organization: "cool",
},
},
},
{
name: "three mapping all wildcards",
args: args{
org: &chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.EditorRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.AdminRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.AdminRoleName,
Organization: "cool",
},
},
},
{
name: "three mapping only one match",
args: args{
principal: oauth2.Principal{
Subject: "billieta@influxdata.com",
Issuer: "google",
Group: "influxdata.com",
},
org: &chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: "google",
Scheme: chronograf.MappingWildcard,
Group: "influxdata.com",
GrantedRole: roles.EditorRoleName,
},
chronograf.Mapping{
Provider: "google",
Scheme: chronograf.MappingWildcard,
Group: "not_influxdata",
GrantedRole: roles.AdminRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: "ldap",
Group: chronograf.MappingWildcard,
GrantedRole: roles.AdminRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.EditorRoleName,
Organization: "cool",
},
},
},
{
name: "three mapping only two matches",
args: args{
principal: oauth2.Principal{
Subject: "billieta@influxdata.com",
Issuer: "google",
Group: "influxdata.com",
},
org: &chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: "google",
Scheme: chronograf.MappingWildcard,
Group: "influxdata.com",
GrantedRole: roles.AdminRoleName,
},
chronograf.Mapping{
Provider: "google",
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.EditorRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: "ldap",
Group: chronograf.MappingWildcard,
GrantedRole: roles.AdminRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.AdminRoleName,
Organization: "cool",
},
},
},
{
name: "missing provider",
args: args{
principal: oauth2.Principal{
Subject: "billieta@influxdata.com",
Issuer: "google",
Group: "influxdata.com",
},
org: &chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: "",
Scheme: "ldap",
Group: chronograf.MappingWildcard,
GrantedRole: roles.AdminRoleName,
},
},
},
},
wants: wants{
role: nil,
},
},
{
name: "user is in multiple github groups",
args: args{
principal: oauth2.Principal{
Subject: "billieta@influxdata.com",
Issuer: "github",
Group: "influxdata,another,mimi",
},
org: &chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: "github",
Scheme: chronograf.MappingWildcard,
Group: "influxdata",
GrantedRole: roles.MemberRoleName,
},
chronograf.Mapping{
Provider: "github",
Scheme: chronograf.MappingWildcard,
Group: "mimi",
GrantedRole: roles.EditorRoleName,
},
chronograf.Mapping{
Provider: "github",
Scheme: chronograf.MappingWildcard,
Group: "another",
GrantedRole: roles.AdminRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.AdminRoleName,
Organization: "cool",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
role := server.MappedRole(tt.args.org, tt.args.principal)
if diff := cmp.Diff(role, tt.wants.role); diff != "" {
t.Errorf("%q. MappedRole():\n-got/+want\ndiff %s", tt.name, diff)
}
})
}
}