mirror of
https://github.com/coreos/prometheus-operator.git
synced 2026-02-05 06:45:27 +01:00
chore: check operator's permissions on status
This commit ensures that the operator's Service Account has the expected permissions to manage status subresources when the `StatusForConfigurationResources` feature gate is enabled. Signed-off-by: Simon Pasquier <spasquie@redhat.com>
This commit is contained in:
@@ -197,6 +197,47 @@ func parseFlags(fs *flag.FlagSet) {
|
||||
_ = fs.Parse(os.Args[1:])
|
||||
}
|
||||
|
||||
// checkStatusSubresourcePermissions returns true when the operator has the
|
||||
// required permissions to update the status subresource of the provided
|
||||
// configuration resources.
|
||||
func checkStatusSubresourcePermissions(
|
||||
ctx context.Context,
|
||||
logger *slog.Logger,
|
||||
kclient kubernetes.Interface,
|
||||
gvrs []schema.GroupVersionResource,
|
||||
) bool {
|
||||
ok := true
|
||||
for _, gvr := range gvrs {
|
||||
allowed, errs, err := k8sutil.IsAllowed(
|
||||
ctx,
|
||||
kclient.AuthorizationV1().SelfSubjectAccessReviews(),
|
||||
cfg.Namespaces.AllowList.Slice(),
|
||||
k8sutil.ResourceAttribute{
|
||||
Group: gvr.Group,
|
||||
Version: gvr.Version,
|
||||
Resource: fmt.Sprintf("%s/status", gvr.Resource),
|
||||
Verbs: []string{"update"},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
ok = false
|
||||
logger.Error("failed to check permissions on status subresource", "err", err, "resource", gvr.String())
|
||||
continue
|
||||
}
|
||||
|
||||
if allowed {
|
||||
continue
|
||||
}
|
||||
|
||||
ok = false
|
||||
for _, reason := range errs {
|
||||
logger.Error("missing permission on status subresource", "reason", reason, "resource", gvr.String())
|
||||
}
|
||||
}
|
||||
|
||||
return ok
|
||||
}
|
||||
|
||||
func run(fs *flag.FlagSet) int {
|
||||
parseFlags(fs)
|
||||
|
||||
@@ -391,6 +432,25 @@ func run(fs *flag.FlagSet) int {
|
||||
|
||||
var po *prometheuscontroller.Operator
|
||||
if prometheusSupported {
|
||||
if cfg.Gates.Enabled(operator.StatusForConfigurationResourcesFeature) {
|
||||
if !checkStatusSubresourcePermissions(
|
||||
ctx,
|
||||
logger,
|
||||
kclient,
|
||||
[]schema.GroupVersionResource{
|
||||
monitoringv1.SchemeGroupVersion.WithResource(monitoringv1.ServiceMonitorName),
|
||||
monitoringv1.SchemeGroupVersion.WithResource(monitoringv1.PodMonitorName),
|
||||
monitoringv1.SchemeGroupVersion.WithResource(monitoringv1.ProbeName),
|
||||
monitoringv1.SchemeGroupVersion.WithResource(monitoringv1.PrometheusRuleName),
|
||||
},
|
||||
) {
|
||||
cancel()
|
||||
return 1
|
||||
}
|
||||
|
||||
promControllerOptions = append(promControllerOptions, prometheuscontroller.WithConfigResourceStatus())
|
||||
}
|
||||
|
||||
po, err = prometheuscontroller.New(ctx, restConfig, cfg, logger, r, promControllerOptions...)
|
||||
if err != nil {
|
||||
logger.Error("instantiating prometheus controller failed", "err", err)
|
||||
@@ -453,6 +513,24 @@ func run(fs *flag.FlagSet) int {
|
||||
|
||||
var pao *prometheusagentcontroller.Operator
|
||||
if prometheusAgentSupported {
|
||||
if cfg.Gates.Enabled(operator.StatusForConfigurationResourcesFeature) {
|
||||
if !checkStatusSubresourcePermissions(
|
||||
ctx,
|
||||
logger,
|
||||
kclient,
|
||||
[]schema.GroupVersionResource{
|
||||
monitoringv1.SchemeGroupVersion.WithResource(monitoringv1.ServiceMonitorName),
|
||||
monitoringv1.SchemeGroupVersion.WithResource(monitoringv1.PodMonitorName),
|
||||
monitoringv1.SchemeGroupVersion.WithResource(monitoringv1.ProbeName),
|
||||
},
|
||||
) {
|
||||
cancel()
|
||||
return 1
|
||||
}
|
||||
|
||||
promAgentControllerOptions = append(promAgentControllerOptions, prometheusagentcontroller.WithConfigResourceStatus())
|
||||
}
|
||||
|
||||
pao, err = prometheusagentcontroller.New(ctx, restConfig, cfg, logger, r, promAgentControllerOptions...)
|
||||
if err != nil {
|
||||
logger.Error("instantiating prometheus-agent controller failed", "err", err)
|
||||
@@ -489,6 +567,11 @@ func run(fs *flag.FlagSet) int {
|
||||
|
||||
var ao *alertmanagercontroller.Operator
|
||||
if alertmanagerSupported {
|
||||
if cfg.Gates.Enabled(operator.StatusForConfigurationResourcesFeature) {
|
||||
// TODO: check permissions when implementing the AlertmanagerConfig status subresource.
|
||||
alertmanagerControllerOptions = append(alertmanagerControllerOptions, alertmanagercontroller.WithConfigResourceStatus())
|
||||
}
|
||||
|
||||
ao, err = alertmanagercontroller.New(ctx, restConfig, cfg, logger, r, alertmanagerControllerOptions...)
|
||||
if err != nil {
|
||||
logger.Error("instantiating alertmanager controller failed", "err", err)
|
||||
@@ -525,6 +608,22 @@ func run(fs *flag.FlagSet) int {
|
||||
|
||||
var to *thanoscontroller.Operator
|
||||
if thanosRulerSupported {
|
||||
if cfg.Gates.Enabled(operator.StatusForConfigurationResourcesFeature) {
|
||||
if !checkStatusSubresourcePermissions(
|
||||
ctx,
|
||||
logger,
|
||||
kclient,
|
||||
[]schema.GroupVersionResource{
|
||||
monitoringv1.SchemeGroupVersion.WithResource(monitoringv1.PrometheusRuleName),
|
||||
},
|
||||
) {
|
||||
cancel()
|
||||
return 1
|
||||
}
|
||||
|
||||
thanosControllerOptions = append(thanosControllerOptions, thanoscontroller.WithConfigResourceStatus())
|
||||
}
|
||||
|
||||
to, err = thanoscontroller.New(ctx, restConfig, cfg, logger, r, thanosControllerOptions...)
|
||||
if err != nil {
|
||||
logger.Error("instantiating thanos controller failed", "err", err)
|
||||
|
||||
@@ -121,6 +121,14 @@ func WithStorageClassValidation() ControllerOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithConfigResourceStatus tells that the controller can manage the status of
|
||||
// configuration resources.
|
||||
func WithConfigResourceStatus() ControllerOption {
|
||||
return func(o *Operator) {
|
||||
o.configResourcesStatusEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
// New creates a new controller.
|
||||
func New(ctx context.Context, restConfig *rest.Config, c operator.Config, logger *slog.Logger, r prometheus.Registerer, options ...ControllerOption) (*Operator, error) {
|
||||
logger = logger.With("component", controllerName)
|
||||
@@ -166,7 +174,6 @@ func New(ctx context.Context, restConfig *rest.Config, c operator.Config, logger
|
||||
Annotations: c.Annotations,
|
||||
Labels: c.Labels,
|
||||
},
|
||||
configResourcesStatusEnabled: c.Gates.Enabled(operator.StatusForConfigurationResourcesFeature),
|
||||
}
|
||||
for _, opt := range options {
|
||||
opt(o)
|
||||
|
||||
@@ -29,20 +29,21 @@ import (
|
||||
// FinalizerSyncer holds the configuration and dependencies
|
||||
// required to perform finalizer synchronization.
|
||||
type FinalizerSyncer struct {
|
||||
mdClient metadata.Interface
|
||||
gvr schema.GroupVersionResource
|
||||
configResourcesStatusEnabled bool
|
||||
mdClient metadata.Interface
|
||||
gvr schema.GroupVersionResource
|
||||
disabled bool
|
||||
}
|
||||
|
||||
func NewFinalizerSyncer(
|
||||
mdClient metadata.Interface,
|
||||
gvr schema.GroupVersionResource,
|
||||
configResourcesStatusEnabled bool,
|
||||
) *FinalizerSyncer {
|
||||
func NewFinalizerSyncer(mdClient metadata.Interface, gvr schema.GroupVersionResource) *FinalizerSyncer {
|
||||
return &FinalizerSyncer{
|
||||
mdClient: mdClient,
|
||||
gvr: gvr,
|
||||
configResourcesStatusEnabled: configResourcesStatusEnabled,
|
||||
mdClient: mdClient,
|
||||
gvr: gvr,
|
||||
}
|
||||
}
|
||||
|
||||
func NewNoopFinalizerSyncer() *FinalizerSyncer {
|
||||
return &FinalizerSyncer{
|
||||
disabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +53,7 @@ func NewFinalizerSyncer(
|
||||
// Returns true if the finalizer was added, otherwise false.
|
||||
// The second return value indicates any error encountered during the operation.
|
||||
func (s *FinalizerSyncer) Sync(ctx context.Context, p metav1.Object, deletionInProgress bool, statusCleanup func() error) (bool, error) {
|
||||
if !s.configResourcesStatusEnabled {
|
||||
if s.disabled {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -123,6 +123,14 @@ func WithStorageClassValidation() ControllerOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithConfigResourceStatus tells that the controller can manage the status of
|
||||
// configuration resources.
|
||||
func WithConfigResourceStatus() ControllerOption {
|
||||
return func(o *Operator) {
|
||||
o.configResourcesStatusEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
// New creates a new controller.
|
||||
func New(ctx context.Context, restConfig *rest.Config, c operator.Config, logger *slog.Logger, r prometheus.Registerer, options ...ControllerOption) (*Operator, error) {
|
||||
logger = logger.With("component", controllerName)
|
||||
@@ -163,7 +171,7 @@ func New(ctx context.Context, restConfig *rest.Config, c operator.Config, logger
|
||||
controllerID: c.ControllerID,
|
||||
newEventRecorder: c.EventRecorderFactory(client, controllerName),
|
||||
configResourcesStatusEnabled: c.Gates.Enabled(operator.StatusForConfigurationResourcesFeature),
|
||||
finalizerSyncer: operator.NewFinalizerSyncer(mdClient, monitoringv1alpha1.SchemeGroupVersion.WithResource(monitoringv1alpha1.PrometheusAgentName), c.Gates.Enabled(operator.StatusForConfigurationResourcesFeature)),
|
||||
finalizerSyncer: operator.NewNoopFinalizerSyncer(),
|
||||
}
|
||||
o.metrics.MustRegister(
|
||||
o.reconciliations,
|
||||
@@ -172,6 +180,10 @@ func New(ctx context.Context, restConfig *rest.Config, c operator.Config, logger
|
||||
opt(o)
|
||||
}
|
||||
|
||||
if o.configResourcesStatusEnabled {
|
||||
o.finalizerSyncer = operator.NewFinalizerSyncer(mdClient, monitoringv1alpha1.SchemeGroupVersion.WithResource(monitoringv1alpha1.PrometheusAgentName))
|
||||
}
|
||||
|
||||
o.promInfs, err = informers.NewInformersForResource(
|
||||
informers.NewMonitoringInformerFactories(
|
||||
c.Namespaces.PrometheusAllowList,
|
||||
|
||||
@@ -144,6 +144,14 @@ func WithoutUnmanagedConfiguration() ControllerOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithConfigResourceStatus tells that the controller can manage the status of
|
||||
// configuration resources.
|
||||
func WithConfigResourceStatus() ControllerOption {
|
||||
return func(o *Operator) {
|
||||
o.configResourcesStatusEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
// New creates a new controller.
|
||||
func New(ctx context.Context, restConfig *rest.Config, c operator.Config, logger *slog.Logger, r prometheus.Registerer, opts ...ControllerOption) (*Operator, error) {
|
||||
logger = logger.With("component", controllerName)
|
||||
@@ -190,16 +198,19 @@ func New(ctx context.Context, restConfig *rest.Config, c operator.Config, logger
|
||||
metrics: operator.NewMetrics(r),
|
||||
reconciliations: &operator.ReconciliationTracker{},
|
||||
|
||||
controllerID: c.ControllerID,
|
||||
newEventRecorder: c.EventRecorderFactory(client, controllerName),
|
||||
retentionPoliciesEnabled: c.Gates.Enabled(operator.PrometheusShardRetentionPolicyFeature),
|
||||
configResourcesStatusEnabled: c.Gates.Enabled(operator.StatusForConfigurationResourcesFeature),
|
||||
finalizerSyncer: operator.NewFinalizerSyncer(mdClient, monitoringv1.SchemeGroupVersion.WithResource(monitoringv1.PrometheusName), c.Gates.Enabled(operator.StatusForConfigurationResourcesFeature)),
|
||||
controllerID: c.ControllerID,
|
||||
newEventRecorder: c.EventRecorderFactory(client, controllerName),
|
||||
retentionPoliciesEnabled: c.Gates.Enabled(operator.PrometheusShardRetentionPolicyFeature),
|
||||
finalizerSyncer: operator.NewNoopFinalizerSyncer(),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(o)
|
||||
}
|
||||
|
||||
if o.configResourcesStatusEnabled {
|
||||
o.finalizerSyncer = operator.NewFinalizerSyncer(mdClient, monitoringv1.SchemeGroupVersion.WithResource(monitoringv1.PrometheusName))
|
||||
}
|
||||
|
||||
o.metrics.MustRegister(o.reconciliations)
|
||||
|
||||
o.promInfs, err = informers.NewInformersForResource(
|
||||
|
||||
@@ -112,6 +112,14 @@ func WithStorageClassValidation() ControllerOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithConfigResourceStatus tells that the controller can manage the status of
|
||||
// configuration resources.
|
||||
func WithConfigResourceStatus() ControllerOption {
|
||||
return func(o *Operator) {
|
||||
o.configResourcesStatusEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
// New creates a new controller.
|
||||
func New(ctx context.Context, restConfig *rest.Config, c operator.Config, logger *slog.Logger, r prometheus.Registerer, options ...ControllerOption) (*Operator, error) {
|
||||
logger = logger.With("component", controllerName)
|
||||
@@ -151,7 +159,6 @@ func New(ctx context.Context, restConfig *rest.Config, c operator.Config, logger
|
||||
Labels: c.Labels,
|
||||
LocalHost: c.LocalHost,
|
||||
},
|
||||
configResourcesStatusEnabled: c.Gates.Enabled(operator.StatusForConfigurationResourcesFeature),
|
||||
}
|
||||
for _, opt := range options {
|
||||
opt(o)
|
||||
|
||||
Reference in New Issue
Block a user