mirror of
https://github.com/grafana/grafana.git
synced 2024-11-29 04:04:00 -06:00
b9abb8cabb
* allow users with regular actions access provisioning API paths * update methods that read rules skip new authorization logic if user CanReadAllRules to avoid performance impact on file-provisioning update all methods to accept identity.Requester that contains all permissions and is required by access control. * create deltas for single rul e * update modify methods skip new authorization logic if user CanWriteAllRules to avoid performance impact on file-provisioning update all methods to accept identity.Requester that contains all permissions and is required by access control. * implement RuleAccessControlService in provisioning * update file provisioning user to have all permissions to bypass authz * update provisioning API to return errutil errors correctly --------- Co-authored-by: Alexander Weaver <weaver.alex.d@gmail.com>
77 lines
3.3 KiB
Go
77 lines
3.3 KiB
Go
package provisioning
|
|
|
|
import (
|
|
"context"
|
|
|
|
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
|
"github.com/grafana/grafana/pkg/services/auth/identity"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
|
)
|
|
|
|
type RuleAccessControlService interface {
|
|
HasAccess(ctx context.Context, user identity.Requester, evaluator ac.Evaluator) (bool, error)
|
|
AuthorizeAccessToRuleGroup(ctx context.Context, user identity.Requester, rules models.RulesGroup) error
|
|
AuthorizeRuleChanges(ctx context.Context, user identity.Requester, change *store.GroupDelta) error
|
|
}
|
|
|
|
func newRuleAccessControlService(ac RuleAccessControlService) *provisioningRuleAccessControl {
|
|
return &provisioningRuleAccessControl{
|
|
RuleAccessControlService: ac,
|
|
}
|
|
}
|
|
|
|
type provisioningRuleAccessControl struct {
|
|
RuleAccessControlService
|
|
}
|
|
|
|
var _ ruleAccessControlService = &provisioningRuleAccessControl{}
|
|
|
|
// AuthorizeRuleGroupRead authorizes the read access to a group of rules for a user.
|
|
// It first checks if the user has permission to read all rules. If yes, it bypasses the authorization.
|
|
// If not, it calls the RuleAccessControlService to authorize access to the rule group.
|
|
// It returns an error if the authorization fails or if there is an error during permission check.
|
|
func (p *provisioningRuleAccessControl) AuthorizeRuleGroupRead(ctx context.Context, user identity.Requester, rules models.RulesGroup) error {
|
|
can, err := p.CanReadAllRules(ctx, user)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !can {
|
|
return p.RuleAccessControlService.AuthorizeAccessToRuleGroup(ctx, user, rules)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// AuthorizeRuleGroupWrite authorizes the write access to a group of rules for a user.
|
|
// It first checks if the user has permission to write all rules. If yes, it bypasses the authorization.
|
|
// If not, it calls the RuleAccessControlService to authorize the rule changes.
|
|
// It returns an error if the authorization fails or if there is an error during permission check.
|
|
func (p *provisioningRuleAccessControl) AuthorizeRuleGroupWrite(ctx context.Context, user identity.Requester, change *store.GroupDelta) error {
|
|
can, err := p.CanWriteAllRules(ctx, user)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !can {
|
|
return p.RuleAccessControlService.AuthorizeRuleChanges(ctx, user, change)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// CanReadAllRules checks if the user has permission to read all rules.
|
|
// It evaluates if the user has either "alert.provisioning:read" or "alert.provisioning.secrets:read" permissions.
|
|
// It returns true if the user has the required permissions, otherwise it returns false.
|
|
func (p *provisioningRuleAccessControl) CanReadAllRules(ctx context.Context, user identity.Requester) (bool, error) {
|
|
return p.HasAccess(ctx, user, ac.EvalAny(
|
|
ac.EvalPermission(ac.ActionAlertingProvisioningRead),
|
|
ac.EvalPermission(ac.ActionAlertingProvisioningReadSecrets),
|
|
))
|
|
}
|
|
|
|
// CanWriteAllRules is a method that checks if a user has permission to write all rules.
|
|
// It calls the HasAccess method with the provided action "alert.provisioning:write".
|
|
// It returns true if the user has permission, false otherwise.
|
|
// It returns an error if there is a problem checking the permission.
|
|
func (p *provisioningRuleAccessControl) CanWriteAllRules(ctx context.Context, user identity.Requester) (bool, error) {
|
|
return p.HasAccess(ctx, user, ac.EvalPermission(ac.ActionAlertingProvisioningWrite))
|
|
}
|