mirror of
https://github.com/grafana/grafana.git
synced 2024-11-25 18:30:41 -06:00
8418aca823
* Alerting: Add single rule checks to alert rule access control Modifies ruler api single rule read to no longer fetch entire groups and instead use the new single rule ac check. Simplifies provisioning api getAlertRuleAuthorized logic to always load a single rule instead of conditionally loading the entire group when provisioning permissions are not present. * Swap out Has/AuthorizeAccessToRule for Has/AuthorizeAccessInFolder
98 lines
4.3 KiB
Go
98 lines
4.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/accesscontrol"
|
|
"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
|
|
AuthorizeAccessInFolder(ctx context.Context, user identity.Requester, namespaced accesscontrol.Namespaced) 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{}
|
|
|
|
// AuthorizeRuleRead authorizes the read access to a rule 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.
|
|
// It returns an error if the authorization fails or if there is an error during permission check.
|
|
func (p *provisioningRuleAccessControl) AuthorizeRuleRead(ctx context.Context, user identity.Requester, rule *models.AlertRule) error {
|
|
can, err := p.CanReadAllRules(ctx, user)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !can {
|
|
return p.RuleAccessControlService.AuthorizeAccessInFolder(ctx, user, rule)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 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),
|
|
ac.EvalPermission(ac.ActionAlertingRulesProvisioningRead),
|
|
))
|
|
}
|
|
|
|
// 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.EvalAny(
|
|
ac.EvalPermission(ac.ActionAlertingProvisioningWrite),
|
|
ac.EvalPermission(ac.ActionAlertingRulesProvisioningWrite),
|
|
))
|
|
}
|