mirror of
https://github.com/gravitational/teleport
synced 2024-10-20 17:23:22 +00:00
DiscoveryConfig: add service with rbac support (#32371)
* DiscoveryConfig: add service with rbac support This PR adds the DiscoveryConfig service protected by RBAC rules. A PR will follow that uses this service to expose the service in the gRPC server. * review pt1
This commit is contained in:
parent
84dbc45e1d
commit
9a428beac6
199
lib/auth/discoveryconfig/discoveryconfigv1/service.go
Normal file
199
lib/auth/discoveryconfig/discoveryconfigv1/service.go
Normal file
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
Copyright 2023 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package discoveryconfigv1
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/jonboulle/clockwork"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
|
||||
discoveryconfigv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/discoveryconfig/v1"
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
conv "github.com/gravitational/teleport/api/types/discoveryconfig/convert/v1"
|
||||
"github.com/gravitational/teleport/lib/authz"
|
||||
"github.com/gravitational/teleport/lib/services"
|
||||
)
|
||||
|
||||
// ServiceConfig holds configuration options for the DiscoveryConfig gRPC service.
|
||||
type ServiceConfig struct {
|
||||
// Logger is the logger to use.
|
||||
Logger logrus.FieldLogger
|
||||
|
||||
// Authorizer is the authorizer to use.
|
||||
Authorizer authz.Authorizer
|
||||
|
||||
// Backend is the backend for storing DiscoveryConfigs.
|
||||
Backend services.DiscoveryConfigs
|
||||
|
||||
// Clock is the clock.
|
||||
Clock clockwork.Clock
|
||||
}
|
||||
|
||||
// CheckAndSetDefaults checks the ServiceConfig fields and returns an error if
|
||||
// a required param is not provided.
|
||||
// Authorizer, Cache and Backend are required params
|
||||
func (s *ServiceConfig) CheckAndSetDefaults() error {
|
||||
if s.Authorizer == nil {
|
||||
return trace.BadParameter("authorizer is required")
|
||||
}
|
||||
if s.Backend == nil {
|
||||
return trace.BadParameter("backend is required")
|
||||
}
|
||||
|
||||
if s.Logger == nil {
|
||||
s.Logger = logrus.New().WithField(trace.Component, "discoveryconfig_crud_service")
|
||||
}
|
||||
|
||||
if s.Clock == nil {
|
||||
s.Clock = clockwork.NewRealClock()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Service implements the teleport.DiscoveryConfig.v1.DiscoveryConfigService RPC service.
|
||||
type Service struct {
|
||||
discoveryconfigv1.UnimplementedDiscoveryConfigServiceServer
|
||||
|
||||
log logrus.FieldLogger
|
||||
authorizer authz.Authorizer
|
||||
backend services.DiscoveryConfigs
|
||||
clock clockwork.Clock
|
||||
}
|
||||
|
||||
// NewService returns a new DiscoveryConfigs gRPC service.
|
||||
func NewService(cfg ServiceConfig) (*Service, error) {
|
||||
if err := cfg.CheckAndSetDefaults(); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
return &Service{
|
||||
log: cfg.Logger,
|
||||
authorizer: cfg.Authorizer,
|
||||
backend: cfg.Backend,
|
||||
clock: cfg.Clock,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListDiscoveryConfigs returns a paginated list of all DiscoveryConfig resources.
|
||||
func (s *Service) ListDiscoveryConfigs(ctx context.Context, req *discoveryconfigv1.ListDiscoveryConfigsRequest) (*discoveryconfigv1.ListDiscoveryConfigsResponse, error) {
|
||||
_, err := authz.AuthorizeWithVerbs(ctx, s.log, s.authorizer, true, types.KindDiscoveryConfig, types.VerbRead, types.VerbList)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
results, nextKey, err := s.backend.ListDiscoveryConfigs(ctx, int(req.GetPageSize()), req.GetNextToken())
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
dcs := make([]*discoveryconfigv1.DiscoveryConfig, len(results))
|
||||
for i, r := range results {
|
||||
dcs[i] = conv.ToProto(r)
|
||||
}
|
||||
|
||||
return &discoveryconfigv1.ListDiscoveryConfigsResponse{
|
||||
DiscoveryConfigs: dcs,
|
||||
NextKey: nextKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetDiscoveryConfig returns the specified DiscoveryConfig resource.
|
||||
func (s *Service) GetDiscoveryConfig(ctx context.Context, req *discoveryconfigv1.GetDiscoveryConfigRequest) (*discoveryconfigv1.DiscoveryConfig, error) {
|
||||
_, err := authz.AuthorizeWithVerbs(ctx, s.log, s.authorizer, true, types.KindDiscoveryConfig, types.VerbRead)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
dc, err := s.backend.GetDiscoveryConfig(ctx, req.Name)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
return conv.ToProto(dc), nil
|
||||
}
|
||||
|
||||
// CreateDiscoveryConfig creates a new DiscoveryConfig resource.
|
||||
func (s *Service) CreateDiscoveryConfig(ctx context.Context, req *discoveryconfigv1.CreateDiscoveryConfigRequest) (*discoveryconfigv1.DiscoveryConfig, error) {
|
||||
_, err := authz.AuthorizeWithVerbs(ctx, s.log, s.authorizer, true, types.KindDiscoveryConfig, types.VerbCreate)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
dc, err := conv.FromProto(req.GetDiscoveryConfig())
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
resp, err := s.backend.CreateDiscoveryConfig(ctx, dc)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
return conv.ToProto(resp), nil
|
||||
}
|
||||
|
||||
// UpdateDiscoveryConfig updates an existing DiscoveryConfig.
|
||||
func (s *Service) UpdateDiscoveryConfig(ctx context.Context, req *discoveryconfigv1.UpdateDiscoveryConfigRequest) (*discoveryconfigv1.DiscoveryConfig, error) {
|
||||
_, err := authz.AuthorizeWithVerbs(ctx, s.log, s.authorizer, true, types.KindDiscoveryConfig, types.VerbUpdate)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
dc, err := conv.FromProto(req.GetDiscoveryConfig())
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
resp, err := s.backend.UpdateDiscoveryConfig(ctx, dc)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
return conv.ToProto(resp), nil
|
||||
}
|
||||
|
||||
// DeleteDiscoveryConfig removes the specified DiscoveryConfig resource.
|
||||
func (s *Service) DeleteDiscoveryConfig(ctx context.Context, req *discoveryconfigv1.DeleteDiscoveryConfigRequest) (*emptypb.Empty, error) {
|
||||
_, err := authz.AuthorizeWithVerbs(ctx, s.log, s.authorizer, true, types.KindDiscoveryConfig, types.VerbDelete)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
if err := s.backend.DeleteDiscoveryConfig(ctx, req.GetName()); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
// DeleteAllDiscoveryConfigs removes all DiscoveryConfig resources.
|
||||
func (s *Service) DeleteAllDiscoveryConfigs(ctx context.Context, _ *discoveryconfigv1.DeleteAllDiscoveryConfigsRequest) (*emptypb.Empty, error) {
|
||||
_, err := authz.AuthorizeWithVerbs(ctx, s.log, s.authorizer, true, types.KindDiscoveryConfig, types.VerbDelete)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
if err := s.backend.DeleteAllDiscoveryConfigs(ctx); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
398
lib/auth/discoveryconfig/discoveryconfigv1/service_test.go
Normal file
398
lib/auth/discoveryconfig/discoveryconfigv1/service_test.go
Normal file
|
@ -0,0 +1,398 @@
|
|||
/*
|
||||
Copyright 2023 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package discoveryconfigv1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
discoveryconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/discoveryconfig/v1"
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
"github.com/gravitational/teleport/api/types/discoveryconfig"
|
||||
convert "github.com/gravitational/teleport/api/types/discoveryconfig/convert/v1"
|
||||
"github.com/gravitational/teleport/api/types/header"
|
||||
"github.com/gravitational/teleport/lib/authz"
|
||||
"github.com/gravitational/teleport/lib/backend/memory"
|
||||
"github.com/gravitational/teleport/lib/services"
|
||||
"github.com/gravitational/teleport/lib/services/local"
|
||||
"github.com/gravitational/teleport/lib/tlsca"
|
||||
)
|
||||
|
||||
func TestDiscoveryConfigCRUD(t *testing.T) {
|
||||
t.Parallel()
|
||||
clusterName := "test-cluster"
|
||||
|
||||
requireTraceErrorFn := func(traceFn func(error) bool) require.ErrorAssertionFunc {
|
||||
return func(tt require.TestingT, err error, i ...interface{}) {
|
||||
require.True(t, traceFn(err), "received an un-expected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
ctx, localClient, resourceSvc := initSvc(t, clusterName)
|
||||
|
||||
sampleDiscoveryConfigFn := func(t *testing.T, name string) *discoveryconfig.DiscoveryConfig {
|
||||
dc, err := discoveryconfig.NewDiscoveryConfig(
|
||||
header.Metadata{Name: name},
|
||||
discoveryconfig.Spec{
|
||||
DiscoveryGroup: "some-group",
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
return dc
|
||||
}
|
||||
|
||||
tt := []struct {
|
||||
Name string
|
||||
Role types.RoleSpecV6
|
||||
Setup func(t *testing.T, dcName string)
|
||||
Test func(ctx context.Context, resourceSvc *Service, dcName string) error
|
||||
ErrAssertion require.ErrorAssertionFunc
|
||||
}{
|
||||
// Read
|
||||
{
|
||||
Name: "allowed read access to discovery configs",
|
||||
Role: types.RoleSpecV6{
|
||||
Allow: types.RoleConditions{Rules: []types.Rule{{
|
||||
Resources: []string{types.KindDiscoveryConfig},
|
||||
Verbs: []string{types.VerbRead},
|
||||
}}},
|
||||
},
|
||||
Setup: func(t *testing.T, dcName string) {
|
||||
_, err := localClient.CreateDiscoveryConfig(ctx, sampleDiscoveryConfigFn(t, dcName))
|
||||
require.NoError(t, err)
|
||||
},
|
||||
Test: func(ctx context.Context, resourceSvc *Service, dcName string) error {
|
||||
_, err := resourceSvc.GetDiscoveryConfig(ctx, &discoveryconfigpb.GetDiscoveryConfigRequest{
|
||||
Name: dcName,
|
||||
})
|
||||
return err
|
||||
},
|
||||
ErrAssertion: require.NoError,
|
||||
},
|
||||
{
|
||||
Name: "no access to read discovery configs",
|
||||
Role: types.RoleSpecV6{},
|
||||
Test: func(ctx context.Context, resourceSvc *Service, dcName string) error {
|
||||
_, err := resourceSvc.GetDiscoveryConfig(ctx, &discoveryconfigpb.GetDiscoveryConfigRequest{
|
||||
Name: dcName,
|
||||
})
|
||||
return err
|
||||
},
|
||||
ErrAssertion: requireTraceErrorFn(trace.IsAccessDenied),
|
||||
},
|
||||
{
|
||||
Name: "denied access to read discovery configs",
|
||||
Role: types.RoleSpecV6{
|
||||
Deny: types.RoleConditions{Rules: []types.Rule{{
|
||||
Resources: []string{types.KindDiscoveryConfig},
|
||||
Verbs: []string{types.VerbRead},
|
||||
}}},
|
||||
},
|
||||
Test: func(ctx context.Context, resourceSvc *Service, dcName string) error {
|
||||
_, err := resourceSvc.GetDiscoveryConfig(ctx, &discoveryconfigpb.GetDiscoveryConfigRequest{
|
||||
Name: dcName,
|
||||
})
|
||||
return err
|
||||
},
|
||||
ErrAssertion: requireTraceErrorFn(trace.IsAccessDenied),
|
||||
},
|
||||
|
||||
// List
|
||||
{
|
||||
Name: "allowed list access to discovery configs",
|
||||
Role: types.RoleSpecV6{
|
||||
Allow: types.RoleConditions{Rules: []types.Rule{{
|
||||
Resources: []string{types.KindDiscoveryConfig},
|
||||
Verbs: []string{types.VerbList, types.VerbRead},
|
||||
}}},
|
||||
},
|
||||
Setup: func(t *testing.T, _ string) {
|
||||
for i := 0; i < 10; i++ {
|
||||
_, err := localClient.CreateDiscoveryConfig(ctx, sampleDiscoveryConfigFn(t, uuid.NewString()))
|
||||
require.NoError(t, err)
|
||||
}
|
||||
},
|
||||
Test: func(ctx context.Context, resourceSvc *Service, dcName string) error {
|
||||
_, err := resourceSvc.ListDiscoveryConfigs(ctx, &discoveryconfigpb.ListDiscoveryConfigsRequest{
|
||||
PageSize: 0,
|
||||
NextToken: "",
|
||||
})
|
||||
return err
|
||||
},
|
||||
ErrAssertion: require.NoError,
|
||||
},
|
||||
{
|
||||
Name: "no list access to discovery config",
|
||||
Role: types.RoleSpecV6{
|
||||
Allow: types.RoleConditions{Rules: []types.Rule{{
|
||||
Resources: []string{types.KindDiscoveryConfig},
|
||||
Verbs: []string{types.VerbCreate},
|
||||
}}},
|
||||
},
|
||||
Test: func(ctx context.Context, resourceSvc *Service, dcName string) error {
|
||||
_, err := resourceSvc.ListDiscoveryConfigs(ctx, &discoveryconfigpb.ListDiscoveryConfigsRequest{
|
||||
PageSize: 0,
|
||||
NextToken: "",
|
||||
})
|
||||
return err
|
||||
},
|
||||
ErrAssertion: requireTraceErrorFn(trace.IsAccessDenied),
|
||||
},
|
||||
|
||||
// Create
|
||||
{
|
||||
Name: "no access to create discovery configs",
|
||||
Role: types.RoleSpecV6{},
|
||||
Test: func(ctx context.Context, resourceSvc *Service, dcName string) error {
|
||||
dc := sampleDiscoveryConfigFn(t, dcName)
|
||||
_, err := resourceSvc.CreateDiscoveryConfig(ctx, &discoveryconfigpb.CreateDiscoveryConfigRequest{
|
||||
DiscoveryConfig: convert.ToProto(dc),
|
||||
})
|
||||
return err
|
||||
},
|
||||
ErrAssertion: requireTraceErrorFn(trace.IsAccessDenied),
|
||||
},
|
||||
{
|
||||
Name: "access to create discovery configs",
|
||||
Role: types.RoleSpecV6{
|
||||
Allow: types.RoleConditions{Rules: []types.Rule{{
|
||||
Resources: []string{types.KindDiscoveryConfig},
|
||||
Verbs: []string{types.VerbCreate},
|
||||
}}},
|
||||
},
|
||||
Test: func(ctx context.Context, resourceSvc *Service, dcName string) error {
|
||||
dc := sampleDiscoveryConfigFn(t, dcName)
|
||||
_, err := resourceSvc.CreateDiscoveryConfig(ctx, &discoveryconfigpb.CreateDiscoveryConfigRequest{
|
||||
DiscoveryConfig: convert.ToProto(dc),
|
||||
})
|
||||
return err
|
||||
},
|
||||
ErrAssertion: require.NoError,
|
||||
},
|
||||
|
||||
// Update
|
||||
{
|
||||
Name: "no access to update discovery config",
|
||||
Role: types.RoleSpecV6{},
|
||||
Test: func(ctx context.Context, resourceSvc *Service, dcName string) error {
|
||||
dc := sampleDiscoveryConfigFn(t, dcName)
|
||||
_, err := resourceSvc.UpdateDiscoveryConfig(ctx, &discoveryconfigpb.UpdateDiscoveryConfigRequest{
|
||||
DiscoveryConfig: convert.ToProto(dc),
|
||||
})
|
||||
return err
|
||||
},
|
||||
ErrAssertion: requireTraceErrorFn(trace.IsAccessDenied),
|
||||
},
|
||||
{
|
||||
Name: "access to update discovery config",
|
||||
Role: types.RoleSpecV6{
|
||||
Allow: types.RoleConditions{Rules: []types.Rule{{
|
||||
Resources: []string{types.KindDiscoveryConfig},
|
||||
Verbs: []string{types.VerbUpdate},
|
||||
}}},
|
||||
},
|
||||
Setup: func(t *testing.T, dcName string) {
|
||||
_, err := localClient.CreateDiscoveryConfig(ctx, sampleDiscoveryConfigFn(t, dcName))
|
||||
require.NoError(t, err)
|
||||
},
|
||||
Test: func(ctx context.Context, resourceSvc *Service, dcName string) error {
|
||||
dc := sampleDiscoveryConfigFn(t, dcName)
|
||||
_, err := resourceSvc.UpdateDiscoveryConfig(ctx, &discoveryconfigpb.UpdateDiscoveryConfigRequest{
|
||||
DiscoveryConfig: convert.ToProto(dc),
|
||||
})
|
||||
return err
|
||||
},
|
||||
ErrAssertion: require.NoError,
|
||||
},
|
||||
|
||||
// Delete
|
||||
{
|
||||
Name: "no access to delete discovery config",
|
||||
Role: types.RoleSpecV6{},
|
||||
Test: func(ctx context.Context, resourceSvc *Service, dcName string) error {
|
||||
_, err := resourceSvc.DeleteDiscoveryConfig(ctx, &discoveryconfigpb.DeleteDiscoveryConfigRequest{Name: "x"})
|
||||
return err
|
||||
},
|
||||
ErrAssertion: requireTraceErrorFn(trace.IsAccessDenied),
|
||||
},
|
||||
{
|
||||
Name: "access to delete discovery config",
|
||||
Role: types.RoleSpecV6{
|
||||
Allow: types.RoleConditions{Rules: []types.Rule{{
|
||||
Resources: []string{types.KindDiscoveryConfig},
|
||||
Verbs: []string{types.VerbDelete},
|
||||
}}},
|
||||
},
|
||||
Setup: func(t *testing.T, dcName string) {
|
||||
_, err := localClient.CreateDiscoveryConfig(ctx, sampleDiscoveryConfigFn(t, dcName))
|
||||
require.NoError(t, err)
|
||||
},
|
||||
Test: func(ctx context.Context, resourceSvc *Service, dcName string) error {
|
||||
_, err := resourceSvc.DeleteDiscoveryConfig(ctx, &discoveryconfigpb.DeleteDiscoveryConfigRequest{Name: dcName})
|
||||
return err
|
||||
},
|
||||
ErrAssertion: require.NoError,
|
||||
},
|
||||
|
||||
// Delete all
|
||||
{
|
||||
Name: "remove all discovery configs fails when no access",
|
||||
Role: types.RoleSpecV6{},
|
||||
Test: func(ctx context.Context, resourceSvc *Service, dcName string) error {
|
||||
_, err := resourceSvc.DeleteAllDiscoveryConfigs(ctx, &discoveryconfigpb.DeleteAllDiscoveryConfigsRequest{})
|
||||
return err
|
||||
},
|
||||
ErrAssertion: requireTraceErrorFn(trace.IsAccessDenied),
|
||||
},
|
||||
{
|
||||
Name: "remove all discovery configs",
|
||||
Role: types.RoleSpecV6{
|
||||
Allow: types.RoleConditions{Rules: []types.Rule{{
|
||||
Resources: []string{types.KindDiscoveryConfig},
|
||||
Verbs: []string{types.VerbDelete},
|
||||
}}},
|
||||
},
|
||||
Setup: func(t *testing.T, _ string) {
|
||||
for i := 0; i < 10; i++ {
|
||||
_, err := localClient.CreateDiscoveryConfig(ctx, sampleDiscoveryConfigFn(t, uuid.NewString()))
|
||||
require.NoError(t, err)
|
||||
}
|
||||
},
|
||||
Test: func(ctx context.Context, resourceSvc *Service, dcName string) error {
|
||||
_, err := resourceSvc.DeleteAllDiscoveryConfigs(ctx, &discoveryconfigpb.DeleteAllDiscoveryConfigsRequest{})
|
||||
return err
|
||||
},
|
||||
ErrAssertion: require.NoError,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
tc := tc
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
localCtx := authorizerForDummyUser(t, ctx, tc.Role, localClient)
|
||||
|
||||
dcName := uuid.NewString()
|
||||
if tc.Setup != nil {
|
||||
tc.Setup(t, dcName)
|
||||
}
|
||||
|
||||
err := tc.Test(localCtx, resourceSvc, dcName)
|
||||
tc.ErrAssertion(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func authorizerForDummyUser(t *testing.T, ctx context.Context, roleSpec types.RoleSpecV6, localClient localClient) context.Context {
|
||||
// Create role
|
||||
roleName := "role-" + uuid.NewString()
|
||||
role, err := types.NewRole(roleName, roleSpec)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = localClient.CreateRole(ctx, role)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create user
|
||||
user, err := types.NewUser("user-" + uuid.NewString())
|
||||
require.NoError(t, err)
|
||||
user.AddRole(roleName)
|
||||
err = localClient.CreateUser(user)
|
||||
require.NoError(t, err)
|
||||
|
||||
return authz.ContextWithUser(ctx, authz.LocalUser{
|
||||
Username: user.GetName(),
|
||||
Identity: tlsca.Identity{
|
||||
Username: user.GetName(),
|
||||
Groups: []string{role.GetName()},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
type localClient interface {
|
||||
CreateUser(user types.User) error
|
||||
CreateRole(ctx context.Context, role types.Role) error
|
||||
CreateDiscoveryConfig(ctx context.Context, dc *discoveryconfig.DiscoveryConfig) (*discoveryconfig.DiscoveryConfig, error)
|
||||
}
|
||||
|
||||
func initSvc(t *testing.T, clusterName string) (context.Context, localClient, *Service) {
|
||||
ctx := context.Background()
|
||||
backend, err := memory.New(memory.Config{})
|
||||
require.NoError(t, err)
|
||||
|
||||
trustSvc := local.NewCAService(backend)
|
||||
roleSvc := local.NewAccessService(backend)
|
||||
userSvc := local.NewIdentityService(backend)
|
||||
|
||||
clusterConfigSvc, err := local.NewClusterConfigurationService(backend)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, clusterConfigSvc.SetAuthPreference(ctx, types.DefaultAuthPreference()))
|
||||
require.NoError(t, clusterConfigSvc.SetClusterAuditConfig(ctx, types.DefaultClusterAuditConfig()))
|
||||
require.NoError(t, clusterConfigSvc.SetClusterNetworkingConfig(ctx, types.DefaultClusterNetworkingConfig()))
|
||||
require.NoError(t, clusterConfigSvc.SetSessionRecordingConfig(ctx, types.DefaultSessionRecordingConfig()))
|
||||
|
||||
accessPoint := struct {
|
||||
services.ClusterConfiguration
|
||||
services.Trust
|
||||
services.RoleGetter
|
||||
services.UserGetter
|
||||
}{
|
||||
ClusterConfiguration: clusterConfigSvc,
|
||||
Trust: trustSvc,
|
||||
RoleGetter: roleSvc,
|
||||
UserGetter: userSvc,
|
||||
}
|
||||
|
||||
accessService := local.NewAccessService(backend)
|
||||
eventService := local.NewEventsService(backend)
|
||||
lockWatcher, err := services.NewLockWatcher(ctx, services.LockWatcherConfig{
|
||||
ResourceWatcherConfig: services.ResourceWatcherConfig{
|
||||
Client: eventService,
|
||||
Component: "test",
|
||||
},
|
||||
LockGetter: accessService,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
authorizer, err := authz.NewAuthorizer(authz.AuthorizerOpts{
|
||||
ClusterName: clusterName,
|
||||
AccessPoint: accessPoint,
|
||||
LockWatcher: lockWatcher,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
localResourceService, err := local.NewDiscoveryConfigService(backend)
|
||||
require.NoError(t, err)
|
||||
|
||||
resourceSvc, err := NewService(ServiceConfig{
|
||||
Backend: localResourceService,
|
||||
Authorizer: authorizer,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
return ctx, struct {
|
||||
*local.AccessService
|
||||
*local.IdentityService
|
||||
*local.DiscoveryConfigService
|
||||
}{
|
||||
AccessService: roleSvc,
|
||||
IdentityService: userSvc,
|
||||
DiscoveryConfigService: localResourceService,
|
||||
}, resourceSvc
|
||||
}
|
Loading…
Reference in a new issue