diff --git a/.github/workflows/e2e_attestation.yml b/.github/workflows/e2e_attestation.yml new file mode 100644 index 00000000000..312ea9e00de --- /dev/null +++ b/.github/workflows/e2e_attestation.yml @@ -0,0 +1,36 @@ +name: e2e test attestation + +on: + pull_request: + paths: + - e2e/attestation/** + +jobs: + test_matrix: + strategy: + matrix: + platform: + - name: Metal-QEMU-SNP + runner: SNP + self-hosted: true + - name: Metal-QEMU-TDX + runner: TDX + self-hosted: true + fail-fast: false + name: "${{ matrix.platform.name }}" + uses: ./.github/workflows/e2e.yml + with: + skip-undeploy: false + test-name: attestation + platform: ${{ matrix.platform.name }} + runner: ${{ matrix.platform.runner }} + self-hosted: ${{ matrix.platform.self-hosted }} + secrets: + GITHUB_TOKEN_IN: ${{ secrets.GITHUB_TOKEN }} + CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} + NUNKI_CI_COMMIT_PUSH_PR: ${{ secrets.NUNKI_CI_COMMIT_PUSH_PR }} + TEAMS_CI_WEBHOOK: ${{ secrets.TEAMS_CI_WEBHOOK }} + CONTRAST_GHCR_READ: ${{ secrets.CONTRAST_GHCR_READ }} + permissions: + contents: read + packages: write diff --git a/e2e/attestation/attestation_test.go b/e2e/attestation/attestation_test.go index 85229ac2cb5..dd498c1effc 100644 --- a/e2e/attestation/attestation_test.go +++ b/e2e/attestation/attestation_test.go @@ -327,6 +327,46 @@ func TestAttestation(t *testing.T) { }) require.True(t.Run("set", ct.Set), "set should succeed as long as one validator passes") }) + + // Test that the SNP guest policy is configurable. + t.Run("configurable-guest-policy", func(t *testing.T) { + platform, err := platforms.FromString(contrasttest.Flags.PlatformStr) + require.NoError(t, err) + // Only run on SNP hosts, SNP guest policy irrelevant on other platforms. + if !platforms.IsSNP(platform) { + t.Skip() + } + ct := contrasttest.New(t) + + runtimeHandler, err := manifest.RuntimeHandler(platform) + require.NoError(t, err) + resources := kuberesource.CoordinatorBundle() + resources = kuberesource.PatchRuntimeHandlers(resources, runtimeHandler) + resources = kuberesource.AddPortForwarders(resources) + + ct.Init(t, resources) + require.True(t, t.Run("generate", ct.Generate), "contrast generate needs to succeed for subsequent tests") + require.True(t, t.Run("apply", ct.Apply), "Kubernetes resources need to be applied for subsequent tests") + require.True(t, t.Run("set", ct.Set), "contrast set needs to succeed for subsequent tests") + require.True(t, t.Run("contrast verify", ct.Verify), "contrast verify needs to succeed for subsequent tests") + unstructured, err := kuberesource.ResourcesToUnstructured(resources) + require.NoError(t, err) + require.NoError(t, ct.Kubeclient.Delete(t.Context(), unstructured...)) + require.NoError(t, ct.Kubeclient.WaitForDeletion(t.Context(), unstructured...)) + + // Change the guest policy. By default, the minimum required ABIMinor version is 0 + // (read from packages/by-name/contrast/reference-values/snpGuestPolicyQEMU.json). + ct.PatchManifest(t, func(m manifest.Manifest) (manifest.Manifest, error) { + for i := range m.ReferenceValues.SNP { + m.ReferenceValues.SNP[i].GuestPolicy.ABIMinor++ + } + return m, nil + }) + require.True(t, t.Run("changed guest policy generate", ct.Generate), "contrast generate needs to succeed for subsequent tests") + require.True(t, t.Run("changed guest policy apply", ct.Apply), "Kubernetes resources need to be applied for subsequent tests") + require.True(t, t.Run("changed guest policy set", ct.Set), "contrast set needs to succeed for subsequent tests") + require.True(t, t.Run("changed guest policy contrast verify", ct.Verify), "contrast verify needs to succeed for subsequent tests") + }) } func TestMain(m *testing.M) {