open-cluster-management.io/governance-policy-propagator@v0.13.0/test/e2e/case20_compliance_api_controller_test.go (about)

     1  // Copyright Contributors to the Open Cluster Management project
     2  
     3  package e2e
     4  
     5  import (
     6  	"bytes"
     7  	"context"
     8  	"database/sql"
     9  	"encoding/json"
    10  	"fmt"
    11  	"io"
    12  	"math/rand"
    13  	"net/http"
    14  	"time"
    15  
    16  	"github.com/google/uuid"
    17  	. "github.com/onsi/ginkgo/v2"
    18  	. "github.com/onsi/gomega"
    19  	corev1 "k8s.io/api/core/v1"
    20  	rbacv1 "k8s.io/api/rbac/v1"
    21  	k8serrors "k8s.io/apimachinery/pkg/api/errors"
    22  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    23  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    24  
    25  	"open-cluster-management.io/governance-policy-propagator/controllers/complianceeventsapi"
    26  	"open-cluster-management.io/governance-policy-propagator/controllers/propagator"
    27  	"open-cluster-management.io/governance-policy-propagator/test/utils"
    28  )
    29  
    30  var _ = Describe("Test governance-policy-database secret changes, DB annotations, and events", Serial, Ordered, func() {
    31  	const (
    32  		case20PolicyName string = "case20-policy"
    33  		case20PolicyYAML string = "../resources/case20_compliance_api_controller/policy.yaml"
    34  	)
    35  
    36  	seededRand := rand.New(rand.NewSource(time.Now().UnixNano()))
    37  	nsName := fmt.Sprintf("case20-%d", seededRand.Int31())
    38  
    39  	createCase20Policy := func(ctx context.Context) {
    40  		By("Creating " + case20PolicyName)
    41  		utils.Kubectl("apply", "-f", case20PolicyYAML, "-n", nsName, "--kubeconfig="+kubeconfigHub)
    42  		plc := utils.GetWithTimeout(
    43  			clientHubDynamic, gvrPolicy, case20PolicyName, nsName, true, defaultTimeoutSeconds,
    44  		)
    45  		ExpectWithOffset(1, plc).NotTo(BeNil())
    46  
    47  		By("Patching the placement with decision of cluster local-cluster")
    48  		pld := utils.GetWithTimeout(
    49  			clientHubDynamic,
    50  			gvrPlacementDecision,
    51  			case20PolicyName,
    52  			nsName,
    53  			true,
    54  			defaultTimeoutSeconds,
    55  		)
    56  		pld.Object["status"] = utils.GeneratePldStatus(pld.GetName(), pld.GetNamespace(), "local-cluster")
    57  		_, err := clientHubDynamic.Resource(gvrPlacementDecision).Namespace(nsName).UpdateStatus(
    58  			ctx, pld, metav1.UpdateOptions{},
    59  		)
    60  		ExpectWithOffset(1, err).ToNot(HaveOccurred())
    61  
    62  		By("Waiting for the replicated policy")
    63  		replicatedPolicy := utils.GetWithTimeout(
    64  			clientHubDynamic, gvrPolicy, case20PolicyName, nsName, true, defaultTimeoutSeconds,
    65  		)
    66  		ExpectWithOffset(1, replicatedPolicy).NotTo(BeNil())
    67  	}
    68  
    69  	waitForDisabledEvent := func(ctx context.Context, after time.Time) {
    70  		afterStr := after.Format(time.RFC3339Nano)
    71  
    72  		By("Waiting for the disabled compliance event after " + afterStr)
    73  		EventuallyWithOffset(1, func(g Gomega) {
    74  			endpoint := fmt.Sprintf(
    75  				"https://localhost:%d/api/v1/compliance-events?cluster.name=local-cluster&event.compliance=Disabled"+
    76  					"&event.timestamp_after=%s&policy.name=%s",
    77  				complianceAPIPort,
    78  				afterStr,
    79  				case20PolicyName,
    80  			)
    81  
    82  			req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
    83  			g.Expect(err).ToNot(HaveOccurred())
    84  
    85  			req.Header.Set("Authorization", "Bearer "+clientToken)
    86  
    87  			resp, err := httpClient.Do(req)
    88  			if err != nil {
    89  				return
    90  			}
    91  
    92  			defer resp.Body.Close()
    93  
    94  			g.Expect(resp.StatusCode).To(Equal(http.StatusOK))
    95  
    96  			body, err := io.ReadAll(resp.Body)
    97  			g.Expect(err).ToNot(HaveOccurred())
    98  
    99  			result := map[string]any{}
   100  
   101  			err = json.Unmarshal(body, &result)
   102  			g.Expect(err).ToNot(HaveOccurred())
   103  
   104  			metadata, ok := result["metadata"].(map[string]interface{})
   105  			g.Expect(ok).To(BeTrue(), "The metadata key was the wrong type")
   106  
   107  			g.Expect(metadata["total"]).To(BeEquivalentTo(1))
   108  		}, defaultTimeoutSeconds*2, 1).Should(Succeed())
   109  	}
   110  
   111  	BeforeAll(func(ctx context.Context) {
   112  		Expect(clientToken).ToNot(BeEmpty(), "Ensure you use the service account kubeconfig (kubeconfig_hub)")
   113  
   114  		By("Creating a random namespace to avoid a cache hit")
   115  		ns := &corev1.Namespace{
   116  			ObjectMeta: metav1.ObjectMeta{
   117  				Name: nsName,
   118  			},
   119  		}
   120  		_, err := clientHub.CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{})
   121  		Expect(err).ToNot(HaveOccurred())
   122  	})
   123  
   124  	AfterEach(func(ctx context.Context) {
   125  		restoreDBConnection(ctx)
   126  	})
   127  
   128  	AfterAll(func(ctx context.Context) {
   129  		err := clientHub.CoreV1().Namespaces().Delete(ctx, nsName, metav1.DeleteOptions{})
   130  		Expect(err).ToNot(HaveOccurred())
   131  	})
   132  
   133  	It("Adds missing database IDs once database connection is restored", func(ctx context.Context) {
   134  		By("Updating the connection to be invalid")
   135  		bringDownDBConnection(ctx)
   136  
   137  		createCase20Policy(ctx)
   138  
   139  		By("Getting the replicated policy")
   140  		replicatedPolicy := utils.GetWithTimeout(
   141  			clientHubDynamic, gvrPolicy, case20PolicyName, nsName, true, defaultTimeoutSeconds,
   142  		)
   143  		Expect(replicatedPolicy).NotTo(BeNil())
   144  
   145  		annotations := replicatedPolicy.GetAnnotations()
   146  		Expect(annotations[propagator.ParentPolicyIDAnnotation]).To(BeEmpty())
   147  		Expect(annotations[propagator.PolicyIDAnnotation]).To(BeEmpty())
   148  
   149  		By("Restoring the database connection")
   150  		Eventually(func(g Gomega) {
   151  			namespacedSecret := clientHub.CoreV1().Secrets("open-cluster-management")
   152  			secret, err := namespacedSecret.Get(
   153  				ctx, complianceeventsapi.DBSecretName, metav1.GetOptions{},
   154  			)
   155  			g.Expect(err).ToNot(HaveOccurred())
   156  
   157  			delete(secret.Data, "port")
   158  
   159  			_, err = namespacedSecret.Update(ctx, secret, metav1.UpdateOptions{})
   160  			g.Expect(err).ToNot(HaveOccurred())
   161  		}, defaultTimeoutSeconds, 1).Should(Succeed())
   162  
   163  		By("Waiting for the replicated policy to have the database ID annotations")
   164  		Eventually(func(g Gomega) {
   165  			replicatedPolicy = utils.GetWithTimeout(
   166  				clientHubDynamic, gvrPolicy, nsName+"."+case20PolicyName, "local-cluster", true, defaultTimeoutSeconds,
   167  			)
   168  			g.Expect(replicatedPolicy).NotTo(BeNil())
   169  
   170  			annotations = replicatedPolicy.GetAnnotations()
   171  			g.Expect(annotations[propagator.ParentPolicyIDAnnotation]).ToNot(BeEmpty())
   172  
   173  			templates, _, _ := unstructured.NestedSlice(replicatedPolicy.Object, "spec", "policy-templates")
   174  			g.Expect(templates).To(HaveLen(1))
   175  
   176  			policyID, _, _ := unstructured.NestedString(
   177  				templates[0].(map[string]interface{}),
   178  				"objectDefinition",
   179  				"metadata",
   180  				"annotations",
   181  				propagator.PolicyIDAnnotation,
   182  			)
   183  			g.Expect(policyID).ToNot(BeEmpty())
   184  		}, defaultTimeoutSeconds, 1).Should(Succeed())
   185  	})
   186  
   187  	It("Creates a disabled event for local-cluster", func(ctx context.Context) {
   188  		now := time.Now().UTC().Add(-1 * time.Second)
   189  
   190  		By("Deleting " + case20PolicyName)
   191  		utils.Kubectl("delete", "-f", case20PolicyYAML, "-n", nsName, "--kubeconfig="+kubeconfigHub)
   192  		plc := utils.GetWithTimeout(
   193  			clientHubDynamic, gvrPolicy, case20PolicyName, nsName, false, defaultTimeoutSeconds,
   194  		)
   195  		Expect(plc).To(BeNil())
   196  
   197  		waitForDisabledEvent(ctx, now)
   198  	})
   199  
   200  	It("Creates a disabled event for local-cluster when the database is down and restored", func(ctx context.Context) {
   201  		createCase20Policy(ctx)
   202  
   203  		bringDownDBConnection(ctx)
   204  
   205  		now := time.Now().UTC().Add(-1 * time.Second)
   206  
   207  		By("Deleting " + case20PolicyName)
   208  		utils.Kubectl("delete", "-f", case20PolicyYAML, "-n", nsName, "--kubeconfig="+kubeconfigHub)
   209  		plc := utils.GetWithTimeout(
   210  			clientHubDynamic, gvrPolicy, case20PolicyName, nsName, false, defaultTimeoutSeconds,
   211  		)
   212  		Expect(plc).To(BeNil())
   213  
   214  		By("Waiting for the replicated policy to be deleted")
   215  		replicatedPolicy := utils.GetWithTimeout(
   216  			clientHubDynamic, gvrPolicy, case20PolicyName, nsName, false, defaultTimeoutSeconds,
   217  		)
   218  		Expect(replicatedPolicy).To(BeNil())
   219  
   220  		restoreDBConnection(ctx)
   221  
   222  		waitForDisabledEvent(ctx, now)
   223  	})
   224  })
   225  
   226  func bringDownDBConnection(ctx context.Context) {
   227  	By("Setting the port to 12345")
   228  	EventuallyWithOffset(1, func(g Gomega) {
   229  		namespacedSecret := clientHub.CoreV1().Secrets("open-cluster-management")
   230  		secret, err := namespacedSecret.Get(
   231  			ctx, complianceeventsapi.DBSecretName, metav1.GetOptions{},
   232  		)
   233  		g.Expect(err).ToNot(HaveOccurred())
   234  
   235  		secret.StringData = map[string]string{"port": "12345"}
   236  
   237  		_, err = namespacedSecret.Update(ctx, secret, metav1.UpdateOptions{})
   238  		g.Expect(err).ToNot(HaveOccurred())
   239  	}, defaultTimeoutSeconds, 1).Should(Succeed())
   240  
   241  	By("Waiting for the database connection to be down")
   242  	EventuallyWithOffset(1, func(g Gomega) {
   243  		req, err := http.NewRequestWithContext(
   244  			ctx, http.MethodGet, fmt.Sprintf("https://localhost:%d/api/v1/compliance-events/1", complianceAPIPort), nil,
   245  		)
   246  		g.Expect(err).ToNot(HaveOccurred())
   247  
   248  		req.Header.Set("Authorization", "Bearer "+clientToken)
   249  
   250  		resp, err := httpClient.Do(req)
   251  		if err != nil {
   252  			return
   253  		}
   254  
   255  		defer resp.Body.Close()
   256  
   257  		g.Expect(resp.StatusCode).To(Equal(http.StatusInternalServerError))
   258  
   259  		body, err := io.ReadAll(resp.Body)
   260  		g.Expect(err).ToNot(HaveOccurred())
   261  
   262  		respJSON := map[string]any{}
   263  
   264  		err = json.Unmarshal(body, &respJSON)
   265  		g.Expect(err).ToNot(HaveOccurred())
   266  
   267  		g.Expect(respJSON["message"]).To(Equal("The database is unavailable"))
   268  	}, defaultTimeoutSeconds, 1).Should(Succeed())
   269  }
   270  
   271  func restoreDBConnection(ctx context.Context) {
   272  	By("Restoring the database connection")
   273  	EventuallyWithOffset(1, func(g Gomega) {
   274  		namespacedSecret := clientHub.CoreV1().Secrets("open-cluster-management")
   275  		secret, err := namespacedSecret.Get(
   276  			ctx, complianceeventsapi.DBSecretName, metav1.GetOptions{},
   277  		)
   278  		g.Expect(err).ToNot(HaveOccurred())
   279  
   280  		if secret.Data["port"] == nil {
   281  			return
   282  		}
   283  
   284  		delete(secret.Data, "port")
   285  
   286  		_, err = namespacedSecret.Update(ctx, secret, metav1.UpdateOptions{})
   287  		g.Expect(err).ToNot(HaveOccurred())
   288  	}, defaultTimeoutSeconds, 1).Should(Succeed())
   289  
   290  	By("Waiting for the database connection to be up")
   291  	EventuallyWithOffset(1, func(g Gomega) {
   292  		req, err := http.NewRequestWithContext(
   293  			ctx,
   294  			http.MethodGet,
   295  			fmt.Sprintf("https://localhost:%d/api/v1/compliance-events?per_page=1", complianceAPIPort),
   296  			nil,
   297  		)
   298  		g.Expect(err).ToNot(HaveOccurred())
   299  
   300  		req.Header.Set("Authorization", "Bearer "+clientToken)
   301  
   302  		resp, err := httpClient.Do(req)
   303  		if err != nil {
   304  			return
   305  		}
   306  
   307  		defer resp.Body.Close()
   308  
   309  		g.Expect(resp.StatusCode).To(Equal(http.StatusOK))
   310  	}, defaultTimeoutSeconds, 1).Should(Succeed())
   311  }
   312  
   313  var _ = Describe("Test compliance events API authentication and authorization", Serial, Ordered, func() {
   314  	eventsEndpoint := fmt.Sprintf("https://localhost:%d/api/v1/compliance-events", complianceAPIPort)
   315  	const saName string = "compliance-api-user"
   316  	var token string
   317  
   318  	getSamplePostRequest := func(clusterName string) *bytes.Buffer {
   319  		payload := []byte(fmt.Sprintf(`{
   320  			"cluster": {
   321  				"name": "%s",
   322  				"cluster_id": "%s"
   323  			},
   324  			"parent_policy": {
   325  				"name": "parent-policy",
   326  				"namespace": "%s"
   327  			},
   328  			"policy": {
   329  				"apiGroup": "policy.open-cluster-management.io",
   330  				"kind": "ConfigurationPolicy",
   331  				"name": "etcd-encryption",
   332  				"spec": {"uid": "%s"}
   333  			},
   334  			"event": {
   335  				"compliance": "NonCompliant",
   336  				"message": "configmaps [etcd] not found in namespace default",
   337  				"timestamp": "2023-02-02T02:02:02.222Z"
   338  			}
   339  		}`, clusterName, uuid.New().String(), uuid.New().String(), uuid.New().String()))
   340  
   341  		return bytes.NewBuffer(payload)
   342  	}
   343  
   344  	BeforeAll(func(ctx context.Context) {
   345  		By("Creating the service account " + saName + " in the namespace" + testNamespace)
   346  		_, err := clientHub.CoreV1().ServiceAccounts(testNamespace).Create(
   347  			ctx,
   348  			&corev1.ServiceAccount{
   349  				ObjectMeta: metav1.ObjectMeta{
   350  					Name:      saName,
   351  					Namespace: testNamespace,
   352  				},
   353  			},
   354  			metav1.CreateOptions{},
   355  		)
   356  		Expect(err).ToNot(HaveOccurred())
   357  
   358  		_, err = clientHub.CoreV1().Secrets(testNamespace).Create(
   359  			ctx,
   360  			&corev1.Secret{
   361  				ObjectMeta: metav1.ObjectMeta{
   362  					Name:      saName,
   363  					Namespace: testNamespace,
   364  					Annotations: map[string]string{
   365  						corev1.ServiceAccountNameKey: saName,
   366  					},
   367  				},
   368  				Type: corev1.SecretTypeServiceAccountToken,
   369  			},
   370  			metav1.CreateOptions{},
   371  		)
   372  		Expect(err).ToNot(HaveOccurred())
   373  
   374  		By("Granting the service account " + saName + " permission to the cluster namespace " + testNamespace)
   375  		_, err = clientHub.RbacV1().Roles(testNamespace).Create(
   376  			ctx,
   377  			&rbacv1.Role{
   378  				ObjectMeta: metav1.ObjectMeta{
   379  					Name:      saName,
   380  					Namespace: testNamespace,
   381  				},
   382  				Rules: []rbacv1.PolicyRule{
   383  					{
   384  						APIGroups: []string{"policy.open-cluster-management.io"},
   385  						Resources: []string{"policies/status"},
   386  						Verbs:     []string{"patch"},
   387  					},
   388  				},
   389  			},
   390  			metav1.CreateOptions{},
   391  		)
   392  		Expect(err).ToNot(HaveOccurred())
   393  
   394  		_, err = clientHub.RbacV1().RoleBindings(testNamespace).Create(
   395  			ctx,
   396  			&rbacv1.RoleBinding{
   397  				ObjectMeta: metav1.ObjectMeta{
   398  					Name:      saName,
   399  					Namespace: testNamespace,
   400  				},
   401  				Subjects: []rbacv1.Subject{
   402  					{
   403  						Kind:      "ServiceAccount",
   404  						Name:      saName,
   405  						Namespace: testNamespace,
   406  					},
   407  				},
   408  				RoleRef: rbacv1.RoleRef{
   409  					APIGroup: "rbac.authorization.k8s.io",
   410  					Kind:     "Role",
   411  					Name:     saName,
   412  				},
   413  			},
   414  			metav1.CreateOptions{},
   415  		)
   416  		Expect(err).ToNot(HaveOccurred())
   417  
   418  		Eventually(func(g Gomega) {
   419  			secret, err := clientHub.CoreV1().Secrets(testNamespace).Get(ctx, saName, metav1.GetOptions{})
   420  			g.Expect(err).ToNot(HaveOccurred())
   421  
   422  			g.Expect(secret.Data["token"]).ToNot(BeNil())
   423  
   424  			token = string(secret.Data["token"])
   425  		}, defaultTimeoutSeconds, 1).Should(Succeed())
   426  	})
   427  
   428  	AfterAll(func(ctx context.Context) {
   429  		By("Deleting the service account")
   430  		err := clientHub.CoreV1().ServiceAccounts(testNamespace).Delete(ctx, saName, metav1.DeleteOptions{})
   431  		if !k8serrors.IsNotFound(err) {
   432  			Expect(err).ToNot(HaveOccurred())
   433  		}
   434  
   435  		err = clientHub.CoreV1().Secrets(testNamespace).Delete(ctx, saName, metav1.DeleteOptions{})
   436  		if !k8serrors.IsNotFound(err) {
   437  			Expect(err).ToNot(HaveOccurred())
   438  		}
   439  
   440  		err = clientHub.RbacV1().Roles(testNamespace).Delete(ctx, saName, metav1.DeleteOptions{})
   441  		if !k8serrors.IsNotFound(err) {
   442  			Expect(err).ToNot(HaveOccurred())
   443  		}
   444  
   445  		err = clientHub.RbacV1().RoleBindings(testNamespace).Delete(ctx, saName, metav1.DeleteOptions{})
   446  		if !k8serrors.IsNotFound(err) {
   447  			Expect(err).ToNot(HaveOccurred())
   448  		}
   449  
   450  		By("Deleting all database records")
   451  		connectionURL := "postgresql://grc:grc@localhost:5432/ocm-compliance-history?sslmode=disable"
   452  		db, err := sql.Open("postgres", connectionURL)
   453  		DeferCleanup(func() {
   454  			Expect(db.Close()).To(Succeed())
   455  		})
   456  
   457  		Expect(err).ToNot(HaveOccurred())
   458  
   459  		_, err = db.ExecContext(ctx, "DELETE FROM compliance_events")
   460  		Expect(err).ToNot(HaveOccurred())
   461  		_, err = db.ExecContext(ctx, "DELETE FROM clusters")
   462  		Expect(err).ToNot(HaveOccurred())
   463  		_, err = db.ExecContext(ctx, "DELETE FROM parent_policies")
   464  		Expect(err).ToNot(HaveOccurred())
   465  		_, err = db.ExecContext(ctx, "DELETE FROM policies")
   466  		Expect(err).ToNot(HaveOccurred())
   467  	})
   468  
   469  	It("Rejects recording the compliance event without authentication", func(ctx context.Context) {
   470  		payload := getSamplePostRequest("cluster")
   471  
   472  		req, err := http.NewRequestWithContext(ctx, http.MethodPost, eventsEndpoint, payload)
   473  		Expect(err).ToNot(HaveOccurred())
   474  		req.Header.Set("Content-Type", "application/json")
   475  
   476  		resp, err := httpClient.Do(req)
   477  		Expect(err).ToNot(HaveOccurred())
   478  
   479  		if resp != nil {
   480  			defer resp.Body.Close()
   481  		}
   482  
   483  		Expect(resp.StatusCode).To(Equal(http.StatusUnauthorized))
   484  	})
   485  
   486  	It("Rejects recording the compliance event for the wrong namespace", func(ctx context.Context) {
   487  		payload := getSamplePostRequest("cluster")
   488  
   489  		req, err := http.NewRequestWithContext(ctx, http.MethodPost, eventsEndpoint, payload)
   490  		Expect(err).ToNot(HaveOccurred())
   491  		req.Header.Set("Content-Type", "application/json")
   492  		req.Header.Set("Authorization", "Bearer "+token)
   493  
   494  		resp, err := httpClient.Do(req)
   495  		Expect(err).ToNot(HaveOccurred())
   496  
   497  		if resp != nil {
   498  			defer resp.Body.Close()
   499  		}
   500  
   501  		Expect(resp.StatusCode).To(Equal(http.StatusForbidden))
   502  	})
   503  
   504  	It("Allows recording the compliance event", func(ctx context.Context) {
   505  		payload := getSamplePostRequest(testNamespace)
   506  
   507  		req, err := http.NewRequestWithContext(ctx, http.MethodPost, eventsEndpoint, payload)
   508  		Expect(err).ToNot(HaveOccurred())
   509  		req.Header.Set("Content-Type", "application/json")
   510  		req.Header.Set("Authorization", "Bearer "+token)
   511  
   512  		resp, err := httpClient.Do(req)
   513  		Expect(err).ToNot(HaveOccurred())
   514  
   515  		if resp != nil {
   516  			defer resp.Body.Close()
   517  		}
   518  
   519  		Expect(resp.StatusCode).To(Equal(http.StatusCreated))
   520  	})
   521  
   522  	It("Clears its database ID cache when the database loses data", func(ctx context.Context) {
   523  		By("Creating a compliance event")
   524  		payloadStr := getSamplePostRequest(testNamespace).String()
   525  		payload := bytes.NewBufferString(payloadStr)
   526  
   527  		req, err := http.NewRequestWithContext(ctx, http.MethodPost, eventsEndpoint, payload)
   528  		Expect(err).ToNot(HaveOccurred())
   529  		req.Header.Set("Content-Type", "application/json")
   530  		req.Header.Set("Authorization", "Bearer "+token)
   531  
   532  		resp, err := httpClient.Do(req)
   533  		Expect(err).ToNot(HaveOccurred())
   534  
   535  		if resp != nil {
   536  			defer resp.Body.Close()
   537  		}
   538  
   539  		Expect(resp.StatusCode).To(Equal(http.StatusCreated))
   540  
   541  		By("Deleting all compliance events and policy references")
   542  		connectionURL := "postgresql://grc:grc@localhost:5432/ocm-compliance-history?sslmode=disable"
   543  		db, err := sql.Open("postgres", connectionURL)
   544  		DeferCleanup(func() {
   545  			Expect(db.Close()).To(Succeed())
   546  		})
   547  
   548  		Expect(err).ToNot(HaveOccurred())
   549  
   550  		_, err = db.ExecContext(ctx, "DELETE FROM compliance_events")
   551  		Expect(err).ToNot(HaveOccurred())
   552  		_, err = db.ExecContext(ctx, "DELETE FROM parent_policies")
   553  		Expect(err).ToNot(HaveOccurred())
   554  		_, err = db.ExecContext(ctx, "DELETE FROM policies")
   555  		Expect(err).ToNot(HaveOccurred())
   556  
   557  		By("Verifying an internal error is returned the first time an invalid ID is provided")
   558  		payload = bytes.NewBufferString(payloadStr)
   559  		req, err = http.NewRequestWithContext(ctx, http.MethodPost, eventsEndpoint, payload)
   560  		Expect(err).ToNot(HaveOccurred())
   561  		req.Header.Set("Content-Type", "application/json")
   562  		req.Header.Set("Authorization", "Bearer "+token)
   563  
   564  		resp, err = httpClient.Do(req)
   565  		Expect(err).ToNot(HaveOccurred())
   566  
   567  		if resp != nil {
   568  			defer resp.Body.Close()
   569  		}
   570  
   571  		body, err := io.ReadAll(resp.Body)
   572  		Expect(err).ToNot(HaveOccurred())
   573  
   574  		Expect(resp.StatusCode).To(Equal(http.StatusInternalServerError), fmt.Sprintf("Got response %s", string(body)))
   575  
   576  		By("Verifying a success after the cache is cleared")
   577  		payload = bytes.NewBufferString(payloadStr)
   578  		req, err = http.NewRequestWithContext(ctx, http.MethodPost, eventsEndpoint, payload)
   579  		Expect(err).ToNot(HaveOccurred())
   580  		req.Header.Set("Content-Type", "application/json")
   581  		req.Header.Set("Authorization", "Bearer "+token)
   582  
   583  		resp, err = httpClient.Do(req)
   584  		Expect(err).ToNot(HaveOccurred())
   585  
   586  		if resp != nil {
   587  			defer resp.Body.Close()
   588  		}
   589  
   590  		Expect(resp.StatusCode).To(Equal(http.StatusCreated))
   591  	})
   592  })