diff --git a/assets/admission-webhook/network-policy-downstream.yaml b/assets/admission-webhook/network-policy-downstream.yaml new file mode 100644 index 0000000000..5b6d24954c --- /dev/null +++ b/assets/admission-webhook/network-policy-downstream.yaml @@ -0,0 +1,21 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/part-of: openshift-monitoring + name: prometheus-operator-admission-webhook + namespace: openshift-monitoring +spec: + egress: + - {} + ingress: + - ports: + - port: https + protocol: TCP + podSelector: + matchLabels: + app.kubernetes.io/name: prometheus-operator-admission-webhook + policyTypes: + - Ingress + - Egress diff --git a/assets/alertmanager/network-policy-downstream.yaml b/assets/alertmanager/network-policy-downstream.yaml new file mode 100644 index 0000000000..53a6f7470b --- /dev/null +++ b/assets/alertmanager/network-policy-downstream.yaml @@ -0,0 +1,25 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/part-of: openshift-monitoring + name: alertmanager + namespace: openshift-monitoring +spec: + egress: + - {} + ingress: + - ports: + - port: tenancy + protocol: TCP + - port: web + protocol: TCP + - port: metrics + protocol: TCP + podSelector: + matchLabels: + app.kubernetes.io/name: alertmanager + policyTypes: + - Ingress + - Egress diff --git a/assets/cluster-monitoring-operator/network-policy-default-deny.yaml b/assets/cluster-monitoring-operator/network-policy-default-deny.yaml new file mode 100644 index 0000000000..3e3155e338 --- /dev/null +++ b/assets/cluster-monitoring-operator/network-policy-default-deny.yaml @@ -0,0 +1,15 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/part-of: openshift-monitoring + name: deny-cluster-monitoring-operator-and-operands + namespace: openshift-monitoring +spec: + podSelector: + matchLabels: + app.kubernetes.io/part-of: openshift-monitoring + policyTypes: + - Ingress + - Egress diff --git a/assets/kube-state-metrics/network-policy-downstream.yaml b/assets/kube-state-metrics/network-policy-downstream.yaml new file mode 100644 index 0000000000..87a6ecd5f2 --- /dev/null +++ b/assets/kube-state-metrics/network-policy-downstream.yaml @@ -0,0 +1,23 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/part-of: openshift-monitoring + name: kube-state-metrics + namespace: openshift-monitoring +spec: + egress: + - {} + ingress: + - ports: + - port: https-main + protocol: TCP + - port: https-self + protocol: TCP + podSelector: + matchLabels: + app.kubernetes.io/name: kube-state-metrics + policyTypes: + - Ingress + - Egress diff --git a/assets/metrics-server/network-policy-downstream.yaml b/assets/metrics-server/network-policy-downstream.yaml new file mode 100644 index 0000000000..0a070f37f9 --- /dev/null +++ b/assets/metrics-server/network-policy-downstream.yaml @@ -0,0 +1,21 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/part-of: openshift-monitoring + name: metrics-server + namespace: openshift-monitoring +spec: + egress: + - {} + ingress: + - ports: + - port: https + protocol: TCP + podSelector: + matchLabels: + app.kubernetes.io/name: metrics-server + policyTypes: + - Ingress + - Egress diff --git a/assets/monitoring-plugin/network-policy-downstream.yaml b/assets/monitoring-plugin/network-policy-downstream.yaml new file mode 100644 index 0000000000..befeaf13ab --- /dev/null +++ b/assets/monitoring-plugin/network-policy-downstream.yaml @@ -0,0 +1,21 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/part-of: openshift-monitoring + name: monitoring-plugin + namespace: openshift-monitoring +spec: + egress: + - {} + ingress: + - ports: + - port: https + protocol: TCP + podSelector: + matchLabels: + app.kubernetes.io/name: monitoring-plugin + policyTypes: + - Ingress + - Egress diff --git a/assets/openshift-state-metrics/network-policy-downstream.yaml b/assets/openshift-state-metrics/network-policy-downstream.yaml new file mode 100644 index 0000000000..0541b2e6b0 --- /dev/null +++ b/assets/openshift-state-metrics/network-policy-downstream.yaml @@ -0,0 +1,23 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/part-of: openshift-monitoring + name: openshift-state-metrics + namespace: openshift-monitoring +spec: + egress: + - {} + ingress: + - ports: + - port: https-main + protocol: TCP + - port: https-self + protocol: TCP + podSelector: + matchLabels: + app.kubernetes.io/name: openshift-state-metrics + policyTypes: + - Ingress + - Egress diff --git a/assets/prometheus-k8s/network-policy-downstream.yaml b/assets/prometheus-k8s/network-policy-downstream.yaml new file mode 100644 index 0000000000..2b6d54a23c --- /dev/null +++ b/assets/prometheus-k8s/network-policy-downstream.yaml @@ -0,0 +1,21 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/part-of: openshift-monitoring + name: prometheus + namespace: openshift-monitoring +spec: + egress: + - {} + ingress: + - ports: + - port: grpc + protocol: TCP + podSelector: + matchLabels: + app.kubernetes.io/name: prometheus + policyTypes: + - Ingress + - Egress diff --git a/assets/prometheus-operator/network-policy-downstream.yaml b/assets/prometheus-operator/network-policy-downstream.yaml new file mode 100644 index 0000000000..c16376cc1e --- /dev/null +++ b/assets/prometheus-operator/network-policy-downstream.yaml @@ -0,0 +1,21 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/part-of: openshift-monitoring + name: prometheus-operator + namespace: openshift-monitoring +spec: + egress: + - {} + ingress: + - ports: + - port: https + protocol: TCP + podSelector: + matchLabels: + app.kubernetes.io/name: prometheus-operator + policyTypes: + - Ingress + - Egress diff --git a/assets/telemeter-client/network-policy-downstream.yaml b/assets/telemeter-client/network-policy-downstream.yaml new file mode 100644 index 0000000000..d0a6d74c22 --- /dev/null +++ b/assets/telemeter-client/network-policy-downstream.yaml @@ -0,0 +1,21 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/part-of: openshift-monitoring + name: telemeter-client + namespace: openshift-monitoring +spec: + egress: + - {} + ingress: + - ports: + - port: https + protocol: TCP + podSelector: + matchLabels: + app.kubernetes.io/name: telemeter-client + policyTypes: + - Ingress + - Egress diff --git a/assets/thanos-querier/network-policy-downstream.yaml b/assets/thanos-querier/network-policy-downstream.yaml new file mode 100644 index 0000000000..9389ed04f6 --- /dev/null +++ b/assets/thanos-querier/network-policy-downstream.yaml @@ -0,0 +1,21 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/part-of: openshift-monitoring + name: thanos-querier + namespace: openshift-monitoring +spec: + egress: + - {} + ingress: + - ports: + - port: tenancy + protocol: TCP + podSelector: + matchLabels: + app.kubernetes.io/name: thanos-query + policyTypes: + - Ingress + - Egress diff --git a/jsonnet/components/admission-webhook.libsonnet b/jsonnet/components/admission-webhook.libsonnet index 8235918f82..e9d6ede6e2 100644 --- a/jsonnet/components/admission-webhook.libsonnet +++ b/jsonnet/components/admission-webhook.libsonnet @@ -169,4 +169,38 @@ function(params) }, ], }, + networkPolicyDownstream: { + apiVersion: 'networking.k8s.io/v1', + kind: 'NetworkPolicy', + metadata: { + name: 'prometheus-operator-admission-webhook', + namespace: 'openshift-monitoring', + }, + spec: { + podSelector: { + matchLabels: { + 'app.kubernetes.io/name': 'prometheus-operator-admission-webhook', + }, + }, + policyTypes: [ + 'Ingress', + 'Egress', + ], + ingress: [ + { + ports: [ + { + // allow apiserver reach to prometheus-operator-admission-webhook + // 8443(port name: https) port to validate customresourcedefinitions + port: 'https', + protocol: 'TCP', + }, + ], + }, + ], + egress: [ + {}, + ], + }, + }, } diff --git a/jsonnet/components/alertmanager.libsonnet b/jsonnet/components/alertmanager.libsonnet index 91ce0bedbc..0dd0e836da 100644 --- a/jsonnet/components/alertmanager.libsonnet +++ b/jsonnet/components/alertmanager.libsonnet @@ -445,4 +445,48 @@ function(params) ], }, }, + networkPolicyDownstream: { + apiVersion: 'networking.k8s.io/v1', + kind: 'NetworkPolicy', + metadata: { + name: 'alertmanager', + namespace: cfg.namespace, + }, + spec: { + podSelector: { + matchLabels: { + 'app.kubernetes.io/name': 'alertmanager', + }, + }, + policyTypes: [ + 'Ingress', + 'Egress', + ], + ingress: [ + { + ports: [ + { + // allow access to the Alertmanager endpoints restricted to a given project, + // port number 9092(port name: tenancy) + port: 'tenancy', + protocol: 'TCP', + }, + { + // allow prometheus to sent alerts to alertmanager, port number 9095(port name: web) + port: 'web', + protocol: 'TCP', + }, + { + // allow prometheus to scrape alertmanager endpoint, port number 9097(port name: metrics) + port: 'metrics', + protocol: 'TCP', + }, + ], + }, + ], + egress: [ + {}, + ], + }, + }, } diff --git a/jsonnet/components/cluster-monitoring-operator.libsonnet b/jsonnet/components/cluster-monitoring-operator.libsonnet index c9d2b9b8f5..c4b785c68c 100644 --- a/jsonnet/components/cluster-monitoring-operator.libsonnet +++ b/jsonnet/components/cluster-monitoring-operator.libsonnet @@ -322,6 +322,11 @@ function(params) { resources: ['alertmanagers/api'], verbs: ['*'], }, + { + apiGroups: ['networking.k8s.io'], + resources: ['networkpolicies'], + verbs: ['create', 'get', 'list', 'watch', 'update', 'delete'], + }, ], }, @@ -566,4 +571,27 @@ function(params) { verbs: ['*'], }], }, + + // default deny all pods traffic for pods which controlled by cluster-monitoring-operator, + // so it won't block with any extra pods controlled by other operators that deployed under + // openshift-monitoring project, example issue: https://issues.redhat.com/browse/ROSA-634 + networkPolicyDefaultDeny: { + apiVersion: 'networking.k8s.io/v1', + kind: 'NetworkPolicy', + metadata: { + name: 'deny-cluster-monitoring-operator-and-operands', + namespace: cfg.namespace, + }, + spec: { + podSelector: { + matchLabels: { + 'app.kubernetes.io/part-of': 'openshift-monitoring', + }, + }, + policyTypes: [ + 'Ingress', + 'Egress', + ], + }, + }, } diff --git a/jsonnet/components/kube-state-metrics.libsonnet b/jsonnet/components/kube-state-metrics.libsonnet index 6e2876a2b3..41ba9e709f 100644 --- a/jsonnet/components/kube-state-metrics.libsonnet +++ b/jsonnet/components/kube-state-metrics.libsonnet @@ -312,4 +312,42 @@ function(params) }, customResourceStateConfigmap: crsConfig, + networkPolicyDownstream: { + apiVersion: 'networking.k8s.io/v1', + kind: 'NetworkPolicy', + metadata: { + name: 'kube-state-metrics', + namespace: cfg.namespace, + }, + spec: { + podSelector: { + matchLabels: { + 'app.kubernetes.io/name': 'kube-state-metrics', + }, + }, + policyTypes: [ + 'Ingress', + 'Egress', + ], + ingress: [ + { + ports: [ + // allow prometheus to scrape kube-state-metrics endpoints, + // 8443(port name: https-main)/9443(port name: https-self) ports + { + port: 'https-main', + protocol: 'TCP', + }, + { + port: 'https-self', + protocol: 'TCP', + }, + ], + }, + ], + egress: [ + {}, + ], + }, + }, } diff --git a/jsonnet/components/metrics-server.libsonnet b/jsonnet/components/metrics-server.libsonnet index fb57677fa8..a15b066734 100644 --- a/jsonnet/components/metrics-server.libsonnet +++ b/jsonnet/components/metrics-server.libsonnet @@ -373,4 +373,38 @@ function(params) { }, }, }, + networkPolicyDownstream: { + apiVersion: 'networking.k8s.io/v1', + kind: 'NetworkPolicy', + metadata: { + name: 'metrics-server', + namespace: cfg.namespace, + }, + spec: { + podSelector: { + matchLabels: { + 'app.kubernetes.io/name': 'metrics-server', + }, + }, + policyTypes: [ + 'Ingress', + 'Egress', + ], + ingress: [ + { + ports: [ + // make Metrics API available and allow prometheus to scrape metrics-server endpoint, + // 10250(port name: https) port + { + port: 'https', + protocol: 'TCP', + }, + ], + }, + ], + egress: [ + {}, + ], + }, + }, } diff --git a/jsonnet/components/monitoring-plugin.libsonnet b/jsonnet/components/monitoring-plugin.libsonnet index b5e4f83f6f..92f7aef2c8 100644 --- a/jsonnet/components/monitoring-plugin.libsonnet +++ b/jsonnet/components/monitoring-plugin.libsonnet @@ -225,4 +225,38 @@ function(params) }, // template }, // spec }, // deployment + networkPolicyDownstream: { + apiVersion: 'networking.k8s.io/v1', + kind: 'NetworkPolicy', + metadata: { + name: 'monitoring-plugin', + namespace: cfg.namespace, + }, + spec: { + podSelector: { + matchLabels: { + 'app.kubernetes.io/name': 'monitoring-plugin', + }, + }, + policyTypes: [ + 'Ingress', + 'Egress', + ], + ingress: [ + { + ports: [ + { + // expose 9443(port name: https) port for admin web console to load monitoring-plugin, + // then Observe menu would show + port: 'https', + protocol: 'TCP', + }, + ], + }, + ], + egress: [ + {}, + ], + }, + }, } diff --git a/jsonnet/components/node-exporter.libsonnet b/jsonnet/components/node-exporter.libsonnet index 526ba3b82c..2d496345cc 100644 --- a/jsonnet/components/node-exporter.libsonnet +++ b/jsonnet/components/node-exporter.libsonnet @@ -250,12 +250,14 @@ function(params) }, clusterRole+: { - rules+: [{ - apiGroups: ['security.openshift.io'], - resources: ['securitycontextconstraints'], - resourceNames: ['node-exporter'], - verbs: ['use'], - }], + rules+: [ + { + apiGroups: ['security.openshift.io'], + resources: ['securitycontextconstraints'], + resourceNames: ['node-exporter'], + verbs: ['use'], + }, + ], }, // This configures the kube-rbac-proxies to use the serving cert diff --git a/jsonnet/components/openshift-state-metrics.libsonnet b/jsonnet/components/openshift-state-metrics.libsonnet index 442f041dfc..911ff50200 100644 --- a/jsonnet/components/openshift-state-metrics.libsonnet +++ b/jsonnet/components/openshift-state-metrics.libsonnet @@ -97,5 +97,42 @@ function(params) { }, }, serviceMonitor: osm.openshiftStateMetrics.serviceMonitor, - + networkPolicyDownstream: { + apiVersion: 'networking.k8s.io/v1', + kind: 'NetworkPolicy', + metadata: { + name: 'openshift-state-metrics', + namespace: cfg.namespace, + }, + spec: { + podSelector: { + matchLabels: { + 'app.kubernetes.io/name': 'openshift-state-metrics', + }, + }, + policyTypes: [ + 'Ingress', + 'Egress', + ], + ingress: [ + { + ports: [ + // allow prometheus to scrape openshift-state-metrics endpoints, + // 8443(port name: https-main)/9443(port name: https-self) ports + { + port: 'https-main', + protocol: 'TCP', + }, + { + port: 'https-self', + protocol: 'TCP', + }, + ], + }, + ], + egress: [ + {}, + ], + }, + }, } diff --git a/jsonnet/components/prometheus-operator.libsonnet b/jsonnet/components/prometheus-operator.libsonnet index f6a5d2ae87..ecb81a97aa 100644 --- a/jsonnet/components/prometheus-operator.libsonnet +++ b/jsonnet/components/prometheus-operator.libsonnet @@ -178,4 +178,38 @@ function(params) ], }, }, + networkPolicyDownstream: { + apiVersion: 'networking.k8s.io/v1', + kind: 'NetworkPolicy', + metadata: { + name: 'prometheus-operator', + namespace: 'openshift-monitoring', + }, + spec: { + podSelector: { + matchLabels: { + 'app.kubernetes.io/name': 'prometheus-operator', + }, + }, + policyTypes: [ + 'Ingress', + 'Egress', + ], + ingress: [ + { + ports: [ + // allow prometheus-operator to watch resources and allow prometheus + // to scrape prometheus-operator endpoint, 8443(port name: https) port + { + port: 'https', + protocol: 'TCP', + }, + ], + }, + ], + egress: [ + {}, + ], + }, + }, } diff --git a/jsonnet/components/prometheus.libsonnet b/jsonnet/components/prometheus.libsonnet index b71d296e65..5feba48522 100644 --- a/jsonnet/components/prometheus.libsonnet +++ b/jsonnet/components/prometheus.libsonnet @@ -601,4 +601,37 @@ function(params) ], }, }, + networkPolicyDownstream: { + apiVersion: 'networking.k8s.io/v1', + kind: 'NetworkPolicy', + metadata: { + name: 'prometheus', + namespace: cfg.namespace, + }, + spec: { + podSelector: { + matchLabels: { + 'app.kubernetes.io/name': 'prometheus', + }, + }, + policyTypes: [ + 'Ingress', + 'Egress', + ], + ingress: [ + { + ports: [ + { + // allow prometheus to update endpoints(port number: 10901, port name: grpc) + port: 'grpc', + protocol: 'TCP', + }, + ], + }, + ], + egress: [ + {}, + ], + }, + }, } diff --git a/jsonnet/components/telemeter-client.libsonnet b/jsonnet/components/telemeter-client.libsonnet index 987126bfa5..bf6dfbe584 100644 --- a/jsonnet/components/telemeter-client.libsonnet +++ b/jsonnet/components/telemeter-client.libsonnet @@ -119,4 +119,38 @@ function(params) { }, trustedCaBundle: generateCertInjection.trustedCNOCaBundleCM(cfg.namespace, 'telemeter-trusted-ca-bundle'), + networkPolicyDownstream: { + apiVersion: 'networking.k8s.io/v1', + kind: 'NetworkPolicy', + metadata: { + name: 'telemeter-client', + namespace: cfg.namespace, + }, + spec: { + podSelector: { + matchLabels: { + 'app.kubernetes.io/name': 'telemeter-client', + }, + }, + policyTypes: [ + 'Ingress', + 'Egress', + ], + ingress: [ + { + ports: [ + { + // allow prometheus to scrape telemeter-client endpoint, + // 8443(port name: https) port + port: 'https', + protocol: 'TCP', + }, + ], + }, + ], + egress: [ + {}, + ], + }, + }, } diff --git a/jsonnet/components/thanos-querier.libsonnet b/jsonnet/components/thanos-querier.libsonnet index 15e1020772..bd4900a11b 100644 --- a/jsonnet/components/thanos-querier.libsonnet +++ b/jsonnet/components/thanos-querier.libsonnet @@ -650,5 +650,39 @@ function(params) }, }, - + networkPolicyDownstream: { + apiVersion: 'networking.k8s.io/v1', + kind: 'NetworkPolicy', + metadata: { + name: 'thanos-querier', + namespace: cfg.namespace, + }, + spec: { + podSelector: { + matchLabels: { + 'app.kubernetes.io/name': 'thanos-query', + }, + }, + policyTypes: [ + 'Ingress', + 'Egress', + ], + ingress: [ + { + ports: [ + // allow for thanos-querier tenancy endpoint, 9092 port(port name: tenancy), + // for example, expose tenancy-aware /api/v1/labels for thanos query, + // load metrics result on admin web UI + { + port: 'tenancy', + protocol: 'TCP', + }, + ], + }, + ], + egress: [ + {}, + ], + }, + }, } diff --git a/manifests/0000_50_cluster-monitoring-operator_02-namespaced-cluster-role.yaml b/manifests/0000_50_cluster-monitoring-operator_02-namespaced-cluster-role.yaml index 6054a6826c..d576549360 100644 --- a/manifests/0000_50_cluster-monitoring-operator_02-namespaced-cluster-role.yaml +++ b/manifests/0000_50_cluster-monitoring-operator_02-namespaced-cluster-role.yaml @@ -73,3 +73,14 @@ rules: - alertmanagers/api verbs: - '*' +- apiGroups: + - networking.k8s.io + resources: + - networkpolicies + verbs: + - create + - get + - list + - watch + - update + - delete diff --git a/manifests/0000_50_cluster-monitoring-operator_04-networkpolicy.yaml b/manifests/0000_50_cluster-monitoring-operator_04-networkpolicy.yaml new file mode 100644 index 0000000000..a6a7635873 --- /dev/null +++ b/manifests/0000_50_cluster-monitoring-operator_04-networkpolicy.yaml @@ -0,0 +1,28 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + annotations: + include.release.openshift.io/hypershift: "true" + include.release.openshift.io/ibm-cloud-managed: "true" + include.release.openshift.io/self-managed-high-availability: "true" + include.release.openshift.io/single-node-developer: "true" + labels: + app.kubernetes.io/managed-by: cluster-version-operator + app.kubernetes.io/part-of: openshift-monitoring + name: cluster-monitoring-operator + namespace: openshift-monitoring +spec: + egress: + - {} + ingress: + - ports: + # allow cluster-monitoring-operator to deploy individual component and allow prometheus + # to scrape cluster-monitoring-operator endpoint, 8443(port name: https) port + - port: https + protocol: TCP + podSelector: + matchLabels: + app.kubernetes.io/name: cluster-monitoring-operator + policyTypes: + - Ingress + - Egress diff --git a/pkg/client/client.go b/pkg/client/client.go index e9058276f3..827da65d7b 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -44,6 +44,7 @@ import ( admissionv1 "k8s.io/api/admissionregistration/v1" appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" policyv1 "k8s.io/api/policy/v1" rbacv1 "k8s.io/api/rbac/v1" extensionsobj "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -808,6 +809,20 @@ func (c *Client) DeletePodDisruptionBudget(ctx context.Context, pdb *policyv1.Po return err } +func (c *Client) DeleteNetworkPolicy(ctx context.Context, netpol *networkingv1.NetworkPolicy) error { + _, err := c.kclient.NetworkingV1().NetworkPolicies(netpol.GetNamespace()).Get(ctx, netpol.GetName(), metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + return nil + } + + err = c.kclient.NetworkingV1().NetworkPolicies(netpol.GetNamespace()).Delete(ctx, netpol.GetName(), metav1.DeleteOptions{}) + if apierrors.IsNotFound(err) { + return nil + } + + return err +} + func (c *Client) DeletePrometheus(ctx context.Context, p *monv1.Prometheus) error { return c.deleteResourceUntilGone(ctx, monv1.SchemeGroupVersion.WithResource("prometheuses"), p, deleteTimeout) } @@ -1585,6 +1600,11 @@ func (c *Client) CreateOrUpdatePodDisruptionBudget(ctx context.Context, pdb *pol return err } +func (c *Client) CreateOrUpdateNetworkPolicy(ctx context.Context, netpol *networkingv1.NetworkPolicy) error { + _, _, err := resourceapply.ApplyNetworkPolicy(ctx, c.kclient.NetworkingV1(), c.eventRecorder, netpol, c.resourceCache) + return err +} + func (c *Client) CreateOrUpdateService(ctx context.Context, svc *v1.Service) error { _, _, err := resourceapply.ApplyService(ctx, c.kclient.CoreV1(), c.eventRecorder, svc) return err diff --git a/pkg/manifests/manifests.go b/pkg/manifests/manifests.go index bdafb7d1d4..73be27901c 100644 --- a/pkg/manifests/manifests.go +++ b/pkg/manifests/manifests.go @@ -43,6 +43,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" policyv1 "k8s.io/api/policy/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -95,6 +96,7 @@ var ( AlertmanagerTrustedCABundle = "alertmanager/trusted-ca-bundle.yaml" AlertmanagerPrometheusRule = "alertmanager/prometheus-rule.yaml" AlertmanagerPodDisruptionBudget = "alertmanager/pod-disruption-budget.yaml" + AlertmanagerNetworkPolicy = "alertmanager/network-policy-downstream.yaml" AlertmanagerUserWorkloadSecret = "alertmanager-user-workload/secret.yaml" AlertmanagerUserWorkloadService = "alertmanager-user-workload/service.yaml" @@ -119,6 +121,7 @@ var ( KubeStateMetricsPrometheusRule = "kube-state-metrics/prometheus-rule.yaml" KubeStateMetricsKubeRbacProxySecret = "kube-state-metrics/kube-rbac-proxy-secret.yaml" KubeStateMetricsCRSConfig = "kube-state-metrics/custom-resource-state-configmap.yaml" + KubeStateMetricsNetworkPolicy = "kube-state-metrics/network-policy-downstream.yaml" OpenShiftStateMetricsClusterRoleBinding = "openshift-state-metrics/cluster-role-binding.yaml" OpenShiftStateMetricsClusterRole = "openshift-state-metrics/cluster-role.yaml" @@ -127,6 +130,7 @@ var ( OpenShiftStateMetricsService = "openshift-state-metrics/service.yaml" OpenShiftStateMetricsServiceMonitor = "openshift-state-metrics/service-monitor.yaml" OpenShiftStateMetricsKubeRbacProxySecret = "openshift-state-metrics/kube-rbac-proxy-secret.yaml" + OpenShiftStateMetricsNetworkPolicy = "openshift-state-metrics/network-policy-downstream.yaml" NodeExporterDaemonSet = "node-exporter/daemonset.yaml" NodeExporterService = "node-exporter/service.yaml" @@ -167,6 +171,7 @@ var ( PrometheusK8sTAlertmanagerRoleBinding = "prometheus-k8s/alertmanager-role-binding.yaml" PrometheusK8sPodDisruptionBudget = "prometheus-k8s/pod-disruption-budget.yaml" PrometheusK8sTelemetry = "prometheus-k8s/telemetry-secret.yaml" + PrometheusK8sNetworkPolicy = "prometheus-k8s/network-policy-downstream.yaml" PrometheusUserWorkloadServingCertsCABundle = "prometheus-user-workload/serving-certs-ca-bundle.yaml" PrometheusUserWorkloadTrustedCABundle = "prometheus-user-workload/trusted-ca-bundle.yaml" @@ -200,6 +205,7 @@ var ( MetricsServerService = "metrics-server/service.yaml" MetricsServerServiceMonitor = "metrics-server/service-monitor.yaml" MetricsServerPodDisruptionBudget = "metrics-server/pod-disruption-budget.yaml" + MetricsServerNetworkPolicy = "metrics-server/network-policy-downstream.yaml" AdmissionWebhookRuleValidatingWebhook = "admission-webhook/prometheus-rule-validating-webhook.yaml" AdmissionWebhookAlertmanagerConfigValidatingWebhook = "admission-webhook/alertmanager-config-validating-webhook.yaml" @@ -207,6 +213,7 @@ var ( AdmissionWebhookPodDisruptionBudget = "admission-webhook/pod-disruption-budget.yaml" AdmissionWebhookService = "admission-webhook/service.yaml" AdmissionWebhookServiceAccount = "admission-webhook/service-account.yaml" + AdmissionWebhookNetworkPolicy = "admission-webhook/network-policy-downstream.yaml" PrometheusOperatorClusterRoleBinding = "prometheus-operator/cluster-role-binding.yaml" PrometheusOperatorClusterRole = "prometheus-operator/cluster-role.yaml" @@ -216,6 +223,7 @@ var ( PrometheusOperatorServiceMonitor = "prometheus-operator/service-monitor.yaml" PrometheusOperatorPrometheusRule = "prometheus-operator/prometheus-rule.yaml" PrometheusOperatorKubeRbacProxySecret = "prometheus-operator/kube-rbac-proxy-secret.yaml" + PrometheusOperatorNetworkPolicy = "prometheus-operator/network-policy-downstream.yaml" PrometheusOperatorUserWorkloadServiceAccount = "prometheus-operator-user-workload/service-account.yaml" PrometheusOperatorUserWorkloadClusterRole = "prometheus-operator-user-workload/cluster-role.yaml" @@ -245,6 +253,7 @@ var ( ClusterMonitoringMetricsServerClientCertsSecret = "cluster-monitoring-operator/metrics-server-client-certs.yaml" ClusterMonitoringFederateClientCertsSecret = "cluster-monitoring-operator/federate-client-certs.yaml" ClusterMonitoringMetricsClientCACM = "cluster-monitoring-operator/metrics-client-ca.yaml" + ClusterMonitoringDenyAllTraffic = "cluster-monitoring-operator/network-policy-default-deny.yaml" TelemeterClientClusterRole = "telemeter-client/cluster-role.yaml" TelemeterClientClusterRoleBinding = "telemeter-client/cluster-role-binding.yaml" @@ -257,6 +266,7 @@ var ( TelemeterClientServingCertsCABundle = "telemeter-client/serving-certs-ca-bundle.yaml" TelemeterClientKubeRbacProxySecret = "telemeter-client/kube-rbac-proxy-secret.yaml" TelemeterClientPrometheusRule = "telemeter-client/prometheus-rule.yaml" + TelemeterClientNetworkPolicy = "telemeter-client/network-policy-downstream.yaml" ThanosQuerierDeployment = "thanos-querier/deployment.yaml" ThanosQuerierPodDisruptionBudget = "thanos-querier/pod-disruption-budget.yaml" @@ -272,6 +282,7 @@ var ( ThanosQuerierClusterRole = "thanos-querier/cluster-role.yaml" ThanosQuerierClusterRoleBinding = "thanos-querier/cluster-role-binding.yaml" ThanosQuerierGrpcTLSSecret = "thanos-querier/grpc-tls-secret.yaml" + ThanosQuerierNetworkPolicy = "thanos-querier/network-policy-downstream.yaml" ThanosRulerCustomResource = "thanos-ruler/thanos-ruler.yaml" ThanosRulerService = "thanos-ruler/service.yaml" @@ -303,6 +314,7 @@ var ( MonitoringPluginServiceAccount = "monitoring-plugin/service-account.yaml" MonitoringPluginService = "monitoring-plugin/service.yaml" MonitoringPluginPodDisruptionBudget = "monitoring-plugin/pod-disruption-budget.yaml" + MonitoringPluginNetworkPolicy = "monitoring-plugin/network-policy-downstream.yaml" ) var ( @@ -727,6 +739,10 @@ func (f *Factory) AlertmanagerPodDisruptionBudget() (*policyv1.PodDisruptionBudg return f.NewPodDisruptionBudget(f.assets.MustNewAssetSlice(AlertmanagerPodDisruptionBudget)) } +func (f *Factory) AlertmanagerNetworkPolicy() (*networkingv1.NetworkPolicy, error) { + return f.NewNetworkPolicy(f.assets.MustNewAssetSlice(AlertmanagerNetworkPolicy)) +} + func (f *Factory) AlertmanagerUserWorkloadPodDisruptionBudget() (*policyv1.PodDisruptionBudget, error) { return f.NewPodDisruptionBudget(f.assets.MustNewAssetSlice(AlertmanagerUserWorkloadPodDisruptionBudget)) } @@ -800,6 +816,10 @@ func (f *Factory) KubeStateMetricsCRSConfigMap() (*v1.ConfigMap, error) { return f.NewConfigMap(f.assets.MustNewAssetSlice(KubeStateMetricsCRSConfig)) } +func (f *Factory) KubeStateMetricsNetworkPolicy() (*networkingv1.NetworkPolicy, error) { + return f.NewNetworkPolicy(f.assets.MustNewAssetSlice(KubeStateMetricsNetworkPolicy)) +} + func (f *Factory) OpenShiftStateMetricsClusterRoleBinding() (*rbacv1.ClusterRoleBinding, error) { return f.NewClusterRoleBinding(f.assets.MustNewAssetSlice(OpenShiftStateMetricsClusterRoleBinding)) } @@ -859,6 +879,10 @@ func (f *Factory) OpenShiftStateMetricsRBACProxySecret() (*v1.Secret, error) { return f.NewSecret(f.assets.MustNewAssetSlice(OpenShiftStateMetricsKubeRbacProxySecret)) } +func (f *Factory) OpenShiftStateMetricsNetworkPolicy() (*networkingv1.NetworkPolicy, error) { + return f.NewNetworkPolicy(f.assets.MustNewAssetSlice(OpenShiftStateMetricsNetworkPolicy)) +} + func (f *Factory) NodeExporterServiceMonitors() ([]*monv1.ServiceMonitor, error) { return serviceMonitors(f.config.CollectionProfilesFeatureGateEnabled, f.NodeExporterServiceMonitor, f.NodeExporterMinimalServiceMonitor) } @@ -1046,6 +1070,10 @@ func (f *Factory) ThanosQuerierClusterRoleBinding() (*rbacv1.ClusterRoleBinding, return f.NewClusterRoleBinding(f.assets.MustNewAssetSlice(ThanosQuerierClusterRoleBinding)) } +func (f *Factory) ThanosQuerierNetworkPolicy() (*networkingv1.NetworkPolicy, error) { + return f.NewNetworkPolicy(f.assets.MustNewAssetSlice(ThanosQuerierNetworkPolicy)) +} + func (f *Factory) PrometheusUserWorkloadClusterRoleBinding() (*rbacv1.ClusterRoleBinding, error) { return f.NewClusterRoleBinding(f.assets.MustNewAssetSlice(PrometheusUserWorkloadClusterRoleBinding)) } @@ -2088,6 +2116,10 @@ func (f *Factory) MetricsServerAPIService() (*apiregistrationv1.APIService, erro return f.NewAPIService(f.assets.MustNewAssetSlice(MetricsServerAPIService)) } +func (f *Factory) MetricsServerNetworkPolicy() (*networkingv1.NetworkPolicy, error) { + return f.NewNetworkPolicy(f.assets.MustNewAssetSlice(MetricsServerNetworkPolicy)) +} + func (f *Factory) PrometheusOperatorServiceMonitor() (*monv1.ServiceMonitor, error) { return f.NewServiceMonitor(f.assets.MustNewAssetSlice(PrometheusOperatorServiceMonitor)) } @@ -2140,10 +2172,18 @@ func (f *Factory) PrometheusOperatorRBACProxySecret() (*v1.Secret, error) { return f.NewSecret(f.assets.MustNewAssetSlice(PrometheusOperatorKubeRbacProxySecret)) } +func (f *Factory) PrometheusOperatorNetworkPolicy() (*networkingv1.NetworkPolicy, error) { + return f.NewNetworkPolicy(f.assets.MustNewAssetSlice(PrometheusOperatorNetworkPolicy)) +} + func (f *Factory) PrometheusOperatorAdmissionWebhookServiceAccount() (*v1.ServiceAccount, error) { return f.NewServiceAccount(f.assets.MustNewAssetSlice(AdmissionWebhookServiceAccount)) } +func (f *Factory) AdmissionWebhookNetworkPolicy() (*networkingv1.NetworkPolicy, error) { + return f.NewNetworkPolicy(f.assets.MustNewAssetSlice(AdmissionWebhookNetworkPolicy)) +} + func (f *Factory) PrometheusOperatorAdmissionWebhookService() (*v1.Service, error) { return f.NewService(f.assets.MustNewAssetSlice(AdmissionWebhookService)) } @@ -2399,6 +2439,10 @@ func (f *Factory) PrometheusK8sPodDisruptionBudget() (*policyv1.PodDisruptionBud return f.NewPodDisruptionBudget(f.assets.MustNewAssetSlice(PrometheusK8sPodDisruptionBudget)) } +func (f *Factory) PrometheusK8sNetworkPolicy() (*networkingv1.NetworkPolicy, error) { + return f.NewNetworkPolicy(f.assets.MustNewAssetSlice(PrometheusK8sNetworkPolicy)) +} + func (f *Factory) PrometheusUserWorkloadPodDisruptionBudget() (*policyv1.PodDisruptionBudget, error) { return f.NewPodDisruptionBudget(f.assets.MustNewAssetSlice(PrometheusUserWorkloadPodDisruptionBudget)) } @@ -2475,6 +2519,10 @@ func (f *Factory) ClusterMonitoringOperatorPrometheusRule() (*monv1.PrometheusRu return f.NewPrometheusRule(f.assets.MustNewAssetSlice(ClusterMonitoringOperatorPrometheusRule)) } +func (f *Factory) ClusterMonitoringDenyAllTraffic() (*networkingv1.NetworkPolicy, error) { + return f.NewNetworkPolicy(f.assets.MustNewAssetSlice(ClusterMonitoringDenyAllTraffic)) +} + func (f *Factory) ControlPlanePrometheusRule() (*monv1.PrometheusRule, error) { r, err := f.NewPrometheusRule(f.assets.MustNewAssetSlice(ControlPlanePrometheusRule)) if err != nil { @@ -2739,6 +2787,15 @@ func (f *Factory) NewAPIService(manifest []byte) (*apiregistrationv1.APIService, return &s, nil } +func (f *Factory) NewNetworkPolicy(manifest []byte) (*networkingv1.NetworkPolicy, error) { + np := networkingv1.NetworkPolicy{} + err := decodeYAML(manifest, &np) + if err != nil { + return nil, err + } + return &np, nil +} + func (f *Factory) NewSecurityContextConstraints(manifest []byte) (*securityv1.SecurityContextConstraints, error) { s := securityv1.SecurityContextConstraints{} err := decodeYAML(manifest, &s) @@ -2842,6 +2899,10 @@ func (f *Factory) MonitoringPluginPodDisruptionBudget() (*policyv1.PodDisruption return f.NewPodDisruptionBudget(f.assets.MustNewAssetSlice(MonitoringPluginPodDisruptionBudget)) } +func (f *Factory) MonitoringPluginNetworkPolicy() (*networkingv1.NetworkPolicy, error) { + return f.NewNetworkPolicy(f.assets.MustNewAssetSlice(MonitoringPluginNetworkPolicy)) +} + func (f *Factory) MonitoringPluginServiceAccount() (*v1.ServiceAccount, error) { return f.NewServiceAccount(f.assets.MustNewAssetSlice(MonitoringPluginServiceAccount)) } @@ -2995,6 +3056,10 @@ func (f *Factory) TelemeterClientPrometheusRule() (*monv1.PrometheusRule, error) return f.NewPrometheusRule(f.assets.MustNewAssetSlice(TelemeterClientPrometheusRule)) } +func (f *Factory) TelemeterClientNetworkPolicy() (*networkingv1.NetworkPolicy, error) { + return f.NewNetworkPolicy(f.assets.MustNewAssetSlice(TelemeterClientNetworkPolicy)) +} + // TelemeterClientDeployment generates a new Deployment for Telemeter client. // If the passed ConfigMap is not empty it mounts the Trusted CA Bundle as a VolumeMount to // /etc/pki/ca-trust/extracted/pem/ location. diff --git a/pkg/operator/operator.go b/pkg/operator/operator.go index 91f8e6ecc7..8531c645df 100644 --- a/pkg/operator/operator.go +++ b/pkg/operator/operator.go @@ -821,9 +821,11 @@ func (o *Operator) sync(ctx context.Context, key string) error { newUWMTaskSpec("ThanosRuler", tasks.NewThanosRulerUserWorkloadTask(o.client, factory, config)), }), // The shared configmap depends on resources being created by the previous tasks hence run it last. + // Deploy the default deny network policy at the end to ensure that traffic is not unintentionally blocked during upgrades before the per-component network policies are in place. tasks.NewTaskGroup( []*tasks.TaskSpec{ newTaskSpec("ConfigurationSharing", tasks.NewConfigSharingTask(o.client, factory, config)), + newTaskSpec("DefaultDenyNetworkPolicy", tasks.NewDefaultDenyNetworkPolicyTask(o.client, factory, config)), }, ), ) diff --git a/pkg/tasks/alertmanager.go b/pkg/tasks/alertmanager.go index 39eedb2e7d..07e1cc98b2 100644 --- a/pkg/tasks/alertmanager.go +++ b/pkg/tasks/alertmanager.go @@ -53,6 +53,16 @@ func (t *AlertmanagerTask) Run(ctx context.Context) error { } func (t *AlertmanagerTask) create(ctx context.Context) error { + netpol, err := t.factory.AlertmanagerNetworkPolicy() + if err != nil { + return fmt.Errorf("initializing Alertmanager NetworkPolicy failed: %w", err) + } + + err = t.client.CreateOrUpdateNetworkPolicy(ctx, netpol) + if err != nil { + return fmt.Errorf("reconciling Alertmanager NetworkPolicy failed: %w", err) + } + hasRoutes, err := t.client.HasRouteCapability(ctx) if err != nil { return fmt.Errorf("checking for Route capability failed: %w", err) @@ -329,6 +339,16 @@ func (t *AlertmanagerTask) destroy(ctx context.Context) error { } } + netpol, err := t.factory.AlertmanagerNetworkPolicy() + if err != nil { + return fmt.Errorf("initializing Alertmanager NetworkPolicy object failed: %w", err) + } + + err = t.client.DeleteNetworkPolicy(ctx, netpol) + if err != nil { + return fmt.Errorf("deleting Alertmanager NetworkPolicy object failed: %w", err) + } + { // Delete trusted CA bundle ConfigMap. trustedCA, err := t.factory.AlertmanagerTrustedCABundle() diff --git a/pkg/tasks/defaultdeny_netpol.go b/pkg/tasks/defaultdeny_netpol.go new file mode 100644 index 0000000000..a7d1939e29 --- /dev/null +++ b/pkg/tasks/defaultdeny_netpol.go @@ -0,0 +1,51 @@ +// Copyright 2025 The Cluster Monitoring Operator Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tasks + +import ( + "context" + "fmt" + + "github.com/openshift/cluster-monitoring-operator/pkg/client" + "github.com/openshift/cluster-monitoring-operator/pkg/manifests" +) + +type DefaultDenyNetworkPolicyTask struct { + client *client.Client + factory *manifests.Factory + config *manifests.Config +} + +func NewDefaultDenyNetworkPolicyTask(client *client.Client, factory *manifests.Factory, config *manifests.Config) *DefaultDenyNetworkPolicyTask { + return &DefaultDenyNetworkPolicyTask{ + client: client, + factory: factory, + config: config, + } +} + +func (t *DefaultDenyNetworkPolicyTask) Run(ctx context.Context) error { + denyNetpol, err := t.factory.ClusterMonitoringDenyAllTraffic() + if err != nil { + return fmt.Errorf("initializing deny all pods traffic NetworkPolicy failed: %w", err) + } + + err = t.client.CreateOrUpdateNetworkPolicy(ctx, denyNetpol) + if err != nil { + return fmt.Errorf("reconciling deny all pods traffic NetworkPolicy failed: %w", err) + } + + return nil +} diff --git a/pkg/tasks/kubestatemetrics.go b/pkg/tasks/kubestatemetrics.go index d3ecc0a401..622a164f43 100644 --- a/pkg/tasks/kubestatemetrics.go +++ b/pkg/tasks/kubestatemetrics.go @@ -35,6 +35,16 @@ func NewKubeStateMetricsTask(client *client.Client, factory *manifests.Factory) } func (t *KubeStateMetricsTask) Run(ctx context.Context) error { + netpol, err := t.factory.KubeStateMetricsNetworkPolicy() + if err != nil { + return fmt.Errorf("initializing kube-state-metrics NetworkPolicy failed: %w", err) + } + + err = t.client.CreateOrUpdateNetworkPolicy(ctx, netpol) + if err != nil { + return fmt.Errorf("reconciling kube-state-metrics NetworkPolicy failed: %w", err) + } + sa, err := t.factory.KubeStateMetricsServiceAccount() if err != nil { return fmt.Errorf("initializing kube-state-metrics Service failed: %w", err) diff --git a/pkg/tasks/metricsserver.go b/pkg/tasks/metricsserver.go index c0753cad8b..9bad4a6795 100644 --- a/pkg/tasks/metricsserver.go +++ b/pkg/tasks/metricsserver.go @@ -30,6 +30,17 @@ func NewMetricsServerTask(ctx context.Context, namespace string, client *client. } func (t *MetricsServerTask) Run(ctx context.Context) error { + { + netpol, err := t.factory.MetricsServerNetworkPolicy() + if err != nil { + return fmt.Errorf("initializing MetricsServer NetworkPolicy failed: %w", err) + } + + err = t.client.CreateOrUpdateNetworkPolicy(ctx, netpol) + if err != nil { + return fmt.Errorf("reconciling MetricsServer NetworkPolicy failed: %w", err) + } + } { // TODO: This is a temporary workaround until the requirements for https://github.com/openshift/cluster-monitoring-operator/pull/2329 // are ready. diff --git a/pkg/tasks/monitoring_plugin.go b/pkg/tasks/monitoring_plugin.go index cd9884bc16..664b03356e 100644 --- a/pkg/tasks/monitoring_plugin.go +++ b/pkg/tasks/monitoring_plugin.go @@ -39,6 +39,18 @@ func NewMonitoringPluginTask(client *client.Client, factory *manifests.Factory, } func (t *MonitoringPluginTask) Run(ctx context.Context) error { + { + netpol, err := t.factory.MonitoringPluginNetworkPolicy() + if err != nil { + return fmt.Errorf("initializing Console Plugin NetworkPolicy failed: %w", err) + } + + err = t.client.CreateOrUpdateNetworkPolicy(ctx, netpol) + if err != nil { + return fmt.Errorf("reconciling Console Plugin NetworkPolicy failed: %w", err) + } + } + // NOTE: console capability (like other capabilities) can only go from // disabled -> enabled and not the other way around, meaning that CMO // doesn't have to deal with removal of the console plugin resources. diff --git a/pkg/tasks/openshiftstatemetrics.go b/pkg/tasks/openshiftstatemetrics.go index 21377f828b..cab4a67341 100644 --- a/pkg/tasks/openshiftstatemetrics.go +++ b/pkg/tasks/openshiftstatemetrics.go @@ -35,6 +35,16 @@ func NewOpenShiftStateMetricsTask(client *client.Client, factory *manifests.Fact } func (t *OpenShiftStateMetricsTask) Run(ctx context.Context) error { + netpol, err := t.factory.OpenShiftStateMetricsNetworkPolicy() + if err != nil { + return fmt.Errorf("initializing openshift-state-metrics NetworkPolicy failed: %w", err) + } + + err = t.client.CreateOrUpdateNetworkPolicy(ctx, netpol) + if err != nil { + return fmt.Errorf("reconciling openshift-state-metrics NetworkPolicy failed: %w", err) + } + sa, err := t.factory.OpenShiftStateMetricsServiceAccount() if err != nil { return fmt.Errorf("initializing openshift-state-metrics Service failed: %w", err) @@ -104,5 +114,6 @@ func (t *OpenShiftStateMetricsTask) Run(ctx context.Context) error { if err != nil { return fmt.Errorf("reconciling openshift-state-metrics ServiceMonitor failed: %w", err) } + return nil } diff --git a/pkg/tasks/prometheus.go b/pkg/tasks/prometheus.go index ba67e70641..588b0bd79f 100644 --- a/pkg/tasks/prometheus.go +++ b/pkg/tasks/prometheus.go @@ -57,6 +57,16 @@ func (t *PrometheusTask) Run(ctx context.Context) error { } func (t *PrometheusTask) create(ctx context.Context) error { + netpol, err := t.factory.PrometheusK8sNetworkPolicy() + if err != nil { + return fmt.Errorf("initializing Prometheus NetworkPolicy failed: %w", err) + } + + err = t.client.CreateOrUpdateNetworkPolicy(ctx, netpol) + if err != nil { + return fmt.Errorf("reconciling Prometheus NetworkPolicy failed: %w", err) + } + cacm, err := t.factory.PrometheusK8sServingCertsCABundle() if err != nil { return fmt.Errorf("initializing serving certs CA Bundle ConfigMap failed: %w", err) diff --git a/pkg/tasks/prometheusoperator.go b/pkg/tasks/prometheusoperator.go index 4ecb05e078..38b0066c68 100644 --- a/pkg/tasks/prometheusoperator.go +++ b/pkg/tasks/prometheusoperator.go @@ -35,6 +35,16 @@ func NewPrometheusOperatorTask(client *client.Client, factory *manifests.Factory } func (t *PrometheusOperatorTask) Run(ctx context.Context) error { + netpol, err := t.factory.PrometheusOperatorNetworkPolicy() + if err != nil { + return fmt.Errorf("initializing Prometheus Operator NetworkPolicy failed: %w", err) + } + + err = t.client.CreateOrUpdateNetworkPolicy(ctx, netpol) + if err != nil { + return fmt.Errorf("reconciling Prometheus Operator NetworkPolicy failed: %w", err) + } + sa, err := t.factory.PrometheusOperatorServiceAccount() if err != nil { return fmt.Errorf("initializing Prometheus Operator ServiceAccount failed: %w", err) @@ -123,10 +133,21 @@ func (t *PrometheusOperatorTask) Run(ctx context.Context) error { if err != nil { return fmt.Errorf("reconciling Prometheus Operator ServiceMonitor failed: %w", err) } + return nil } func (t *PrometheusOperatorTask) runAdmissionWebhook(ctx context.Context) error { + netpol, err := t.factory.AdmissionWebhookNetworkPolicy() + if err != nil { + return fmt.Errorf("initializing Prometheus Operator Admission Webhook NetworkPolicy failed: %w", err) + } + + err = t.client.CreateOrUpdateNetworkPolicy(ctx, netpol) + if err != nil { + return fmt.Errorf("reconciling Prometheus Operator Admission Webhook NetworkPolicy failed: %w", err) + } + // Deploy manifests for the admission webhook service. sa, err := t.factory.PrometheusOperatorAdmissionWebhookServiceAccount() if err != nil { diff --git a/pkg/tasks/telemeter.go b/pkg/tasks/telemeter.go index 65c5cb539e..2599a63d56 100644 --- a/pkg/tasks/telemeter.go +++ b/pkg/tasks/telemeter.go @@ -196,10 +196,31 @@ func (t *TelemeterClientTask) create(ctx context.Context) error { if err != nil { return fmt.Errorf("reconciling Telemeter client ServiceMonitor failed: %w", err) } + + netpol, err := t.factory.TelemeterClientNetworkPolicy() + if err != nil { + return fmt.Errorf("initializing Telemeter Client NetworkPolicy failed: %w", err) + } + + err = t.client.CreateOrUpdateNetworkPolicy(ctx, netpol) + if err != nil { + return fmt.Errorf("reconciling Telemeter Client NetworkPolicy failed: %w", err) + } + return nil } func (t *TelemeterClientTask) destroy(ctx context.Context) error { + netpol, err := t.factory.TelemeterClientNetworkPolicy() + if err != nil { + return fmt.Errorf("initializing Telemeter Client NetworkPolicy object failed: %w", err) + } + + err = t.client.DeleteNetworkPolicy(ctx, netpol) + if err != nil { + return fmt.Errorf("deleting Telemeter Client NetworkPolicy object failed: %w", err) + } + dep, err := t.factory.TelemeterClientDeployment(nil, nil) if err != nil { return fmt.Errorf("initializing Telemeter client Deployment failed: %w", err) @@ -289,5 +310,6 @@ func (t *TelemeterClientTask) destroy(ctx context.Context) error { if err != nil { return fmt.Errorf("deleting Telemeter Client serving certs CA Bundle ConfigMap failed: %w", err) } + return nil } diff --git a/pkg/tasks/thanos_querier.go b/pkg/tasks/thanos_querier.go index 7ec8b2f677..d1ee50b540 100644 --- a/pkg/tasks/thanos_querier.go +++ b/pkg/tasks/thanos_querier.go @@ -37,6 +37,16 @@ func NewThanosQuerierTask(client *client.Client, factory *manifests.Factory, cfg } func (t *ThanosQuerierTask) Run(ctx context.Context) error { + netpol, err := t.factory.ThanosQuerierNetworkPolicy() + if err != nil { + return fmt.Errorf("initializing Thanos Querier NetworkPolicy failed: %w", err) + } + + err = t.client.CreateOrUpdateNetworkPolicy(ctx, netpol) + if err != nil { + return fmt.Errorf("reconciling Thanos Querier NetworkPolicy failed: %w", err) + } + svc, err := t.factory.ThanosQuerierService() if err != nil { return fmt.Errorf("initializing Thanos Querier Service failed: %w", err) diff --git a/test/e2e/alertmanager_test.go b/test/e2e/alertmanager_test.go index 156631fee8..ec9cb470a1 100644 --- a/test/e2e/alertmanager_test.go +++ b/test/e2e/alertmanager_test.go @@ -699,7 +699,8 @@ func TestAlertmanagerDisabling(t *testing.T) { {name: "assert trusted-ca-bundle does not exist", assertion: f.AssertConfigmapDoesNotExist("alertmanager-trusted-ca-bundle", f.Ns)}, {name: "assert prometheus rule does not exist", assertion: f.AssertPrometheusRuleDoesNotExist("alertmanager-main-rules", f.Ns)}, {name: "assert service monitor does not exist", assertion: f.AssertServiceMonitorDoesNotExist("alertmanager-main", f.Ns)}, - {name: "assert old service monitor does not exists", assertion: f.AssertServiceMonitorDoesNotExist("alertmanager", f.Ns)}, + {name: "assert old service monitor does not exist", assertion: f.AssertServiceMonitorDoesNotExist("alertmanager", f.Ns)}, + {name: "assert alertmanager networkpolicy does not exist", assertion: f.AssertNetworkPolicyDoesNotExist("alertmanager", f.Ns)}, {name: "alertmanager public URL is unset", assertion: f.AssertValueInConfigMapEquals( "monitoring-shared-config", "openshift-config-managed", "alertmanagerPublicURL", "")}, {name: "assert prometheus alertmanager endpoints empty", assertion: f.AssertPrometheusAlertmanagerEndpointsEmpty("prometheus-k8s", f.Ns)}, @@ -718,6 +719,7 @@ func TestAlertmanagerDisabling(t *testing.T) { name string assertion framework.AssertionFunc }{ + {name: "assert alertmanager networkpolicy exists", assertion: f.AssertNetworkPolicyExists("alertmanager", f.Ns)}, {name: "assert alertmanager exists", assertion: f.AssertStatefulsetExists("alertmanager-main", f.Ns)}, {name: "assert route exists", assertion: f.AssertRouteExists("alertmanager-main", f.Ns)}, {name: "assert alertmanager main config exists", assertion: f.AssertSecretExists("alertmanager-main", f.Ns)}, diff --git a/test/e2e/framework/assertions.go b/test/e2e/framework/assertions.go index 19b46449d4..34b2c98166 100644 --- a/test/e2e/framework/assertions.go +++ b/test/e2e/framework/assertions.go @@ -198,6 +198,22 @@ func (f *Framework) AssertNamespaceDoesNotExist(name string) func(t *testing.T) } } +func (f *Framework) AssertNetworkPolicyExists(name string, namespace string) func(t *testing.T) { + return func(t *testing.T) { + assertResourceExists(t, func() (metav1.Object, error) { + return f.KubeClient.NetworkingV1().NetworkPolicies(namespace).Get(ctx, name, metav1.GetOptions{}) + }) + } +} + +func (f *Framework) AssertNetworkPolicyDoesNotExist(name string, namespace string) func(t *testing.T) { + return func(t *testing.T) { + assertResourceDoesNotExists(t, func() (metav1.Object, error) { + return f.KubeClient.NetworkingV1().NetworkPolicies(namespace).Get(ctx, name, metav1.GetOptions{}) + }) + } +} + func (f *Framework) AssertPrometheusRuleExists(name string, namespace string) func(t *testing.T) { return func(t *testing.T) { assertResourceExists(t, func() (metav1.Object, error) { diff --git a/test/e2e/main_test.go b/test/e2e/main_test.go index c9e046ce62..2de9d2643b 100644 --- a/test/e2e/main_test.go +++ b/test/e2e/main_test.go @@ -190,6 +190,45 @@ func TestMemoryUsageRecordingRule(t *testing.T) { ) } +// TestNetworkPolicy ensures that the NetworkPolicies +// are deployed under openshift-monitoring namespace +func TestNetworkPolicy(t *testing.T) { + ctx := context.Background() + networkPolicyNames := []string{ + "deny-cluster-monitoring-operator-and-operands", + "cluster-monitoring-operator", + "alertmanager", + "prometheus", + "kube-state-metrics", + "metrics-server", + "monitoring-plugin", + "openshift-state-metrics", + "prometheus-operator", + "prometheus-operator-admission-webhook", + "telemeter-client", + "thanos-querier", + } + + t.Run("check in-cluster monitoring NetworkPolicies", func(t *testing.T) { + for _, name := range networkPolicyNames { + t.Run(fmt.Sprintf("assert %s networkpolicy exists", name), func(t *testing.T) { + f.AssertNetworkPolicyExists(name, f.Ns) + }) + } + }) + + // check the total count of deployed NetworkPolicies is equal to len(networkPolicyNames) + t.Run("assert total deployed NetworkPolicies count matches", func(t *testing.T) { + npList, err := f.KubeClient.NetworkingV1().NetworkPolicies(f.Ns).List(ctx, metav1.ListOptions{}) + if err != nil { + t.Fatalf("failed to list NetworkPolicies: %v", err) + } + if len(npList.Items) != len(networkPolicyNames) { + t.Errorf("NetworkPolicies count = %d, want %d", len(npList.Items), len(networkPolicyNames)) + } + }) +} + func TestPodsLabels(t *testing.T) { // Verify that all pods in the openshift-monitoring namespace have the // app.kubernetes.io/part-of: openshift-monitoring label.