|
5 | 5 | "context" |
6 | 6 | "encoding/json" |
7 | 7 | "fmt" |
| 8 | + "net/http" |
| 9 | + "os" |
8 | 10 | "regexp" |
9 | 11 | "strings" |
10 | 12 | "time" |
@@ -49,6 +51,101 @@ type TelemeterClientConfig struct { |
49 | 51 | Enabled *bool `json:"enabled"` |
50 | 52 | } |
51 | 53 |
|
| 54 | +// Set $MONITORING_AUTH_TEST_NAMESPACE to focus on the targets from a single namespace |
| 55 | +var monitoringAuthTestNamespace = os.Getenv("MONITORING_AUTH_TEST_NAMESPACE") |
| 56 | + |
| 57 | +var _ = g.Describe("[sig-instrumentation][Late] Platform Prometheus targets", func() { |
| 58 | + defer g.GinkgoRecover() |
| 59 | + var ( |
| 60 | + oc = exutil.NewCLIWithPodSecurityLevel("prometheus", admissionapi.LevelBaseline) |
| 61 | + prometheusURL, bearerToken string |
| 62 | + |
| 63 | + // TODO: remove the namespace when the bug is fixed. |
| 64 | + namespacesToSkip = sets.New[string]("openshift-marketplace", // https://issues.redhat.com/browse/OCPBUGS-59763 |
| 65 | + "openshift-image-registry", // https://issues.redhat.com/browse/OCPBUGS-59767 |
| 66 | + "openshift-operator-lifecycle-manager", // https://issues.redhat.com/browse/OCPBUGS-59768 |
| 67 | + "openshift-cluster-samples-operator", // https://issues.redhat.com/browse/OCPBUGS-59769 |
| 68 | + "openshift-cluster-version", // https://issues.redhat.com/browse/OCPBUGS-57585 |
| 69 | + "openshift-cluster-csi-drivers", // https://issues.redhat.com/browse/OCPBUGS-60159 |
| 70 | + "openshift-cluster-node-tuning-operator", // https://issues.redhat.com/browse/OCPBUGS-60258 |
| 71 | + "openshift-etcd", // https://issues.redhat.com/browse/OCPBUGS-60263 |
| 72 | + ) |
| 73 | + ) |
| 74 | + |
| 75 | + g.BeforeEach(func(ctx g.SpecContext) { |
| 76 | + var err error |
| 77 | + |
| 78 | + kubeClient, err := kubernetes.NewForConfig(oc.AdminConfig()) |
| 79 | + o.Expect(err).NotTo(o.HaveOccurred()) |
| 80 | + nsExist, err := exutil.IsNamespaceExist(kubeClient, "openshift-monitoring") |
| 81 | + o.Expect(err).NotTo(o.HaveOccurred()) |
| 82 | + if !nsExist { |
| 83 | + g.Skip("openshift-monitoring namespace does not exist, skipping") |
| 84 | + } |
| 85 | + |
| 86 | + prometheusURL, err = helper.PrometheusRouteURL(ctx, oc) |
| 87 | + o.Expect(err).NotTo(o.HaveOccurred(), "Get public url of prometheus") |
| 88 | + bearerToken, err = helper.RequestPrometheusServiceAccountAPIToken(ctx, oc) |
| 89 | + o.Expect(err).NotTo(o.HaveOccurred(), "Request prometheus service account API token") |
| 90 | + |
| 91 | + if namespacesToSkip.Has(monitoringAuthTestNamespace) { |
| 92 | + e2e.Logf("The namespace %s is not skipped because $MONITORING_AUTH_TEST_NAMESPACE is set to it", monitoringAuthTestNamespace) |
| 93 | + namespacesToSkip.Delete(monitoringAuthTestNamespace) |
| 94 | + } |
| 95 | + }) |
| 96 | + |
| 97 | + g.It("should not be accessible without auth [Serial]", func() { |
| 98 | + var errs []error |
| 99 | + |
| 100 | + g.By("checking that targets reject the requests with 401 or 403") |
| 101 | + execPod := exutil.CreateExecPodOrFail(oc.AdminKubeClient(), oc.Namespace(), "execpod-targets-authorization") |
| 102 | + defer func() { |
| 103 | + err := oc.AdminKubeClient().CoreV1().Pods(execPod.Namespace).Delete(context.Background(), execPod.Name, *metav1.NewDeleteOptions(1)) |
| 104 | + o.Expect(err).NotTo(o.HaveOccurred(), fmt.Sprintf("Delete pod %s/%s", execPod.Namespace, execPod.Name)) |
| 105 | + }() |
| 106 | + |
| 107 | + contents, err := helper.GetURLWithToken(helper.MustJoinUrlPath(prometheusURL, "api/v1/targets"), bearerToken) |
| 108 | + o.Expect(err).NotTo(o.HaveOccurred()) |
| 109 | + |
| 110 | + targets := &prometheusTargets{} |
| 111 | + err = json.Unmarshal([]byte(contents), targets) |
| 112 | + o.Expect(err).NotTo(o.HaveOccurred()) |
| 113 | + o.Expect(len(targets.Data.ActiveTargets)).Should(o.BeNumerically(">=", 5)) |
| 114 | + |
| 115 | + expected := sets.New[int](http.StatusUnauthorized, http.StatusForbidden) |
| 116 | + for _, target := range targets.Data.ActiveTargets { |
| 117 | + ns := target.Labels["namespace"] |
| 118 | + o.Expect(ns).NotTo(o.BeEmpty()) |
| 119 | + if monitoringAuthTestNamespace != "" && ns != monitoringAuthTestNamespace { |
| 120 | + continue |
| 121 | + } |
| 122 | + pod := target.Labels["pod"] |
| 123 | + e2e.Logf("Checking via pod exec status code from the scrape url %s for pod %s/%s without authorization (skip=%t)", target.ScrapeUrl, ns, pod, namespacesToSkip.Has(ns)) |
| 124 | + err := wait.PollUntilContextTimeout(context.Background(), 10*time.Second, time.Minute, true, func(context.Context) (bool, error) { |
| 125 | + statusCode, execError := helper.URLStatusCodeExecViaPod(execPod.Namespace, execPod.Name, target.ScrapeUrl) |
| 126 | + e2e.Logf("The scrape url %s for pod %s/%s without authorization returned %d, %v (skip=%t)", target.ScrapeUrl, ns, pod, statusCode, execError, namespacesToSkip.Has(ns)) |
| 127 | + if expected.Has(statusCode) { |
| 128 | + return true, nil |
| 129 | + } |
| 130 | + // retry on those cases |
| 131 | + if execError != nil || |
| 132 | + statusCode/100 == 5 || |
| 133 | + statusCode == http.StatusRequestTimeout || |
| 134 | + statusCode == http.StatusTooManyRequests { |
| 135 | + return false, nil |
| 136 | + } |
| 137 | + return false, fmt.Errorf("expecting status code %v but returned %d", expected.UnsortedList(), statusCode) |
| 138 | + }) |
| 139 | + if err != nil && !namespacesToSkip.Has(ns) { |
| 140 | + errs = append(errs, fmt.Errorf("the scrape url %s for pod %s/%s is accessible without authorization: %w", target.ScrapeUrl, ns, pod, err)) |
| 141 | + } |
| 142 | + } |
| 143 | + |
| 144 | + o.Expect(errs).To(o.BeEmpty()) |
| 145 | + }) |
| 146 | + |
| 147 | +}) |
| 148 | + |
52 | 149 | var _ = g.Describe("[sig-instrumentation][Late] OpenShift alerting rules [apigroup:image.openshift.io]", func() { |
53 | 150 | defer g.GinkgoRecover() |
54 | 151 |
|
|
0 commit comments