mirror of
https://github.com/SigNoz/signoz.git
synced 2026-06-25 17:40:32 +01:00
Compare commits
3 Commits
feat/trace
...
platform-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18f4c035bc | ||
|
|
237c568582 | ||
|
|
e6372dab62 |
@@ -370,7 +370,7 @@ func (provider *provider) Delete(ctx context.Context, orgID valuer.UUID, id valu
|
||||
}
|
||||
|
||||
for _, cb := range provider.onBeforeRoleDelete {
|
||||
if err := cb(ctx, orgID, id); err != nil {
|
||||
if err := cb(ctx, orgID, id, role.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ type AuthZ interface {
|
||||
}
|
||||
|
||||
// OnBeforeRoleDelete is a callback invoked before a role is deleted.
|
||||
type OnBeforeRoleDelete func(context.Context, valuer.UUID, valuer.UUID) error
|
||||
type OnBeforeRoleDelete func(ctx context.Context, orgID valuer.UUID, roleID valuer.UUID, roleName string) error
|
||||
|
||||
type Handler interface {
|
||||
Create(http.ResponseWriter, *http.Request)
|
||||
|
||||
@@ -44,3 +44,7 @@ type Handler interface {
|
||||
Update(http.ResponseWriter, *http.Request)
|
||||
Delete(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
type Getter interface {
|
||||
OnBeforeRoleDelete(ctx context.Context, orgID valuer.UUID, roleID valuer.UUID, roleName string) error
|
||||
}
|
||||
|
||||
45
pkg/modules/authdomain/implauthdomain/getter.go
Normal file
45
pkg/modules/authdomain/implauthdomain/getter.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package implauthdomain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/modules/authdomain"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type getter struct {
|
||||
store authtypes.AuthDomainStore
|
||||
}
|
||||
|
||||
func NewGetter(store authtypes.AuthDomainStore) authdomain.Getter {
|
||||
return &getter{store: store}
|
||||
}
|
||||
|
||||
func (getter *getter) OnBeforeRoleDelete(ctx context.Context, orgID valuer.UUID, roleID valuer.UUID, roleName string) error {
|
||||
domains, err := getter.store.ListByOrgID(ctx, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
referencedBy := make([]string, 0)
|
||||
for _, domain := range domains {
|
||||
for _, mappedRole := range domain.AuthDomainConfig().RoleMapping.RoleNames() {
|
||||
if mappedRole == roleName {
|
||||
referencedBy = append(referencedBy, domain.StorableAuthDomain().Name)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(referencedBy) > 0 {
|
||||
return errors.WithAdditionalf(
|
||||
errors.New(errors.TypeInvalidInput, authtypes.ErrCodeRoleHasAuthDomainMappings, "role is referenced by an SSO role mapping, remove it before deleting"),
|
||||
"referenced by auth domain(s): %s", strings.Join(referencedBy, ", "),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/authn"
|
||||
"github.com/SigNoz/signoz/pkg/authz"
|
||||
"github.com/SigNoz/signoz/pkg/modules/authdomain"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
@@ -12,13 +13,18 @@ import (
|
||||
type module struct {
|
||||
store authtypes.AuthDomainStore
|
||||
authNs map[authtypes.AuthNProvider]authn.AuthN
|
||||
authz authz.AuthZ
|
||||
}
|
||||
|
||||
func NewModule(store authtypes.AuthDomainStore, authNs map[authtypes.AuthNProvider]authn.AuthN) authdomain.Module {
|
||||
return &module{store: store, authNs: authNs}
|
||||
func NewModule(store authtypes.AuthDomainStore, authNs map[authtypes.AuthNProvider]authn.AuthN, authz authz.AuthZ) authdomain.Module {
|
||||
return &module{store: store, authNs: authNs, authz: authz}
|
||||
}
|
||||
|
||||
func (module *module) Create(ctx context.Context, domain *authtypes.AuthDomain) error {
|
||||
if err := module.validateRoleMapping(ctx, domain); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return module.store.Create(ctx, domain)
|
||||
}
|
||||
|
||||
@@ -50,6 +56,10 @@ func (module *module) ListByOrgID(ctx context.Context, orgID valuer.UUID) ([]*au
|
||||
}
|
||||
|
||||
func (module *module) Update(ctx context.Context, domain *authtypes.AuthDomain) error {
|
||||
if err := module.validateRoleMapping(ctx, domain); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return module.store.Update(ctx, domain)
|
||||
}
|
||||
|
||||
@@ -74,3 +84,13 @@ func (module *module) Collect(ctx context.Context, orgID valuer.UUID) (map[strin
|
||||
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
func (module *module) validateRoleMapping(ctx context.Context, domain *authtypes.AuthDomain) error {
|
||||
roleNames := domain.AuthDomainConfig().RoleMapping.RoleNames()
|
||||
if len(roleNames) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := module.authz.ListByOrgIDAndNames(ctx, domain.StorableAuthDomain().OrgID, roleNames)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ func NewGetter(store serviceaccounttypes.Store) serviceaccount.Getter {
|
||||
return &getter{store: store}
|
||||
}
|
||||
|
||||
func (getter *getter) OnBeforeRoleDelete(ctx context.Context, orgID valuer.UUID, roleID valuer.UUID) error {
|
||||
func (getter *getter) OnBeforeRoleDelete(ctx context.Context, orgID valuer.UUID, roleID valuer.UUID, _ string) error {
|
||||
serviceAccounts, err := getter.store.GetServiceAccountsByOrgIDAndRoleID(ctx, orgID, roleID)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
type Getter interface {
|
||||
// OnBeforeRoleDelete checks if any service accounts are assigned to the role and rejects deletion if so.
|
||||
OnBeforeRoleDelete(ctx context.Context, orgID valuer.UUID, roleID valuer.UUID) error
|
||||
OnBeforeRoleDelete(ctx context.Context, orgID valuer.UUID, roleID valuer.UUID, roleName string) error
|
||||
}
|
||||
|
||||
type Module interface {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/authn"
|
||||
"github.com/SigNoz/signoz/pkg/authz"
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/modules/authdomain"
|
||||
@@ -29,9 +30,10 @@ type module struct {
|
||||
authDomain authdomain.Module
|
||||
tokenizer tokenizer.Tokenizer
|
||||
orgGetter organization.Getter
|
||||
authz authz.AuthZ
|
||||
}
|
||||
|
||||
func NewModule(providerSettings factory.ProviderSettings, authNs map[authtypes.AuthNProvider]authn.AuthN, userSetter user.Setter, userGetter user.Getter, authDomain authdomain.Module, tokenizer tokenizer.Tokenizer, orgGetter organization.Getter) session.Module {
|
||||
func NewModule(providerSettings factory.ProviderSettings, authNs map[authtypes.AuthNProvider]authn.AuthN, userSetter user.Setter, userGetter user.Getter, authDomain authdomain.Module, tokenizer tokenizer.Tokenizer, orgGetter organization.Getter, authz authz.AuthZ) session.Module {
|
||||
return &module{
|
||||
settings: factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/modules/session/implsession"),
|
||||
authNs: authNs,
|
||||
@@ -40,6 +42,7 @@ func NewModule(providerSettings factory.ProviderSettings, authNs map[authtypes.A
|
||||
authDomain: authDomain,
|
||||
tokenizer: tokenizer,
|
||||
orgGetter: orgGetter,
|
||||
authz: authz,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,15 +146,23 @@ func (module *module) CreateCallbackAuthNSession(ctx context.Context, authNProvi
|
||||
}
|
||||
|
||||
roleMapping := authDomain.AuthDomainConfig().RoleMapping
|
||||
role := roleMapping.NewRoleFromCallbackIdentity(callbackIdentity)
|
||||
signozManagedRole := authtypes.MustGetSigNozManagedRoleFromExistingRole(role)
|
||||
|
||||
roleAttributeExists := false
|
||||
if roleMapping != nil && roleMapping.UseRoleAttribute && callbackIdentity.Role != "" {
|
||||
_, err := module.authz.GetByOrgIDAndName(ctx, callbackIdentity.OrgID, authtypes.NormalizeRoleName(callbackIdentity.Role))
|
||||
if err == nil {
|
||||
roleAttributeExists = true
|
||||
}
|
||||
}
|
||||
|
||||
roleNames := roleMapping.NewRolesFromCallbackIdentity(callbackIdentity, roleAttributeExists)
|
||||
|
||||
newUser, err := types.NewUser(callbackIdentity.Name, callbackIdentity.Email, callbackIdentity.OrgID, types.UserStatusActive)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
newUser, err = module.userSetter.GetOrCreateUser(ctx, newUser, user.WithRoleNames([]string{signozManagedRole}))
|
||||
newUser, err = module.userSetter.GetOrCreateUser(ctx, newUser, user.WithRoleNames(roleNames))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ func (module *getter) VerifyResetPasswordToken(ctx context.Context, token string
|
||||
return nil
|
||||
}
|
||||
|
||||
func (module *getter) OnBeforeRoleDelete(ctx context.Context, orgID valuer.UUID, roleID valuer.UUID) error {
|
||||
func (module *getter) OnBeforeRoleDelete(ctx context.Context, orgID valuer.UUID, roleID valuer.UUID, _ string) error {
|
||||
users, err := module.GetUsersByOrgIDAndRoleID(ctx, orgID, roleID)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -96,7 +96,7 @@ type Getter interface {
|
||||
GetUsersByOrgIDAndRoleID(ctx context.Context, orgID valuer.UUID, roleID valuer.UUID) ([]*types.User, error)
|
||||
|
||||
// OnBeforeRoleDelete checks if any users are assigned to the role and rejects deletion if so.
|
||||
OnBeforeRoleDelete(ctx context.Context, orgID valuer.UUID, roleID valuer.UUID) error
|
||||
OnBeforeRoleDelete(ctx context.Context, orgID valuer.UUID, roleID valuer.UUID, roleName string) error
|
||||
|
||||
// VerifyResetPasswordToken checks if a reset password token exists and is not expired.
|
||||
VerifyResetPasswordToken(ctx context.Context, token string) error
|
||||
|
||||
@@ -128,6 +128,7 @@ func NewModules(
|
||||
}
|
||||
userSetter := impluser.NewSetter(impluser.NewStore(sqlstore, providerSettings), tokenizer, emailing, providerSettings, orgSetter, authz, analytics, config.User, userRoleStore, userGetter, onDeleteUser)
|
||||
ruleStore := sqlrulestore.NewRuleStore(sqlstore, queryParser, providerSettings)
|
||||
authDomainModule := implauthdomain.NewModule(implauthdomain.NewStore(sqlstore), authNs, authz)
|
||||
|
||||
return Modules{
|
||||
OrgGetter: orgGetter,
|
||||
@@ -142,8 +143,8 @@ func NewModules(
|
||||
QuickFilter: quickfilter,
|
||||
TraceFunnel: impltracefunnel.NewModule(impltracefunnel.NewStore(sqlstore)),
|
||||
RawDataExport: implrawdataexport.NewModule(querier),
|
||||
AuthDomain: implauthdomain.NewModule(implauthdomain.NewStore(sqlstore), authNs),
|
||||
Session: implsession.NewModule(providerSettings, authNs, userSetter, userGetter, implauthdomain.NewModule(implauthdomain.NewStore(sqlstore), authNs), tokenizer, orgGetter),
|
||||
AuthDomain: authDomainModule,
|
||||
Session: implsession.NewModule(providerSettings, authNs, userSetter, userGetter, authDomainModule, tokenizer, orgGetter, authz),
|
||||
SpanPercentile: implspanpercentile.NewModule(querier, providerSettings),
|
||||
Services: implservices.NewModule(querier, telemetryStore),
|
||||
MetricsExplorer: implmetricsexplorer.NewModule(telemetryStore, telemetryMetadataStore, cache, ruleStore, dashboard, providerSettings, config.MetricsExplorer),
|
||||
|
||||
@@ -215,6 +215,7 @@ func NewSQLMigrationProviderFactories(
|
||||
sqlmigration.NewRecreateUserDashboardPreferenceFactory(sqlstore, sqlschema),
|
||||
sqlmigration.NewMigrateRecurrenceBoundsFactory(sqlstore),
|
||||
sqlmigration.NewAddDashboardViewFactory(sqlstore, sqlschema),
|
||||
sqlmigration.NewMigrateSSORoleMappingNamesFactory(sqlstore),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/instrumentation"
|
||||
"github.com/SigNoz/signoz/pkg/licensing"
|
||||
"github.com/SigNoz/signoz/pkg/meterreporter"
|
||||
"github.com/SigNoz/signoz/pkg/modules/authdomain/implauthdomain"
|
||||
"github.com/SigNoz/signoz/pkg/modules/cloudintegration"
|
||||
"github.com/SigNoz/signoz/pkg/modules/dashboard"
|
||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||
@@ -349,10 +350,13 @@ func New(
|
||||
// Initialize service account getter
|
||||
serviceAccountGetter := implserviceaccount.NewGetter(implserviceaccount.NewStore(sqlstore))
|
||||
|
||||
authDomainGetter := implauthdomain.NewGetter(implauthdomain.NewStore(sqlstore))
|
||||
|
||||
// Build pre-delete callbacks from modules
|
||||
onBeforeRoleDelete := []authz.OnBeforeRoleDelete{
|
||||
userGetter.OnBeforeRoleDelete,
|
||||
serviceAccountGetter.OnBeforeRoleDelete,
|
||||
authDomainGetter.OnBeforeRoleDelete,
|
||||
}
|
||||
|
||||
// Initialize authz
|
||||
|
||||
127
pkg/sqlmigration/096_migrate_sso_role_mapping_names.go
Normal file
127
pkg/sqlmigration/096_migrate_sso_role_mapping_names.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package sqlmigration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/uptrace/bun"
|
||||
"github.com/uptrace/bun/migrate"
|
||||
)
|
||||
|
||||
type migrateSSORoleMappingNames struct {
|
||||
sqlstore sqlstore.SQLStore
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
type authDomainRow struct {
|
||||
bun.BaseModel `bun:"table:auth_domain"`
|
||||
|
||||
ID string `bun:"id"`
|
||||
Data string `bun:"data"`
|
||||
}
|
||||
|
||||
var legacyRoleToManagedRoleName = map[string]string{
|
||||
"ADMIN": "signoz-admin",
|
||||
"EDITOR": "signoz-editor",
|
||||
"VIEWER": "signoz-viewer",
|
||||
}
|
||||
|
||||
type ssoRoleMapping struct {
|
||||
DefaultRole string `json:"defaultRole"`
|
||||
GroupMappings map[string]string `json:"groupMappings"`
|
||||
UseRoleAttribute bool `json:"useRoleAttribute"`
|
||||
}
|
||||
|
||||
func NewMigrateSSORoleMappingNamesFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[SQLMigration, Config] {
|
||||
return factory.NewProviderFactory(
|
||||
factory.MustNewName("migrate_sso_role_mapping_names"),
|
||||
func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) {
|
||||
return &migrateSSORoleMappingNames{sqlstore: sqlstore, logger: ps.Logger}, nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (migration *migrateSSORoleMappingNames) Register(migrations *migrate.Migrations) error {
|
||||
return migrations.Register(migration.Up, migration.Down)
|
||||
}
|
||||
|
||||
func (migration *migrateSSORoleMappingNames) Up(ctx context.Context, db *bun.DB) error {
|
||||
tx, err := db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = tx.Rollback()
|
||||
}()
|
||||
|
||||
rows := make([]*authDomainRow, 0)
|
||||
if err := tx.NewSelect().Model(&rows).Scan(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, row := range rows {
|
||||
config := make(map[string]json.RawMessage)
|
||||
if err := json.Unmarshal([]byte(row.Data), &config); err != nil {
|
||||
migration.logger.WarnContext(ctx, "skipping auth domain with unreadable data", slog.String("auth_domain_id", row.ID), errors.Attr(err))
|
||||
continue
|
||||
}
|
||||
|
||||
roleMappingRaw, ok := config["roleMapping"]
|
||||
if !ok || string(roleMappingRaw) == "null" {
|
||||
continue
|
||||
}
|
||||
|
||||
var roleMapping ssoRoleMapping
|
||||
if err := json.Unmarshal(roleMappingRaw, &roleMapping); err != nil {
|
||||
migration.logger.WarnContext(ctx, "skipping auth domain with unreadable role mapping", slog.String("auth_domain_id", row.ID), errors.Attr(err))
|
||||
continue
|
||||
}
|
||||
|
||||
changed := false
|
||||
if managed, ok := legacyRoleToManagedRoleName[strings.ToUpper(roleMapping.DefaultRole)]; ok {
|
||||
roleMapping.DefaultRole = managed
|
||||
changed = true
|
||||
}
|
||||
for group, role := range roleMapping.GroupMappings {
|
||||
if managed, ok := legacyRoleToManagedRoleName[strings.ToUpper(role)]; ok {
|
||||
roleMapping.GroupMappings[group] = managed
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
|
||||
if !changed {
|
||||
continue
|
||||
}
|
||||
|
||||
newRoleMapping, err := json.Marshal(roleMapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config["roleMapping"] = newRoleMapping
|
||||
|
||||
newData, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := tx.NewUpdate().
|
||||
Model((*authDomainRow)(nil)).
|
||||
Set("data = ?", string(newData)).
|
||||
Where("id = ?", row.ID).
|
||||
Exec(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (migration *migrateSSORoleMappingNames) Down(context.Context, *bun.DB) error {
|
||||
return nil
|
||||
}
|
||||
@@ -2,10 +2,6 @@ package authtypes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
)
|
||||
|
||||
type AttributeMapping struct {
|
||||
@@ -51,83 +47,95 @@ func (attr *AttributeMapping) UnmarshalJSON(data []byte) error {
|
||||
}
|
||||
|
||||
type RoleMapping struct {
|
||||
// Default role any new SSO users. Defaults to "VIEWER"
|
||||
// Default role assigned to new SSO users when no group mapping applies.
|
||||
DefaultRole string `json:"defaultRole"`
|
||||
// Map of IDP group names to SigNoz roles. Key is group name, value is SigNoz role
|
||||
|
||||
// Map of IDP group name to SigNoz role name.
|
||||
GroupMappings map[string]string `json:"groupMappings"`
|
||||
// If true, use the role claim directly from IDP instead of group mappings
|
||||
|
||||
// If true, use the role claim directly from IDP instead of group mappings.
|
||||
UseRoleAttribute bool `json:"useRoleAttribute"`
|
||||
}
|
||||
|
||||
func (typ *RoleMapping) UnmarshalJSON(data []byte) error {
|
||||
type Alias RoleMapping
|
||||
func (roleMapping *RoleMapping) UnmarshalJSON(data []byte) error {
|
||||
type alias RoleMapping
|
||||
|
||||
var temp Alias
|
||||
var temp alias
|
||||
if err := json.Unmarshal(data, &temp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if temp.DefaultRole != "" {
|
||||
if _, err := types.NewRole(strings.ToUpper(temp.DefaultRole)); err != nil {
|
||||
return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "invalid default role %s", temp.DefaultRole)
|
||||
}
|
||||
}
|
||||
|
||||
temp.DefaultRole = NormalizeRoleName(temp.DefaultRole)
|
||||
for group, role := range temp.GroupMappings {
|
||||
if _, err := types.NewRole(strings.ToUpper(role)); err != nil {
|
||||
return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "invalid role %s for group %s", role, group)
|
||||
}
|
||||
temp.GroupMappings[group] = NormalizeRoleName(role)
|
||||
}
|
||||
|
||||
*typ = RoleMapping(temp)
|
||||
*roleMapping = RoleMapping(temp)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (roleMapping *RoleMapping) NewRoleFromCallbackIdentity(callbackIdentity *CallbackIdentity) types.Role {
|
||||
func (roleMapping *RoleMapping) NewRolesFromCallbackIdentity(callbackIdentity *CallbackIdentity, roleAttributeExists bool) []string {
|
||||
if roleMapping == nil {
|
||||
return types.RoleViewer
|
||||
return []string{SigNozViewerRoleName}
|
||||
}
|
||||
|
||||
if roleMapping.UseRoleAttribute && callbackIdentity.Role != "" {
|
||||
if role, err := types.NewRole(strings.ToUpper(callbackIdentity.Role)); err == nil {
|
||||
return role
|
||||
}
|
||||
if roleAttributeExists {
|
||||
return []string{NormalizeRoleName(callbackIdentity.Role)}
|
||||
}
|
||||
|
||||
if len(roleMapping.GroupMappings) > 0 && len(callbackIdentity.Groups) > 0 {
|
||||
highestRole := types.RoleViewer
|
||||
found := false
|
||||
|
||||
roleNames := make([]string, 0)
|
||||
seen := make(map[string]struct{})
|
||||
for _, group := range callbackIdentity.Groups {
|
||||
if mappedRole, exists := roleMapping.GroupMappings[group]; exists {
|
||||
found = true
|
||||
if role, err := types.NewRole(strings.ToUpper(mappedRole)); err == nil {
|
||||
if compareRoles(role, highestRole) > 0 {
|
||||
highestRole = role
|
||||
}
|
||||
}
|
||||
roleName, exists := roleMapping.GroupMappings[group]
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
if _, duplicate := seen[roleName]; duplicate {
|
||||
continue
|
||||
}
|
||||
seen[roleName] = struct{}{}
|
||||
roleNames = append(roleNames, roleName)
|
||||
}
|
||||
|
||||
if found {
|
||||
return highestRole
|
||||
if len(roleNames) > 0 {
|
||||
return roleNames
|
||||
}
|
||||
}
|
||||
|
||||
return []string{roleMapping.DefaultRoleName()}
|
||||
}
|
||||
|
||||
func (roleMapping *RoleMapping) DefaultRoleName() string {
|
||||
if roleMapping.DefaultRole != "" {
|
||||
return roleMapping.DefaultRole
|
||||
}
|
||||
|
||||
return SigNozViewerRoleName
|
||||
}
|
||||
|
||||
func (roleMapping *RoleMapping) RoleNames() []string {
|
||||
if roleMapping == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
seen := make(map[string]struct{})
|
||||
roleNames := make([]string, 0, len(roleMapping.GroupMappings)+1)
|
||||
|
||||
if roleMapping.DefaultRole != "" {
|
||||
if role, err := types.NewRole(strings.ToUpper(roleMapping.DefaultRole)); err == nil {
|
||||
return role
|
||||
seen[roleMapping.DefaultRole] = struct{}{}
|
||||
roleNames = append(roleNames, roleMapping.DefaultRole)
|
||||
}
|
||||
|
||||
for _, roleName := range roleMapping.GroupMappings {
|
||||
if roleName == "" {
|
||||
continue
|
||||
}
|
||||
if _, duplicate := seen[roleName]; duplicate {
|
||||
continue
|
||||
}
|
||||
seen[roleName] = struct{}{}
|
||||
roleNames = append(roleNames, roleName)
|
||||
}
|
||||
|
||||
return types.RoleViewer
|
||||
}
|
||||
|
||||
func compareRoles(a, b types.Role) int {
|
||||
order := map[types.Role]int{
|
||||
types.RoleViewer: 0,
|
||||
types.RoleEditor: 1,
|
||||
types.RoleAdmin: 2,
|
||||
}
|
||||
return order[a] - order[b]
|
||||
return roleNames
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ var (
|
||||
ErrCodeRoleUnsupported = errors.MustNewCode("role_unsupported")
|
||||
ErrCodeRoleHasUserAssignees = errors.MustNewCode("role_has_user_assignees")
|
||||
ErrCodeRoleHasServiceAccountAssignees = errors.MustNewCode("role_has_service_account_assignees")
|
||||
ErrCodeRoleHasAuthDomainMappings = errors.MustNewCode("role_has_auth_domain_mappings")
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -298,6 +299,20 @@ func MustGetSigNozManagedRoleFromExistingRole(role types.Role) string {
|
||||
return managedRole
|
||||
}
|
||||
|
||||
func NormalizeRoleName(role string) string {
|
||||
legacyRole, err := types.NewRole(strings.ToUpper(role))
|
||||
if err != nil {
|
||||
return role
|
||||
}
|
||||
|
||||
managedRole, ok := ExistingRoleToSigNozManagedRoleMap[legacyRole]
|
||||
if !ok {
|
||||
return role
|
||||
}
|
||||
|
||||
return managedRole
|
||||
}
|
||||
|
||||
type RoleStore interface {
|
||||
Create(context.Context, *Role) error
|
||||
Get(context.Context, valuer.UUID, valuer.UUID) (*Role, error)
|
||||
|
||||
Reference in New Issue
Block a user