open-nomad/lib/auth/oidc/binder_test.go

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

182 lines
3.9 KiB
Go
Raw Normal View History

package oidc
import (
"testing"
"github.com/shoenig/test/must"
"github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/helper/uuid"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/state"
"github.com/hashicorp/nomad/nomad/structs"
)
func TestBinder_Bind(t *testing.T) {
ci.Parallel(t)
testStore := state.TestStateStore(t)
testBind := NewBinder(testStore)
// create an authMethod method and insert into the state store
authMethod := mock.ACLAuthMethod()
must.NoError(t, testStore.UpsertACLAuthMethods(0, []*structs.ACLAuthMethod{authMethod}))
// create some roles and insert into the state store
targetRole := &structs.ACLRole{
ID: uuid.Generate(),
Name: "vim-role",
}
otherRole := &structs.ACLRole{
ID: uuid.Generate(),
Name: "frontend-engineers",
}
must.NoError(t, testStore.UpsertACLRoles(
structs.MsgTypeTestSetup, 0, []*structs.ACLRole{targetRole, otherRole}, true,
))
// create binding rules and insert into the state store
bindingRules := []*structs.ACLBindingRule{
{
ID: uuid.Generate(),
Selector: "role==engineer",
BindType: structs.ACLBindingRuleBindTypeRole,
BindName: "${editor}-role",
AuthMethod: authMethod.Name,
},
{
ID: uuid.Generate(),
Selector: "role==engineer",
BindType: structs.ACLBindingRuleBindTypeRole,
BindName: "this-role-does-not-exist",
AuthMethod: authMethod.Name,
},
{
ID: uuid.Generate(),
Selector: "language==js",
BindType: structs.ACLBindingRuleBindTypeRole,
BindName: otherRole.Name,
AuthMethod: authMethod.Name,
},
}
must.NoError(t, testStore.UpsertACLBindingRules(0, bindingRules, true))
tests := []struct {
name string
authMethod *structs.ACLAuthMethod
identity *Identity
want *Bindings
wantErr bool
}{
{
"empty identity",
authMethod,
&Identity{},
&Bindings{},
false,
},
{
"role",
authMethod,
&Identity{
Claims: map[string]string{
"role": "engineer",
"language": "go",
},
ClaimMappings: map[string]string{
"editor": "vim",
},
},
&Bindings{Roles: []*structs.ACLTokenRoleLink{{ID: targetRole.ID}}},
false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := testBind.Bind(tt.authMethod, tt.identity)
if tt.wantErr {
must.Error(t, err)
} else {
must.NoError(t, err)
}
must.Eq(t, got, tt.want)
})
}
}
func Test_computeBindName(t *testing.T) {
ci.Parallel(t)
tests := []struct {
name string
bindType string
bindName string
claimMappings map[string]string
wantName string
wantTrue bool
wantErr bool
}{
{
"valid bind name and type",
structs.ACLBindingRuleBindTypeRole,
"cluster-admin",
map[string]string{"cluster-admin": "root"},
"cluster-admin",
true,
false,
},
{
"invalid type",
"amazing",
"cluster-admin",
map[string]string{"cluster-admin": "root"},
"",
false,
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, got1, err := computeBindName(tt.bindType, tt.bindName, tt.claimMappings)
if tt.wantErr {
must.NotNil(t, err)
}
must.Eq(t, got, tt.wantName)
must.Eq(t, got1, tt.wantTrue)
})
}
}
func Test_doesSelectorMatch(t *testing.T) {
ci.Parallel(t)
tests := []struct {
name string
selector string
selectableVars interface{}
want bool
}{
{
"catch-all",
"",
nil,
true,
},
{
"valid selector but no selectable vars",
"nomad_engineering_team in Groups",
"",
false,
},
{
"valid selector and successful evaluation",
"nomad_engineering_team in Groups",
map[string][]string{"Groups": {"nomad_sales_team", "nomad_engineering_team"}},
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
must.Eq(t, doesSelectorMatch(tt.selector, tt.selectableVars), tt.want)
})
}
}