Skip to content

Commit ca92ea3

Browse files
committed
MON-3701: clean-up trusted CA bundle for Alertmanager
CMO needed to inject the hashed version of the trusted CA bundle ConfigMap into the Alertmanager resource when OAuth proxy was used because it couldn't detect updates to the bundle and reload it. The trusted CA bundle is still required to be mounted into the pod for the Alertmanager container but it is declared directly in the static manifest instead of being injected at runtime by CMO since Alertmanager reloads the CA whenever it changes. Signed-off-by: Simon Pasquier <[email protected]>
1 parent bf04aae commit ca92ea3

File tree

7 files changed

+55
-75
lines changed

7 files changed

+55
-75
lines changed

assets/alertmanager/alertmanager.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,19 @@ spec:
143143
runAsUser: 65534
144144
serviceAccountName: alertmanager-main
145145
version: 0.26.0
146+
volumeMounts:
147+
- mountPath: /etc/pki/ca-trust/extracted/pem/
148+
name: alertmanager-trusted-ca-bundle
146149
volumes:
147150
- configMap:
148151
name: metrics-client-ca
149152
name: metrics-client-ca
153+
- configMap:
154+
items:
155+
- key: ca-bundle.crt
156+
path: tls-ca-bundle.pem
157+
name: alertmanager-trusted-ca-bundle
158+
name: alertmanager-trusted-ca-bundle
150159
web:
151160
httpConfig:
152161
headers:

jsonnet/components/alertmanager.libsonnet

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ function(params)
1616
trustedCaBundle: generateCertInjection.trustedCNOCaBundleCM(cfg.namespace, 'alertmanager-trusted-ca-bundle'),
1717

1818
// OpenShift route to access the Alertmanager UI.
19-
2019
route: {
2120
apiVersion: 'v1',
2221
kind: 'Route',
@@ -411,6 +410,22 @@ function(params)
411410
name: 'metrics-client-ca',
412411
},
413412
},
413+
{
414+
name: $.trustedCaBundle.metadata.name,
415+
configMap: {
416+
name: $.trustedCaBundle.metadata.name,
417+
items: [{
418+
key: 'ca-bundle.crt',
419+
path: 'tls-ca-bundle.pem',
420+
}],
421+
},
422+
},
423+
],
424+
volumeMounts+: [
425+
{
426+
name: $.trustedCaBundle.metadata.name,
427+
mountPath: '/etc/pki/ca-trust/extracted/pem/',
428+
},
414429
],
415430
},
416431
},

jsonnet/utils/generate-certificate-injection.libsonnet

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
},
1616
data: {},
1717
},
18+
1819
// This CA bundle is injected by the service-ca-operator.
1920
SCOCaBundleCM(cfgNamespace, cfgName):: {
2021
apiVersion: 'v1',
@@ -28,6 +29,7 @@
2829
},
2930
data: {},
3031
},
32+
3133
SCOCaBundleVolume(volName):: {
3234
name: volName,
3335
configmap: {

pkg/manifests/manifests.go

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ func setupStartupProbe(a *monv1.Alertmanager) {
586586
)
587587
}
588588

589-
func (f *Factory) AlertmanagerMain(trustedCABundleCM *v1.ConfigMap) (*monv1.Alertmanager, error) {
589+
func (f *Factory) AlertmanagerMain() (*monv1.Alertmanager, error) {
590590
a, err := f.NewAlertmanager(f.assets.MustNewAssetSlice(AlertmanagerMain))
591591
if err != nil {
592592
return nil, err
@@ -651,18 +651,6 @@ func (f *Factory) AlertmanagerMain(trustedCABundleCM *v1.ConfigMap) (*monv1.Aler
651651
f.config.ClusterMonitoringConfiguration.AlertmanagerMainConfig.TopologySpreadConstraints
652652
}
653653

654-
if trustedCABundleCM != nil {
655-
volumeName := "alertmanager-trusted-ca-bundle"
656-
a.Spec.VolumeMounts = append(a.Spec.VolumeMounts, trustedCABundleVolumeMount(volumeName))
657-
658-
volume := trustedCABundleVolume(trustedCABundleCM.Name, volumeName)
659-
volume.VolumeSource.ConfigMap.Items = append(volume.VolumeSource.ConfigMap.Items, v1.KeyToPath{
660-
Key: TrustedCABundleKey,
661-
Path: "tls-ca-bundle.pem",
662-
})
663-
a.Spec.Volumes = append(a.Spec.Volumes, volume)
664-
}
665-
666654
for i, c := range a.Spec.Containers {
667655
switch c.Name {
668656
case "kube-rbac-proxy", "kube-rbac-proxy-metric", "kube-rbac-proxy-web":

pkg/manifests/manifests_test.go

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"fmt"
2121
"net/url"
2222
"reflect"
23+
"slices"
2324
"sort"
2425
"strings"
2526
"testing"
@@ -33,7 +34,6 @@ import (
3334
policyv1 "k8s.io/api/policy/v1"
3435
"k8s.io/apimachinery/pkg/api/resource"
3536
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
36-
"k8s.io/utils/strings/slices"
3737
)
3838

3939
type fakeInfrastructureReader struct {
@@ -251,7 +251,7 @@ func TestUnconfiguredManifests(t *testing.T) {
251251
t.Fatal(err)
252252
}
253253

254-
_, err = f.AlertmanagerMain(nil)
254+
_, err = f.AlertmanagerMain()
255255
if err != nil {
256256
t.Fatal(err)
257257
}
@@ -3041,9 +3041,7 @@ func TestAlertmanagerMainStartupProbe(t *testing.T) {
30413041
t.Fatal(err)
30423042
}
30433043
f := NewFactory("openshift-monitoring", "openshift-user-workload-monitoring", c, tc.infrastructure, &fakeProxyReader{}, NewAssets(assetsPath), &APIServerConfig{}, &configv1.Console{})
3044-
a, err := f.AlertmanagerMain(
3045-
&v1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "foo"}},
3046-
)
3044+
a, err := f.AlertmanagerMain()
30473045
if err != nil {
30483046
t.Fatal(err)
30493047
}
@@ -3115,9 +3113,7 @@ ingress:
31153113
})
31163114

31173115
f := NewFactory("openshift-monitoring", "openshift-user-workload-monitoring", c, defaultInfrastructureReader(), &fakeProxyReader{}, NewAssets(assetsPath), &APIServerConfig{}, &configv1.Console{Status: configv1.ConsoleStatus{ConsoleURL: "https://console-openshift-console.apps.foo.devcluster.openshift.com"}})
3118-
a, err := f.AlertmanagerMain(
3119-
&v1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "foo"}},
3120-
)
3116+
a, err := f.AlertmanagerMain()
31213117
if err != nil {
31223118
t.Fatal(err)
31233119
}
@@ -3241,6 +3237,17 @@ ingress:
32413237
}
32423238
}
32433239

3240+
if !slices.ContainsFunc(a.Spec.Volumes, func(v v1.Volume) bool {
3241+
return v.Name == "alertmanager-trusted-ca-bundle"
3242+
}) {
3243+
t.Fatalf("expected to find volume with name 'alertmanager-trusted-ca-bundle' but got none: %#v", a.Spec.Volumes)
3244+
}
3245+
3246+
if !slices.ContainsFunc(a.Spec.VolumeMounts, func(v v1.VolumeMount) bool {
3247+
return v.Name == "alertmanager-trusted-ca-bundle"
3248+
}) {
3249+
t.Fatalf("expected to find volume mount with name 'alertmanager-trusted-ca-bundle' but got none: %#v", a.Spec.VolumeMounts)
3250+
}
32443251
}
32453252

32463253
func TestAlertManagerUserWorkloadConfiguration(t *testing.T) {
@@ -4360,9 +4367,7 @@ func TestNonHighlyAvailableInfrastructure(t *testing.T) {
43604367
{
43614368
name: "Alertmanager",
43624369
getSpec: func(f *Factory) (spec, error) {
4363-
a, err := f.AlertmanagerMain(
4364-
&v1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "foo"}},
4365-
)
4370+
a, err := f.AlertmanagerMain()
43664371
if err != nil {
43674372
return spec{}, err
43684373
}

pkg/tasks/alertmanager.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -185,17 +185,12 @@ func (t *AlertmanagerTask) create(ctx context.Context) error {
185185
return fmt.Errorf("initializing Alertmanager CA bundle ConfigMap failed: %w", err)
186186
}
187187

188-
cbs := &caBundleSyncer{
189-
client: t.client,
190-
factory: t.factory,
191-
prefix: "alertmanager",
192-
}
193-
trustedCA, err = cbs.syncTrustedCABundle(ctx, trustedCA)
188+
err = t.client.CreateOrUpdateConfigMap(ctx, trustedCA)
194189
if err != nil {
195-
return fmt.Errorf("syncing Alertmanager trusted CA bundle ConfigMap failed: %w", err)
190+
return fmt.Errorf("reconciling Alertmanager trusted CA bundle ConfigMap failed: %w", err)
196191
}
197192

198-
a, err := t.factory.AlertmanagerMain(trustedCA)
193+
a, err := t.factory.AlertmanagerMain()
199194
if err != nil {
200195
return fmt.Errorf("initializing Alertmanager object failed: %w", err)
201196
}
@@ -239,6 +234,12 @@ func (t *AlertmanagerTask) create(ctx context.Context) error {
239234
return fmt.Errorf("deleting Alertmanager proxy Secret failed: %w", err)
240235
}
241236

237+
// TODO(simonpasquier): remove this step after OCP 4.16 is released.
238+
err = t.client.DeleteHashedConfigMap(ctx, "openshift-monitoring", "alertmanager-trusted-ca-bundle", "")
239+
if err != nil {
240+
return fmt.Errorf("deleting all hashed Alertmanager trusted CA bundle ConfigMap failed: %w", err)
241+
}
242+
242243
return nil
243244
}
244245

@@ -356,7 +357,7 @@ func (t *AlertmanagerTask) destroy(ctx context.Context) error {
356357
return fmt.Errorf("deleting Alertmanager trusted CA bundle failed: %w", err)
357358
}
358359

359-
a, err := t.factory.AlertmanagerMain(trustedCA)
360+
a, err := t.factory.AlertmanagerMain()
360361
if err != nil {
361362
return fmt.Errorf("initializing Alertmanager object failed: %w", err)
362363
}

test/e2e/alertmanager_test.go

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ import (
2222
"io"
2323
"net/http"
2424
"reflect"
25+
"slices"
2526
"testing"
2627
"time"
2728

2829
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
2930
monitoringv1beta1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1beta1"
30-
"k8s.io/utils/strings/slices"
3131

3232
"github.com/Jeffail/gabs/v2"
3333
statusv1 "github.com/openshift/api/config/v1"
@@ -39,46 +39,6 @@ import (
3939
"k8s.io/apimachinery/pkg/util/wait"
4040
)
4141

42-
func TestAlertmanagerTrustedCA(t *testing.T) {
43-
var (
44-
newCM *v1.ConfigMap
45-
lastErr error
46-
)
47-
48-
cm := f.MustGetConfigMap(t, "alertmanager-trusted-ca-bundle", f.Ns)
49-
newCM, err := f.ManifestsFactory.HashTrustedCA(cm, "alertmanager")
50-
if err != nil {
51-
t.Fatal(fmt.Errorf("no trusted CA bundle data available: %w", err))
52-
}
53-
54-
// Wait for the new hashed trusted CA bundle ConfigMap to be created
55-
f.AssertConfigmapExists(newCM.Name, f.Ns)(t)
56-
57-
// Get Alertmanager StatefulSet and make sure it has a volume mounted.
58-
err = wait.Poll(time.Second, 5*time.Minute, func() (bool, error) {
59-
ss := f.MustGetStatefulSet(t, "alertmanager-main", f.Ns)
60-
61-
if len(ss.Spec.Template.Spec.Containers[0].VolumeMounts) == 0 {
62-
return false, errors.New("Could not find any VolumeMounts, expected at least 1")
63-
}
64-
65-
for _, mount := range ss.Spec.Template.Spec.Containers[0].VolumeMounts {
66-
if mount.Name == "alertmanager-trusted-ca-bundle" {
67-
return true, nil
68-
}
69-
}
70-
71-
lastErr = fmt.Errorf("no volume %s mounted", newCM.Name)
72-
return false, nil
73-
})
74-
if err != nil {
75-
if err == wait.ErrWaitTimeout && lastErr != nil {
76-
err = lastErr
77-
}
78-
t.Fatal(err)
79-
}
80-
}
81-
8242
// TestAlertmanagerTenancyAPI ensures that the Alertmanager API exposed on the
8343
// tenancy port enforces the namespace value.
8444
func TestAlertmanagerTenancyAPI(t *testing.T) {

0 commit comments

Comments
 (0)