//go:build !ent // +build !ent package nomad import ( "context" "errors" "testing" "github.com/hashicorp/nomad/ci" "github.com/hashicorp/nomad/command/agent/consul" "github.com/hashicorp/nomad/helper/testlog" "github.com/hashicorp/nomad/nomad/structs" "github.com/stretchr/testify/require" ) func TestConsulACLsAPI_CheckPermissions_oss(t *testing.T) { ci.Parallel(t) // In Nomad OSS, CheckPermissions will only receive "" as input for the // namespace parameter - as the ConsulUsage map from namespace to usages will // always contain one key - the empty string. try := func(t *testing.T, namespace string, usage *structs.ConsulUsage, secretID string, exp error) { logger := testlog.HCLogger(t) aclAPI := consul.NewMockACLsAPI(logger) cAPI := NewConsulACLsAPI(aclAPI, logger, nil) err := cAPI.CheckPermissions(context.Background(), namespace, usage, secretID) if exp == nil { require.NoError(t, err) } else { require.Equal(t, exp.Error(), err.Error()) } } t.Run("check-permissions kv read", func(t *testing.T) { t.Run("uses kv has permission", func(t *testing.T) { u := &structs.ConsulUsage{KV: true} try(t, "", u, consul.ExampleOperatorTokenID5, nil) }) t.Run("uses kv without permission", func(t *testing.T) { u := &structs.ConsulUsage{KV: true} try(t, "", u, consul.ExampleOperatorTokenID1, errors.New("insufficient Consul ACL permissions to use template")) }) t.Run("uses kv no token", func(t *testing.T) { u := &structs.ConsulUsage{KV: true} try(t, "", u, "", errors.New("missing consul token")) }) t.Run("uses kv nonsense token", func(t *testing.T) { u := &structs.ConsulUsage{KV: true} try(t, "", u, "47d33e22-720a-7fe6-7d7f-418bf844a0be", errors.New("unable to read consul token: no such token")) }) t.Run("no kv no token", func(t *testing.T) { u := &structs.ConsulUsage{KV: false} try(t, "", u, "", nil) }) }) t.Run("check-permissions service write", func(t *testing.T) { usage := &structs.ConsulUsage{Services: []string{"service1"}} t.Run("operator has service write", func(t *testing.T) { try(t, "", usage, consul.ExampleOperatorTokenID1, nil) }) t.Run("operator has service_prefix write", func(t *testing.T) { u := &structs.ConsulUsage{Services: []string{"foo-service1"}} try(t, "", u, consul.ExampleOperatorTokenID2, nil) }) t.Run("operator has service_prefix write wrong prefix", func(t *testing.T) { u := &structs.ConsulUsage{Services: []string{"bar-service1"}} try(t, "", u, consul.ExampleOperatorTokenID2, errors.New(`insufficient Consul ACL permissions to write service "bar-service1"`)) }) t.Run("operator permissions insufficient", func(t *testing.T) { try(t, "", usage, consul.ExampleOperatorTokenID3, errors.New(`insufficient Consul ACL permissions to write service "service1"`)) }) t.Run("operator provided no token", func(t *testing.T) { try(t, "", usage, "", errors.New("missing consul token")) }) t.Run("operator provided nonsense token", func(t *testing.T) { try(t, "", usage, "f1682bde-1e71-90b1-9204-85d35467ba61", errors.New("unable to read consul token: no such token")) }) }) t.Run("check-permissions connect service identity write", func(t *testing.T) { usage := &structs.ConsulUsage{Kinds: []structs.TaskKind{structs.NewTaskKind(structs.ConnectProxyPrefix, "service1")}} t.Run("operator has service write", func(t *testing.T) { try(t, "", usage, consul.ExampleOperatorTokenID1, nil) }) t.Run("operator has service_prefix write", func(t *testing.T) { u := &structs.ConsulUsage{Kinds: []structs.TaskKind{structs.NewTaskKind(structs.ConnectProxyPrefix, "foo-service1")}} try(t, "", u, consul.ExampleOperatorTokenID2, nil) }) t.Run("operator has service_prefix write wrong prefix", func(t *testing.T) { u := &structs.ConsulUsage{Kinds: []structs.TaskKind{structs.NewTaskKind(structs.ConnectProxyPrefix, "bar-service1")}} try(t, "", u, consul.ExampleOperatorTokenID2, errors.New(`insufficient Consul ACL permissions to write Connect service "bar-service1"`)) }) t.Run("operator permissions insufficient", func(t *testing.T) { try(t, "", usage, consul.ExampleOperatorTokenID3, errors.New(`insufficient Consul ACL permissions to write Connect service "service1"`)) }) t.Run("operator provided no token", func(t *testing.T) { try(t, "", usage, "", errors.New("missing consul token")) }) t.Run("operator provided nonsense token", func(t *testing.T) { try(t, "", usage, "f1682bde-1e71-90b1-9204-85d35467ba61", errors.New("unable to read consul token: no such token")) }) }) }