Repository: istio/istio
File: tests/integration/ambient/crl/crl_test.go (Go)

Code before:
	if err != nil {
		t.Fatalf("failed to get system namespace: %v", err)
	}

	expectedCRL := strings.TrimSpace(string(bundle.CRLPEM()))

	retry.UntilSuccessOrFail(t, func() error {
		for _, c := range t.AllClusters() {
			pods, err := c.Kube().CoreV1().Pods(systemNS.Name()).List(
				context.TODO(),
				metav1.ListOptions{LabelSelector: "app=ztunnel"},
			)
			if err != nil {
				return fmt.Errorf("failed to list ztunnel pods: %w", err)
			}

			for _, pod := range pods.Items {
				stdout, stderr, err := c.PodExec(
					pod.Name,
					systemNS.Name(),
					"istio-proxy",
					"cat /var/run/secrets/istio/crl/ca-crl.pem",
				)
				if err != nil {
					return fmt.Errorf("failed to read CRL file in %s: %v, stderr: %s", pod.Name, err, stderr)
				}

				actualCRL := strings.TrimSpace(stdout)
				if actualCRL != expectedCRL {
					return fmt.Errorf("CRL file in %s not yet updated (expected len=%d, got len=%d)",
						pod.Name, len(expectedCRL), len(actualCRL))
				}
			}
		}
		return nil
	}, retry.Timeout(3*time.Minute), retry.Delay(5*time.Second))

	t.Logf("CRL file synced to all ztunnel pods")
}

// deployRevokedApps deploys new echo apps in the given namespaces
// these apps will get certificates from the now-revoked CA chain
func deployRevokedApps(t framework.TestContext, clientNS, serverNS namespace.Instance) (echo.Instance, echo.Instance) {
	t.Helper()

	var revokedClient, revokedServer echo.Instance

	deployment.New(t).
		With(&revokedClient, echo.Config{
			Service:        "ambient-client-revoked",
			Namespace:      clientNS,

Review comment (suggestion):
I don't think this will work with out distroless images. Even then there could be a race between the crl existing on the pod and ztunnel loading it. I think we can either

Just do the retry, this would involve messing around with hbone timeouts since we only check crls on new connections.

Check readiness based on logs. I think this is easier.

Code after:
	retry.UntilSuccessOrFail(t, func() error {
		for _, c := range t.AllClusters() {
			pods, err := c.Kube().CoreV1().Pods(systemNS.Name()).List(
				t.Context(),
				metav1.ListOptions{LabelSelector: "app=ztunnel"},
			)
			if err != nil {
				return fmt.Errorf("failed to list ztunnel pods: %w", err)
			}

			for _, pod := range pods.Items {
				logs, err := c.PodLogs(t.Context(), pod.Name, systemNS.Name(), "istio-proxy", false)
				if err != nil {
					return fmt.Errorf("failed to get logs from %s: %w", pod.Name, err)
				}

				if !strings.Contains(logs, "crl reloaded successfully") {
					return fmt.Errorf("ztunnel %s has not reloaded CRL yet", pod.Name)
				}
			}
		}
		return nil
	}, retry.Timeout(3*time.Minute), retry.Delay(5*time.Second))

	t.Logf("ztunnel CRL reload confirmed via logs")
}

// deployRevokedApps deploys new echo apps in the given namespaces
// these apps will get certificates from the now-revoked CA chain
func deployRevokedApps(t framework.TestContext, clientNS, serverNS namespace.Instance) (echo.Instance, echo.Instance) {
	t.Helper()

	var revokedClient, revokedServer echo.Instance

	deployment.New(t).
		With(&revokedClient, echo.Config{
			Service:        "ambient-client-revoked",
			Namespace:      clientNS,
			ServiceAccount: true,
			Ports: []echo.Port{{
				Name:         "http",
				Protocol:     protocol.HTTP,
				WorkloadPort: 8080,
			}},
		}).
		With(&revokedServer, echo.Config{
			Service:        "ambient-server-revoked",
			Namespace:      serverNS,
			ServiceAccount: true,
			Ports: []echo.Port{{
				Name:         "http",