Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions central/apitoken/creation/log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (

func Test_loggingMessage(t *testing.T) {
ap, err := authproviders.NewProvider(
t.Context(),
authproviders.WithID("1234-5678"),
authproviders.WithName("provider-name"),
authproviders.WithType("test-provider"),
Expand Down
1 change: 1 addition & 0 deletions central/auth/service/service_impl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ type authServiceAccessControlTestSuite struct {

func (s *authServiceAccessControlTestSuite) SetupSuite() {
authProvider, err := authproviders.NewProvider(
s.T().Context(),
authproviders.WithEnabled(true),
authproviders.WithID(uuid.NewDummy().String()),
authproviders.WithName("Test Auth Provider"),
Expand Down
2 changes: 1 addition & 1 deletion central/authprovider/service/service_impl_postgres_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (s *authProviderServiceTestSuite) SetupSuite() {
authProviderDS := authProviderDataStore.GetTestPostgresDataStore(t, db)
groupDS := groupDataStore.GetTestPostgresDataStore(t, db, roleDS, nil)
userDS := userDataStore.GetTestDataStore(t)
mapperFactory := roleMapper.NewStoreBasedMapperFactory(groupDS, roleDS, userDS)
mapperFactory := roleMapper.NewStoreBasedMapperFactory(groupDS, roleDS, userDS, authProviderDS)
providerRegistry := authproviders.NewStoreBackedRegistry(
urlPathPrefix,
redirectURL,
Expand Down
2 changes: 1 addition & 1 deletion central/authprovider/service/service_impl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (s *mockedAuthProviderServiceTestSuite) SetupTest() {
mockRoleMapper := permissionsMocks.NewMockRoleMapper(s.mockCtrl)

mapperFactory := permissionsMocks.NewMockRoleMapperFactory(s.mockCtrl)
mapperFactory.EXPECT().GetRoleMapper(gomock.Any()).AnyTimes().Return(mockRoleMapper)
mapperFactory.EXPECT().GetRoleMapper(gomock.Any(), gomock.Any()).AnyTimes().Return(mockRoleMapper)

registry := authproviders.NewStoreBackedRegistry(
urlPathPrefix,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ func (s *BaseImageRepositoryDatastoreTestSuite) TestUniqueRepositoryPathConstrai
func (s *BaseImageRepositoryDatastoreTestSuite) TestListRepositoriesAccessDenied() {
// Create a context with a user that has no image administration access.
authProvider, err := authproviders.NewProvider(
s.T().Context(),
authproviders.WithEnabled(true),
authproviders.WithID(uuid.NewDummy().String()),
authproviders.WithName("Test Auth Provider"),
Expand Down
2 changes: 1 addition & 1 deletion central/declarativeconfig/updater/role_updater_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (s *roleUpdaterTestSuite) SetupTest() {
tokenIssuerFactory := authTokenMocks.NewMockIssuerFactory(s.mockCtrl)
tokenIssuerFactory.EXPECT().CreateIssuer(gomock.Any(), gomock.Any()).AnyTimes().Return(nil, nil)
uds := userDS.GetTestDataStore(s.T())
mapperFactory := roleMapper.NewStoreBasedMapperFactory(s.gds, rds, uds)
mapperFactory := roleMapper.NewStoreBasedMapperFactory(s.gds, rds, uds, ads)
s.authProviderRegistry = authproviders.NewStoreBackedRegistry(
"/sso/",
"/auth/response/generic",
Expand Down
1 change: 1 addition & 0 deletions central/development/service/service_impl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func (s *developmentServiceAccessControlTestSuite) SetupSuite() {
}

authProvider, err := authproviders.NewProvider(
s.T().Context(),
authproviders.WithEnabled(true),
authproviders.WithID(uuid.NewDummy().String()),
authproviders.WithName("Test Auth Provider"),
Expand Down
1 change: 1 addition & 0 deletions central/group/datastore/datastore_impl_postgres_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ func (s *groupsWithPostgresTestSuite) validRoleAndAuthProvider(roleName, authPro
Name: roleName,
}
mockedAP, err := authproviders.NewProvider(
s.T().Context(),
authproviders.WithStorageView(&storage.AuthProvider{
Id: authProviderID,
Name: "auth-provider",
Expand Down
1 change: 1 addition & 0 deletions central/group/datastore/datastore_impl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,7 @@ func (s *groupDataStoreTestSuite) validRoleAndAuthProvider(roleName, authProvide
},
}
mockedAP, err := authproviders.NewProvider(
s.T().Context(),
authproviders.WithStorageView(&storage.AuthProvider{
Id: authProviderID,
Name: "auth-provider",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ func Test_forEachImageVuln(t *testing.T) {

func makeAdminContext(t *testing.T) context.Context {
authProvider, _ := authproviders.NewProvider(
t.Context(),
authproviders.WithEnabled(true),
authproviders.WithID(uuid.NewDummy().String()),
authproviders.WithName("Test Auth Provider"),
Expand Down
1 change: 1 addition & 0 deletions central/metrics/custom/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ func TestRunner_ServeHTTP(t *testing.T) {

func makeAdminContext(t *testing.T) context.Context {
authProvider, _ := authproviders.NewProvider(
t.Context(),
authproviders.WithEnabled(true),
authproviders.WithID(uuid.NewDummy().String()),
authproviders.WithName("Test Auth Provider"),
Expand Down
3 changes: 3 additions & 0 deletions central/metrics/custom/tracker/tracker_base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@ func TestTrackerBase_cleanup(t *testing.T) {

func makeAdminContext(t *testing.T) context.Context {
authProvider, _ := authproviders.NewProvider(
t.Context(),
authproviders.WithEnabled(true),
authproviders.WithID(uuid.NewDummy().String()),
authproviders.WithName("Test Auth Provider"),
Expand Down Expand Up @@ -650,6 +651,7 @@ func Test_scope(t *testing.T) {
})

provider, _ := authproviders.NewProvider(
t.Context(),
authproviders.WithEnabled(true),
authproviders.WithID(uuid.NewV4().String()),
authproviders.WithName("test"),
Expand Down Expand Up @@ -725,6 +727,7 @@ rox_central_test_Test_scope_scoped_access_metric2{Namespace="ns 3"} 1
})

provider, _ := authproviders.NewProvider(
t.Context(),
authproviders.WithEnabled(true),
authproviders.WithID(uuid.NewV4().String()),
authproviders.WithName("test"),
Expand Down
96 changes: 96 additions & 0 deletions central/role/mapper/acm_based_mapper_impl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package mapper

import (
"context"

"github.com/pkg/errors"
"github.com/stackrox/rox/pkg/auth/permissions"
"github.com/stackrox/rox/pkg/errox"
"github.com/stackrox/rox/pkg/sac/externalrolebroker"
"github.com/stackrox/rox/pkg/sac/externalrolebroker/acmclient"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/client-go/rest"
)

type acmBasedMapperImpl struct {
clientFactory func(ctx context.Context, token string) (externalrolebroker.ACMClient, error)
}

type user struct {
name string
identifier string
groups []string
}

func (u user) GetName() string {
return u.name
}

func (u user) GetUID() string {
return u.identifier
}

func (u user) GetGroups() []string {
return u.groups
}

func (u user) GetExtra() map[string][]string {
return nil
}

// FromUserDescriptor retrieves roles from ACM UserPermissions.
// It queries the ACM clusterview aggregate API to get user permissions,
// filters them for base Kubernetes resources, and converts them to ACS ResolvedRoles.
func (rm *acmBasedMapperImpl) FromUserDescriptor(ctx context.Context, ud *permissions.UserDescriptor) ([]permissions.ResolvedRole, error) {
if ud.Attributes == nil || len(ud.Attributes["name"]) <= 0 || len(ud.Attributes["userid"]) <= 0 {

Check failure on line 45 in central/role/mapper/acm_based_mapper_impl.go

View workflow job for this annotation

GitHub Actions / golangci-lint

sloppyLen: len(ud.Attributes["name"]) <= 0 can be len(ud.Attributes["name"]) == 0 (gocritic)
return nil, errox.InvalidArgs.CausedBy("user had no attribute from which to extract roles")
}
userForCtx := &user{
name: ud.Attributes["name"][0],
identifier: ud.Attributes["userid"][0],
groups: ud.Attributes["groups"],
}
tokens := ud.Attributes["providerToken"]
if len(tokens) == 0 || tokens[0] == "" {
return nil, nil
}
log.Info("ACM token ", tokens[0])
acmClient, err := rm.clientFactory(ctx, tokens[0])
if err != nil {
return nil, errors.Wrap(err, "failed to instantiate ACM client")
}
ctxForACM := request.WithUser(ctx, userForCtx)
log.Info("Querying ACM for user", userForCtx)
roles, err := externalrolebroker.GetResolvedRolesFromACM(ctxForACM, acmClient)
if err != nil {
return nil, errors.Wrap(err, "failed to get resolved roles from ACM")
}
log.Info(len(roles), " Resolved roles ", roles)
return roles, nil
}

func defaultACMClientFactory(ctx context.Context, token string) (externalrolebroker.ACMClient, error) {
cfg, err := rest.InClusterConfig()
if err != nil {
return nil, errors.Wrap(err, "failed to load k8s config")
}
cfg.BearerToken = token
return acmclient.NewACMClientFromConfig(cfg)
}

// NewACMBasedMapper creates a RoleMapper that retrieves roles from ACM UserPermissions.
// It creates an ACM client using in-cluster configuration and uses it to fetch
// user permissions from the ACM clusterview aggregate API.
func NewACMBasedMapper() (permissions.RoleMapper, error) {
return &acmBasedMapperImpl{
clientFactory: defaultACMClientFactory,
}, nil
}

// NewACMBasedMapperWithClient creates a RoleMapper with a custom ACM client.
// This is useful for testing or when you need to provide a custom client configuration.
func NewACMBasedMapperWithClient(clientFactory func(context.Context, string) (externalrolebroker.ACMClient, error)) permissions.RoleMapper {
return &acmBasedMapperImpl{
clientFactory: clientFactory,
}
}
Loading
Loading