Skip to content

Commit 437adf7

Browse files
Merge pull request #2604 from machine424/nope
OCPBUGS-18282: prevent use of reserved labels keys in Prometheus externalLabels
2 parents 85576cf + 3c35f55 commit 437adf7

File tree

6 files changed

+101
-7
lines changed

6 files changed

+101
-7
lines changed

Documentation/api.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ The `PrometheusK8sConfig` resource defines settings for the Prometheus component
424424
| -------- | ---- | ----------- |
425425
| additionalAlertmanagerConfigs | [][AdditionalAlertmanagerConfig](#additionalalertmanagerconfig) | Configures additional Alertmanager instances that receive alerts from the Prometheus component. By default, no additional Alertmanager instances are configured. |
426426
| enforcedBodySizeLimit | string | Enforces a body size limit for Prometheus scraped metrics. If a scraped target's body response is larger than the limit, the scrape will fail. The following values are valid: an empty value to specify no limit, a numeric value in Prometheus size format (such as `64MB`), or the string `automatic`, which indicates that the limit will be automatically calculated based on cluster capacity. The default value is empty, which indicates no limit. |
427-
| externalLabels | map[string]string | Defines labels to be added to any time series or alerts when communicating with external systems such as federation, remote storage, and Alertmanager. By default, no labels are added. |
427+
| externalLabels | ExternalLabels | Defines labels to be added to any time series or alerts when communicating with external systems such as federation, remote storage, and Alertmanager. By default, no labels are added. |
428428
| logLevel | string | Defines the log level setting for Prometheus. The possible values are: `error`, `warn`, `info`, and `debug`. The default value is `info`. |
429429
| nodeSelector | map[string]string | Defines the nodes on which the pods are scheduled. |
430430
| queryLogFile | string | Specifies the file to which PromQL queries are logged. This setting can be either a filename, in which case the queries are saved to an `emptyDir` volume at `/var/log/prometheus`, or a full path to a location where an `emptyDir` volume will be mounted and the queries saved. Writing to `/dev/stderr`, `/dev/stdout` or `/dev/null` is supported, but writing to any other `/dev/` path is not supported. Relative paths are also not supported. By default, PromQL queries are not logged. |
@@ -493,7 +493,7 @@ The `PrometheusRestrictedConfig` resource defines the settings for the Prometheu
493493
| enforcedLabelValueLengthLimit | *uint64 | Specifies a per-scrape limit on the length of a label value for a sample. If the length of a label value exceeds this limit after metric relabeling, the entire scrape is treated as failed. The default value is `0`, which means that no limit is set. |
494494
| enforcedSampleLimit | *uint64 | Specifies a global limit on the number of scraped samples that will be accepted. This setting overrides the `SampleLimit` value set in any user-defined `ServiceMonitor` or `PodMonitor` object if the value is greater than `enforcedTargetLimit`. Administrators can use this setting to keep the overall number of samples under control. The default value is `0`, which means that no limit is set. |
495495
| enforcedTargetLimit | *uint64 | Specifies a global limit on the number of scraped targets. This setting overrides the `TargetLimit` value set in any user-defined `ServiceMonitor` or `PodMonitor` object if the value is greater than `enforcedSampleLimit`. Administrators can use this setting to keep the overall number of targets under control. The default value is `0`. |
496-
| externalLabels | map[string]string | Defines labels to be added to any time series or alerts when communicating with external systems such as federation, remote storage, and Alertmanager. By default, no labels are added. |
496+
| externalLabels | ExternalLabels | Defines labels to be added to any time series or alerts when communicating with external systems such as federation, remote storage, and Alertmanager. By default, no labels are added. |
497497
| logLevel | string | Defines the log level setting for Prometheus. The possible values are `error`, `warn`, `info`, and `debug`. The default setting is `info`. |
498498
| nodeSelector | map[string]string | Defines the nodes on which the pods are scheduled. |
499499
| queryLogFile | string | Specifies the file to which PromQL queries are logged. This setting can be either a filename, in which case the queries are saved to an `emptyDir` volume at `/var/log/prometheus`, or a full path to a location where an `emptyDir` volume will be mounted and the queries saved. Writing to `/dev/stderr`, `/dev/stdout` or `/dev/null` is supported, but writing to any other `/dev/` path is not supported. Relative paths are also not supported. By default, PromQL queries are not logged. |

Documentation/openshiftdocs/modules/prometheusk8sconfig.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Appears in: link:clustermonitoringconfiguration.adoc[ClusterMonitoringConfigurat
2222

2323
|enforcedBodySizeLimit|string|Enforces a body size limit for Prometheus scraped metrics. If a scraped target's body response is larger than the limit, the scrape will fail. The following values are valid: an empty value to specify no limit, a numeric value in Prometheus size format (such as `64MB`), or the string `automatic`, which indicates that the limit will be automatically calculated based on cluster capacity. The default value is empty, which indicates no limit.
2424

25-
|externalLabels|map[string]string|Defines labels to be added to any time series or alerts when communicating with external systems such as federation, remote storage, and Alertmanager. By default, no labels are added.
25+
|externalLabels|ExternalLabels|Defines labels to be added to any time series or alerts when communicating with external systems such as federation, remote storage, and Alertmanager. By default, no labels are added.
2626

2727
|logLevel|string|Defines the log level setting for Prometheus. The possible values are: `error`, `warn`, `info`, and `debug`. The default value is `info`.
2828

Documentation/openshiftdocs/modules/prometheusrestrictedconfig.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Appears in: link:userworkloadconfiguration.adoc[UserWorkloadConfiguration]
3434

3535
|enforcedTargetLimit|*uint64|Specifies a global limit on the number of scraped targets. This setting overrides the `TargetLimit` value set in any user-defined `ServiceMonitor` or `PodMonitor` object if the value is greater than `enforcedSampleLimit`. Administrators can use this setting to keep the overall number of targets under control. The default value is `0`.
3636

37-
|externalLabels|map[string]string|Defines labels to be added to any time series or alerts when communicating with external systems such as federation, remote storage, and Alertmanager. By default, no labels are added.
37+
|externalLabels|ExternalLabels|Defines labels to be added to any time series or alerts when communicating with external systems such as federation, remote storage, and Alertmanager. By default, no labels are added.
3838

3939
|logLevel|string|Defines the log level setting for Prometheus. The possible values are `error`, `warn`, `info`, and `debug`. The default setting is `info`.
4040

pkg/manifests/config.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ const (
5454
)
5555

5656
var errAlertmanagerV1NotSupported = errors.New("alertmanager's apiVersion=v1 is no longer supported, v2 has been available since Alertmanager 0.16.0")
57+
var reservedPrometheusExternalLabels = []string{"prometheus", "prometheus_replica", "cluster", "managed_cluster"}
5758

5859
type Config struct {
5960
Images *Images `json:"-"`
@@ -756,3 +757,17 @@ func NewDefaultUserWorkloadMonitoringConfig() *UserWorkloadConfiguration {
756757
u.applyDefaults()
757758
return u
758759
}
760+
761+
func (lb *ExternalLabels) UnmarshalJSON(data []byte) error {
762+
var v map[string]string
763+
if err := json.Unmarshal(data, &v); err != nil {
764+
return err
765+
}
766+
for _, r := range reservedPrometheusExternalLabels {
767+
if _, ok := v[r]; ok {
768+
return fmt.Errorf("reserved keys %v cannot be set as external labels", reservedPrometheusExternalLabels)
769+
}
770+
}
771+
*lb = v
772+
return nil
773+
}

pkg/manifests/manifests_test.go

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1665,7 +1665,10 @@ func TestPrometheusUserWorkloadConfiguration(t *testing.T) {
16651665
whenUnsatisfiable: DoNotSchedule
16661666
labelSelector:
16671667
matchLabels:
1668-
foo: bar`)
1668+
foo: bar
1669+
externalLabels:
1670+
foo: bar
1671+
oof: rab`)
16691672

16701673
c.UserWorkloadConfiguration = uwc
16711674
if err != nil {
@@ -1724,6 +1727,8 @@ func TestPrometheusUserWorkloadConfiguration(t *testing.T) {
17241727
require.Len(t, p.Spec.ScrapeClasses, 1)
17251728
require.Equal(t, p.Spec.ScrapeClasses[0].Default, ptr.To(true))
17261729
require.Equal(t, p.Spec.ScrapeClasses[0].FallbackScrapeProtocol, ptr.To(monv1.PrometheusText1_0_0))
1730+
1731+
require.Equal(t, p.Spec.ExternalLabels, map[string]string{"foo": "bar", "oof": "rab"})
17271732
}
17281733

17291734
func TestPrometheusQueryLogFileConfig(t *testing.T) {
@@ -5205,3 +5210,76 @@ func TestSetTLSSecurityConfiguration(t *testing.T) {
52055210
})
52065211
}
52075212
}
5213+
5214+
func TestPromConfigurationExternalLabels(t *testing.T) {
5215+
for _, p := range []struct {
5216+
promFieldName string
5217+
parser func(string) error
5218+
}{
5219+
// platform and UWM
5220+
{promFieldName: "prometheusK8s", parser: func(s string) error {
5221+
_, err := NewConfigFromString(s, false)
5222+
return err
5223+
}},
5224+
{promFieldName: "prometheus", parser: func(s string) error {
5225+
_, err := NewUserConfigFromString(s)
5226+
return err
5227+
}},
5228+
} {
5229+
t.Run(p.promFieldName, func(t *testing.T) {
5230+
for _, tc := range []struct {
5231+
name string
5232+
template string
5233+
shouldFail bool
5234+
}{
5235+
{
5236+
name: "all reserved labels",
5237+
template: `%s:
5238+
externalLabels:
5239+
prometheus: foo
5240+
prometheus_replica: bar
5241+
`,
5242+
shouldFail: true,
5243+
},
5244+
{
5245+
name: "no reserved",
5246+
template: `%s:
5247+
externalLabels:
5248+
foo: bar
5249+
bar: foo
5250+
`,
5251+
},
5252+
{
5253+
name: "one reserved",
5254+
template: `%s:
5255+
externalLabels:
5256+
cluster: bar
5257+
bar: foo
5258+
`,
5259+
shouldFail: true,
5260+
},
5261+
{
5262+
name: "one rempty reserved",
5263+
template: `%s:
5264+
externalLabels:
5265+
managed_cluster:
5266+
bar: foo
5267+
`,
5268+
shouldFail: true,
5269+
},
5270+
} {
5271+
t.Run(tc.name, func(t *testing.T) {
5272+
config := fmt.Sprintf(tc.template, p.promFieldName)
5273+
err := p.parser(config)
5274+
if tc.shouldFail {
5275+
require.Error(t, err)
5276+
// Ensure we’re testing what we intend.
5277+
require.ErrorContains(t, err, "cannot be set as external labels")
5278+
return
5279+
}
5280+
require.NoError(t, err)
5281+
})
5282+
}
5283+
})
5284+
}
5285+
}

pkg/manifests/types.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
type CollectionProfile string
2323
type CollectionProfiles []CollectionProfile
24+
type ExternalLabels map[string]string
2425

2526
const (
2627
FullCollectionProfile = "full"
@@ -195,7 +196,7 @@ type PrometheusK8sConfig struct {
195196
// Defines labels to be added to any time series or alerts when
196197
// communicating with external systems such as federation, remote storage,
197198
// and Alertmanager. By default, no labels are added.
198-
ExternalLabels map[string]string `json:"externalLabels,omitempty"`
199+
ExternalLabels ExternalLabels `json:"externalLabels,omitempty"`
199200
// Defines the log level setting for Prometheus.
200201
// The possible values are: `error`, `warn`, `info`, and `debug`.
201202
// The default value is `info`.
@@ -659,7 +660,7 @@ type PrometheusRestrictedConfig struct {
659660
// communicating with external systems such as federation, remote storage,
660661
// and Alertmanager.
661662
// By default, no labels are added.
662-
ExternalLabels map[string]string `json:"externalLabels,omitempty"`
663+
ExternalLabels ExternalLabels `json:"externalLabels,omitempty"`
663664
// Defines the log level setting for Prometheus.
664665
// The possible values are `error`, `warn`, `info`, and `debug`.
665666
// The default setting is `info`.

0 commit comments

Comments
 (0)