Alerting: Receiver resource permissions service (#93552)

This commit is contained in:
Matthew Jacobson 2024-09-20 18:31:42 -04:00 committed by GitHub
parent 7398fe3fcb
commit 1ede1e32b8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 295 additions and 57 deletions

View File

@ -107,9 +107,9 @@ func convertToK8sResource(
var permissionMapper = map[ngmodels.ReceiverPermission]string{
ngmodels.ReceiverPermissionReadSecret: "canReadSecrets",
//ngmodels.ReceiverPermissionAdmin: "canAdmin", // TODO: Add when resource permissions are implemented.
ngmodels.ReceiverPermissionWrite: "canWrite",
ngmodels.ReceiverPermissionDelete: "canDelete",
ngmodels.ReceiverPermissionAdmin: "canAdmin",
ngmodels.ReceiverPermissionWrite: "canWrite",
ngmodels.ReceiverPermissionDelete: "canDelete",
}
func convertToDomainModel(receiver *model.Receiver) (*ngmodels.Receiver, map[string][]string, error) {

View File

@ -315,6 +315,8 @@ var wireBasicSet = wire.NewSet(
wire.Bind(new(accesscontrol.FolderPermissionsService), new(*ossaccesscontrol.FolderPermissionsService)),
ossaccesscontrol.ProvideDashboardPermissions,
wire.Bind(new(accesscontrol.DashboardPermissionsService), new(*ossaccesscontrol.DashboardPermissionsService)),
ossaccesscontrol.ProvideReceiverPermissionsService,
wire.Bind(new(accesscontrol.ReceiverPermissionsService), new(*ossaccesscontrol.ReceiverPermissionsService)),
starimpl.ProvideService,
playlistimpl.ProvideService,
apikeyimpl.ProvideService,

View File

@ -11,6 +11,7 @@ import (
"go.opentelemetry.io/otel/trace"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/registry"
"github.com/grafana/grafana/pkg/services/authn"
@ -148,6 +149,10 @@ type ServiceAccountPermissionsService interface {
PermissionsService
}
type ReceiverPermissionsService interface {
PermissionsService
}
type PermissionsService interface {
// GetPermissions returns all permissions for given resourceID
GetPermissions(ctx context.Context, user identity.Requester, resourceID string) ([]ResourcePermission, error)

View File

@ -444,12 +444,14 @@ const (
ActionAlertingNotificationsTimeIntervalsDelete = "alert.notifications.time-intervals:delete"
// Alerting receiver actions
ActionAlertingReceiversList = "alert.notifications.receivers:list"
ActionAlertingReceiversRead = "alert.notifications.receivers:read"
ActionAlertingReceiversReadSecrets = "alert.notifications.receivers.secrets:read"
ActionAlertingReceiversCreate = "alert.notifications.receivers:create"
ActionAlertingReceiversUpdate = "alert.notifications.receivers:write"
ActionAlertingReceiversDelete = "alert.notifications.receivers:delete"
ActionAlertingReceiversList = "alert.notifications.receivers:list"
ActionAlertingReceiversRead = "alert.notifications.receivers:read"
ActionAlertingReceiversReadSecrets = "alert.notifications.receivers.secrets:read"
ActionAlertingReceiversCreate = "alert.notifications.receivers:create"
ActionAlertingReceiversUpdate = "alert.notifications.receivers:write"
ActionAlertingReceiversDelete = "alert.notifications.receivers:delete"
ActionAlertingReceiversPermissionsRead = "receivers.permissions:read"
ActionAlertingReceiversPermissionsWrite = "receivers.permissions:write"
// External alerting rule actions. We can only narrow it down to writes or reads, as we don't control the atomicity in the external system.
ActionAlertingRuleExternalWrite = "alert.rules.external:write"

View File

@ -0,0 +1,60 @@
package ossaccesscontrol
import (
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/licensing"
"github.com/grafana/grafana/pkg/services/ngalert"
alertingac "github.com/grafana/grafana/pkg/services/ngalert/accesscontrol"
"github.com/grafana/grafana/pkg/services/team"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
)
var ReceiversViewActions = []string{accesscontrol.ActionAlertingReceiversRead}
var ReceiversEditActions = append(ReceiversViewActions, []string{accesscontrol.ActionAlertingReceiversUpdate, accesscontrol.ActionAlertingReceiversDelete}...)
var ReceiversAdminActions = append(ReceiversEditActions, []string{accesscontrol.ActionAlertingReceiversReadSecrets, accesscontrol.ActionAlertingReceiversPermissionsRead, accesscontrol.ActionAlertingReceiversPermissionsWrite}...)
func ProvideReceiverPermissionsService(
cfg *setting.Cfg, features featuremgmt.FeatureToggles, router routing.RouteRegister, sql db.DB, ac accesscontrol.AccessControl,
license licensing.Licensing, service accesscontrol.Service,
teamService team.Service, userService user.Service, actionSetService resourcepermissions.ActionSetService,
) (*ReceiverPermissionsService, error) {
if !features.IsEnabledGlobally(featuremgmt.FlagAlertingApiServer) {
return nil, nil
}
options := resourcepermissions.Options{
Resource: "receivers",
ResourceAttribute: "uid",
Assignments: resourcepermissions.Assignments{
Users: true,
Teams: true,
BuiltInRoles: true,
ServiceAccounts: true,
},
PermissionsToActions: map[string][]string{
string(alertingac.ReceiverPermissionView): append([]string{}, ReceiversViewActions...),
string(alertingac.ReceiverPermissionEdit): append([]string{}, ReceiversEditActions...),
string(alertingac.ReceiverPermissionAdmin): append([]string{}, ReceiversAdminActions...),
},
ReaderRoleName: "Alerting receiver permission reader",
WriterRoleName: "Alerting receiver permission writer",
RoleGroup: ngalert.AlertRolesGroup,
}
srv, err := resourcepermissions.New(cfg, options, features, router, license, ac, service, sql, teamService, userService, actionSetService)
if err != nil {
return nil, err
}
return &ReceiverPermissionsService{Service: srv}, nil
}
var _ accesscontrol.ReceiverPermissionsService = new(ReceiverPermissionsService)
type ReceiverPermissionsService struct {
*resourcepermissions.Service
}

View File

@ -4,6 +4,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/featuremgmt"
ac "github.com/grafana/grafana/pkg/services/ngalert/accesscontrol"
"github.com/grafana/grafana/pkg/services/org"
)
@ -115,13 +116,50 @@ var (
},
}
receiversReaderRole = accesscontrol.RoleRegistration{
Role: accesscontrol.RoleDTO{
Name: accesscontrol.FixedRolePrefix + "alerting.receivers:reader",
DisplayName: "Contact Point Reader",
Description: "Read all contact points in Grafana",
Group: AlertRolesGroup,
Permissions: []accesscontrol.Permission{
{Action: accesscontrol.ActionAlertingReceiversRead, Scope: ac.ScopeReceiversAll},
},
},
}
receiversCreatorRole = accesscontrol.RoleRegistration{
Role: accesscontrol.RoleDTO{
Name: accesscontrol.FixedRolePrefix + "alerting.receivers:creator",
DisplayName: "Contact Point Creator",
Description: "Create new contact points in Grafana",
Group: AlertRolesGroup,
Permissions: []accesscontrol.Permission{
{Action: accesscontrol.ActionAlertingReceiversCreate},
},
},
}
receiversWriterRole = accesscontrol.RoleRegistration{
Role: accesscontrol.RoleDTO{
Name: accesscontrol.FixedRolePrefix + "alerting.receivers:writer",
DisplayName: "Contact Point Writer",
Description: "Create, update, and delete all contact points in Grafana",
Group: AlertRolesGroup,
Permissions: accesscontrol.ConcatPermissions(receiversReaderRole.Role.Permissions, receiversCreatorRole.Role.Permissions, []accesscontrol.Permission{
{Action: accesscontrol.ActionAlertingReceiversUpdate, Scope: ac.ScopeReceiversAll},
{Action: accesscontrol.ActionAlertingReceiversDelete, Scope: ac.ScopeReceiversAll},
}),
},
}
notificationsReaderRole = accesscontrol.RoleRegistration{
Role: accesscontrol.RoleDTO{
Name: accesscontrol.FixedRolePrefix + "alerting.notifications:reader",
DisplayName: "Notifications Reader",
Description: "Read notification policies and contact points in Grafana and external providers",
Group: AlertRolesGroup,
Permissions: []accesscontrol.Permission{
Permissions: accesscontrol.ConcatPermissions(receiversReaderRole.Role.Permissions, []accesscontrol.Permission{
{
Action: accesscontrol.ActionAlertingNotificationsRead,
},
@ -132,11 +170,7 @@ var (
{
Action: accesscontrol.ActionAlertingNotificationsTimeIntervalsRead,
},
{
Action: accesscontrol.ActionAlertingReceiversRead,
Scope: ac.ScopeReceiversAll,
},
},
}),
},
}
@ -146,7 +180,7 @@ var (
DisplayName: "Notifications Writer",
Description: "Add, update, and delete contact points and notification policies in Grafana and external providers",
Group: AlertRolesGroup,
Permissions: accesscontrol.ConcatPermissions(notificationsReaderRole.Role.Permissions, []accesscontrol.Permission{
Permissions: accesscontrol.ConcatPermissions(notificationsReaderRole.Role.Permissions, receiversWriterRole.Role.Permissions, []accesscontrol.Permission{
{
Action: accesscontrol.ActionAlertingNotificationsWrite,
},
@ -154,18 +188,6 @@ var (
Action: accesscontrol.ActionAlertingNotificationsExternalWrite,
Scope: datasources.ScopeAll,
},
{
Action: accesscontrol.ActionAlertingReceiversCreate,
Scope: ac.ScopeReceiversAll,
},
{
Action: accesscontrol.ActionAlertingReceiversUpdate,
Scope: ac.ScopeReceiversAll,
},
{
Action: accesscontrol.ActionAlertingReceiversDelete,
Scope: ac.ScopeReceiversAll,
},
}),
},
}
@ -184,12 +206,27 @@ var (
alertingWriterRole = accesscontrol.RoleRegistration{
Role: accesscontrol.RoleDTO{
Name: accesscontrol.FixedRolePrefix + "alerting:writer",
DisplayName: "Full access",
Description: "Add,update and delete alert rules, instances, silences, contact points, and notification policies in Grafana and all external providers",
DisplayName: "Full write access",
Description: "Add, update and delete alert rules, instances, silences, contact points, and notification policies in Grafana and all external providers",
Group: AlertRolesGroup,
Permissions: accesscontrol.ConcatPermissions(rulesWriterRole.Role.Permissions, instancesWriterRole.Role.Permissions, notificationsWriterRole.Role.Permissions),
},
Grants: []string{string(org.RoleEditor), string(org.RoleAdmin)},
Grants: []string{string(org.RoleEditor)},
}
alertingAdminRole = accesscontrol.RoleRegistration{
Role: accesscontrol.RoleDTO{
Name: accesscontrol.FixedRolePrefix + "alerting:admin",
DisplayName: "Full admin access",
Description: "Full write access in Grafana and all external providers, including their permissions and secrets",
Group: AlertRolesGroup,
Permissions: accesscontrol.ConcatPermissions(alertingWriterRole.Role.Permissions, []accesscontrol.Permission{
{Action: accesscontrol.ActionAlertingReceiversPermissionsRead, Scope: ac.ScopeReceiversAll},
{Action: accesscontrol.ActionAlertingReceiversPermissionsWrite, Scope: ac.ScopeReceiversAll},
{Action: accesscontrol.ActionAlertingReceiversReadSecrets, Scope: ac.ScopeReceiversAll},
}),
},
Grants: []string{string(org.RoleAdmin)},
}
alertingProvisionerRole = accesscontrol.RoleRegistration{
@ -266,11 +303,17 @@ var (
}
)
func DeclareFixedRoles(service accesscontrol.Service) error {
return service.DeclareFixedRoles(
func DeclareFixedRoles(service accesscontrol.Service, features featuremgmt.FeatureToggles) error {
fixedRoles := []accesscontrol.RoleRegistration{
rulesReaderRole, rulesWriterRole,
instancesReaderRole, instancesWriterRole,
notificationsReaderRole, notificationsWriterRole,
alertingReaderRole, alertingWriterRole, alertingProvisionerRole, alertingProvisioningReaderWithSecretsRole, alertingProvisioningStatus,
)
alertingReaderRole, alertingWriterRole, alertingAdminRole, alertingProvisionerRole, alertingProvisioningReaderWithSecretsRole, alertingProvisioningStatus,
}
if features.IsEnabledGlobally(featuremgmt.FlagAlertingApiServer) {
fixedRoles = append(fixedRoles, receiversReaderRole, receiversCreatorRole, receiversWriterRole)
}
return service.DeclareFixedRoles(fixedRoles...)
}

View File

@ -17,6 +17,15 @@ var (
ScopeReceiversAll = ScopeReceiversProvider.GetResourceAllScope()
)
// ReceiverPermission is a type for representing a receiver permission.
type ReceiverPermission string
const (
ReceiverPermissionView ReceiverPermission = "View"
ReceiverPermissionEdit ReceiverPermission = "Edit"
ReceiverPermissionAdmin ReceiverPermission = "Admin"
)
var (
// Asserts pre-conditions for read access to redacted receivers. If this evaluates to false, the user cannot read any redacted receivers.
readRedactedReceiversPreConditionsEval = ac.EvalAny(
@ -125,6 +134,28 @@ var (
ac.EvalPermission(ac.ActionAlertingReceiversDelete, ScopeReceiversProvider.GetResourceScopeUID(uid)),
)
}
// Admin
// Asserts pre-conditions for resource permissions access to receivers. If this evaluates to false, the user cannot modify permissions for any receivers.
permissionsReceiversPreConditionsEval = ac.EvalAll(
ac.EvalPermission(ac.ActionAlertingReceiversPermissionsRead), // Action for receivers. UID scope.
ac.EvalPermission(ac.ActionAlertingReceiversPermissionsWrite), // Action for receivers. UID scope.
)
// Asserts resource permissions access to all receivers.
permissionsAllReceiversEval = ac.EvalAll(
ac.EvalPermission(ac.ActionAlertingReceiversPermissionsRead, ScopeReceiversAll),
ac.EvalPermission(ac.ActionAlertingReceiversPermissionsWrite, ScopeReceiversAll),
)
// Asserts resource permissions access to a specific receiver.
permissionsReceiverEval = func(uid string) ac.Evaluator {
return ac.EvalAll(
ac.EvalPermission(ac.ActionAlertingReceiversPermissionsRead, ScopeReceiversProvider.GetResourceScopeUID(uid)),
ac.EvalPermission(ac.ActionAlertingReceiversPermissionsWrite, ScopeReceiversProvider.GetResourceScopeUID(uid)),
)
}
)
type ReceiverAccess[T models.Identified] struct {
@ -133,6 +164,7 @@ type ReceiverAccess[T models.Identified] struct {
create actionAccess[T]
update actionAccess[T]
delete actionAccess[T]
permissions actionAccess[T]
}
// NewReceiverAccess creates a new ReceiverAccess service. If includeProvisioningActions is true, the service will include
@ -199,6 +231,18 @@ func NewReceiverAccess[T models.Identified](a ac.AccessControl, includeProvision
},
authorizeAll: deleteAllReceiversEval,
},
permissions: actionAccess[T]{
genericService: genericService{
ac: a,
},
resource: "receiver",
action: "admin", // Essentially read+write receiver resource permissions.
authorizeSome: permissionsReceiversPreConditionsEval,
authorizeOne: func(receiver models.Identified) ac.Evaluator {
return permissionsReceiverEval(receiver.GetUID())
},
authorizeAll: permissionsAllReceiversEval,
},
}
// If this service is meant for the provisioning API, we include the provisioning actions as possible permissions.
@ -219,9 +263,10 @@ func NewReceiverAccess[T models.Identified](a ac.AccessControl, includeProvision
})
}
// Write and delete permissions should require read permissions.
// Write, delete, and permissions management should require read permissions.
extendAccessControl(&rcvAccess.update, ac.EvalAll, rcvAccess.read)
extendAccessControl(&rcvAccess.delete, ac.EvalAll, rcvAccess.read)
extendAccessControl(&rcvAccess.permissions, ac.EvalAll, rcvAccess.read)
return rcvAccess
}
@ -335,12 +380,11 @@ func (s ReceiverAccess[T]) Access(ctx context.Context, user identity.Requester,
basePerms.Set(models.ReceiverPermissionReadSecret, true) // Has access to all receivers.
}
// TODO: Add when resource permissions are implemented.
//if err := s.permissions.AuthorizePreConditions(ctx, user); err != nil {
// basePerms.Set(models.ReceiverPermissionAdmin, false) // Doesn't match the preconditions.
//} else if err := s.permissions.AuthorizeAll(ctx, user); err == nil {
// basePerms.Set(models.ReceiverPermissionAdmin, true) // Has access to all receivers.
//}
if err := s.permissions.AuthorizePreConditions(ctx, user); err != nil {
basePerms.Set(models.ReceiverPermissionAdmin, false) // Doesn't match the preconditions.
} else if err := s.permissions.AuthorizeAll(ctx, user); err == nil {
basePerms.Set(models.ReceiverPermissionAdmin, true) // Has access to all receivers.
}
if err := s.update.AuthorizePreConditions(ctx, user); err != nil {
basePerms.Set(models.ReceiverPermissionWrite, false) // Doesn't match the preconditions.
@ -371,11 +415,10 @@ func (s ReceiverAccess[T]) Access(ctx context.Context, user identity.Requester,
permSet.Set(models.ReceiverPermissionReadSecret, err == nil)
}
// TODO: Add when resource permissions are implemented.
//if _, ok := permSet.Has(models.ReceiverPermissionAdmin); !ok {
// err := s.permissions.authorize(ctx, user, rcv)
// permSet.Set(models.ReceiverPermissionAdmin, err == nil)
//}
if _, ok := permSet.Has(models.ReceiverPermissionAdmin); !ok {
err := s.permissions.authorize(ctx, user, rcv)
permSet.Set(models.ReceiverPermissionAdmin, err == nil)
}
if _, ok := permSet.Has(models.ReceiverPermissionWrite); !ok {
err := s.update.authorize(ctx, user, rcv)

View File

@ -238,6 +238,65 @@ func TestReceiverAccess(t *testing.T) {
recv3.UID: permissions(),
},
},
// Receiver admin.
{
name: "receiver read permissions alone can't admin",
user: newViewUser(ac.Permission{Action: ac.ActionAlertingReceiversPermissionsRead, Scope: ScopeReceiversAll}),
expected: map[string]models.ReceiverPermissionSet{
recv1.UID: permissions(),
recv2.UID: permissions(),
recv3.UID: permissions(),
},
},
{
name: "receiver write permissions alone can't admin",
user: newViewUser(ac.Permission{Action: ac.ActionAlertingReceiversPermissionsWrite, Scope: ScopeReceiversAll}),
expected: map[string]models.ReceiverPermissionSet{
recv1.UID: permissions(),
recv2.UID: permissions(),
recv3.UID: permissions(),
},
},
{
name: "global receiver read + write permissions can admin",
user: newViewUser(
ac.Permission{Action: ac.ActionAlertingReceiversPermissionsRead, Scope: ScopeReceiversAll},
ac.Permission{Action: ac.ActionAlertingReceiversPermissionsWrite, Scope: ScopeReceiversAll},
),
expected: map[string]models.ReceiverPermissionSet{
recv1.UID: permissions(models.ReceiverPermissionAdmin),
recv2.UID: permissions(models.ReceiverPermissionAdmin),
recv3.UID: permissions(models.ReceiverPermissionAdmin),
},
},
{
name: "per-receiver read + write permissions should have per-receiver admin",
user: newViewUser(
ac.Permission{Action: ac.ActionAlertingReceiversPermissionsRead, Scope: ScopeReceiversProvider.GetResourceScopeUID(recv1.UID)},
ac.Permission{Action: ac.ActionAlertingReceiversPermissionsWrite, Scope: ScopeReceiversProvider.GetResourceScopeUID(recv1.UID)},
ac.Permission{Action: ac.ActionAlertingReceiversPermissionsRead, Scope: ScopeReceiversProvider.GetResourceScopeUID(recv3.UID)},
ac.Permission{Action: ac.ActionAlertingReceiversPermissionsWrite, Scope: ScopeReceiversProvider.GetResourceScopeUID(recv3.UID)},
),
expected: map[string]models.ReceiverPermissionSet{
recv1.UID: permissions(models.ReceiverPermissionAdmin),
recv2.UID: permissions(),
recv3.UID: permissions(models.ReceiverPermissionAdmin),
},
},
{
name: "per-receiver admin should require read",
user: newEmptyUser(
ac.Permission{Action: ac.ActionAlertingReceiversPermissionsRead, Scope: ScopeReceiversProvider.GetResourceScopeUID(recv1.UID)},
ac.Permission{Action: ac.ActionAlertingReceiversPermissionsWrite, Scope: ScopeReceiversProvider.GetResourceScopeUID(recv1.UID)},
ac.Permission{Action: ac.ActionAlertingReceiversPermissionsRead, Scope: ScopeReceiversProvider.GetResourceScopeUID(recv3.UID)},
ac.Permission{Action: ac.ActionAlertingReceiversPermissionsWrite, Scope: ScopeReceiversProvider.GetResourceScopeUID(recv3.UID)},
),
expected: map[string]models.ReceiverPermissionSet{
recv1.UID: permissions(),
recv2.UID: permissions(),
recv3.UID: permissions(),
},
},
// Mixed permissions.
{
name: "legacy provisioning secret read, receiver write",

View File

@ -10,16 +10,16 @@ type ReceiverPermission string
const (
ReceiverPermissionReadSecret ReceiverPermission = "secrets"
//ReceiverPermissionAdmin ReceiverPermission = "admin" // TODO: Add when resource permissions are implemented.
ReceiverPermissionWrite ReceiverPermission = "write"
ReceiverPermissionDelete ReceiverPermission = "delete"
ReceiverPermissionAdmin ReceiverPermission = "admin"
ReceiverPermissionWrite ReceiverPermission = "write"
ReceiverPermissionDelete ReceiverPermission = "delete"
)
// ReceiverPermissions returns all possible silence permissions.
func ReceiverPermissions() []ReceiverPermission {
return []ReceiverPermission{
ReceiverPermissionReadSecret,
//ReceiverPermissionAdmin, // TODO: Add when resource permissions are implemented.
ReceiverPermissionAdmin,
ReceiverPermissionWrite,
ReceiverPermissionDelete,
}

View File

@ -489,7 +489,7 @@ func (ng *AlertNG) init() error {
return key.LogContext(), true
})
return DeclareFixedRoles(ng.accesscontrolService)
return DeclareFixedRoles(ng.accesscontrolService, ng.FeatureToggles)
}
func subscribeToFolderChanges(logger log.Logger, bus bus.Bus, dbStore api.RuleStore) {

View File

@ -27,6 +27,7 @@ import (
notificationsv0alpha1 "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/alerting_notifications/v0alpha1"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
"github.com/grafana/grafana/pkg/services/authz/zanzana"
"github.com/grafana/grafana/pkg/services/dashboards"
@ -142,6 +143,7 @@ func TestIntegrationAccessControl(t *testing.T) {
canCreate bool
canDelete bool
canReadSecrets bool
canAdmin bool
}
// region users
unauthorized := helper.CreateUser("unauthorized", "Org1", org.RoleNone, []resourcepermissions.SetResourcePermissionCommand{})
@ -185,6 +187,12 @@ func TestIntegrationAccessControl(t *testing.T) {
},
},
})
adminLikeUser := helper.CreateUser("adminLikeUser", apis.Org1, org.RoleNone, []resourcepermissions.SetResourcePermissionCommand{
createWildcardPermission(append(
[]string{accesscontrol.ActionAlertingReceiversCreate},
ossaccesscontrol.ReceiversAdminActions...,
)...),
})
// endregion
@ -197,11 +205,13 @@ func TestIntegrationAccessControl(t *testing.T) {
canDelete: false,
},
{
user: org1.Admin,
canRead: true,
canUpdate: true,
canCreate: true,
canDelete: true,
user: org1.Admin,
canRead: true,
canCreate: true,
canUpdate: true,
canDelete: true,
canAdmin: true,
canReadSecrets: true,
},
{
user: org1.Editor,
@ -249,6 +259,15 @@ func TestIntegrationAccessControl(t *testing.T) {
canUpdate: true,
canDelete: true,
},
{
user: adminLikeUser,
canRead: true,
canCreate: true,
canUpdate: true,
canDelete: true,
canAdmin: true,
canReadSecrets: true,
},
}
admin := org1.Admin
@ -315,6 +334,9 @@ func TestIntegrationAccessControl(t *testing.T) {
if tc.canReadSecrets {
expectedWithMetadata.SetAccessControl("canReadSecrets")
}
if tc.canAdmin {
expectedWithMetadata.SetAccessControl("canAdmin")
}
t.Run("should be able to list receivers", func(t *testing.T) {
list, err := client.List(ctx, v1.ListOptions{})
require.NoError(t, err)
@ -1027,6 +1049,8 @@ func TestIntegrationCRUD(t *testing.T) {
// Set expected metadata
receiver.SetAccessControl("canWrite")
receiver.SetAccessControl("canDelete")
receiver.SetAccessControl("canReadSecrets")
receiver.SetAccessControl("canAdmin")
receiver.SetInUse(0, nil)
// Use export endpoint because it's the only way to get decrypted secrets fast.