From 30df225cccdb370338283d9a9ff54b6e77cf3ba5 Mon Sep 17 00:00:00 2001 From: Paul Meyer <49727155+katexochen@users.noreply.github.com> Date: Fri, 11 Aug 2023 18:59:11 +0200 Subject: [PATCH] hack: remove azure-snp-report-verify Signed-off-by: Paul Meyer <49727155+katexochen@users.noreply.github.com> --- hack/azure-snp-report-verify/BUILD.bazel | 19 --- hack/azure-snp-report-verify/Dockerfile | 16 --- hack/azure-snp-report-verify/README.md | 21 --- hack/azure-snp-report-verify/verify.go | 166 ----------------------- hack/go.mod | 2 +- 5 files changed, 1 insertion(+), 223 deletions(-) delete mode 100644 hack/azure-snp-report-verify/BUILD.bazel delete mode 100644 hack/azure-snp-report-verify/Dockerfile delete mode 100644 hack/azure-snp-report-verify/README.md delete mode 100644 hack/azure-snp-report-verify/verify.go diff --git a/hack/azure-snp-report-verify/BUILD.bazel b/hack/azure-snp-report-verify/BUILD.bazel deleted file mode 100644 index 6124fff2c..000000000 --- a/hack/azure-snp-report-verify/BUILD.bazel +++ /dev/null @@ -1,19 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") - -go_library( - name = "azure-snp-report-verify_lib", - srcs = ["verify.go"], - importpath = "github.com/edgelesssys/constellation/v2/hack/azure-snp-report-verify", - visibility = ["//visibility:private"], - deps = [ - "//internal/api/attestationconfigapi", - "@in_gopkg_square_go_jose_v2//:go-jose_v2", - "@in_gopkg_square_go_jose_v2//jwt", - ], -) - -go_binary( - name = "azure-snp-report-verify", - embed = [":azure-snp-report-verify_lib"], - visibility = ["//visibility:public"], -) diff --git a/hack/azure-snp-report-verify/Dockerfile b/hack/azure-snp-report-verify/Dockerfile deleted file mode 100644 index 6802ca18f..000000000 --- a/hack/azure-snp-report-verify/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -FROM ubuntu:20.04@sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba AS build -RUN apt-get update && apt-get install -y \ - build-essential \ - libcurl4-openssl-dev \ - wget -RUN wget -q https://packages.microsoft.com/repos/azurecore/pool/main/a/azguestattestation1/azguestattestation1_1.0.2_amd64.deb \ - && apt-get install /azguestattestation1_1.0.2_amd64.deb -RUN wget -q https://github.com/Azure/confidential-computing-cvm-guest-attestation/raw/4bd89d2808912fbaa319e8853e6f5e1e245d45ca/cvm-guest-attestation-linux-app/main.cpp \ - && sed -i s/test.attest.azure.net/attest.azure.net/ main.cpp \ - && touch Utils.h \ - && g++ -Os -I/usr/include/azguestattestation1 -oclient main.cpp -lazguestattestation - -FROM ubuntu:20.04@sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba AS release -COPY --from=build client azguestattestation1_1.0.2_amd64.deb / -RUN apt-get update && apt-get install -y /azguestattestation1_1.0.2_amd64.deb -ENTRYPOINT ["/client"] diff --git a/hack/azure-snp-report-verify/README.md b/hack/azure-snp-report-verify/README.md deleted file mode 100644 index 10744bd41..000000000 --- a/hack/azure-snp-report-verify/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Obtain current Azure SNP ID key digest & firmware versions - -On Azure, Constellation verifies that the SNP attestation report contains Azure's ID key digest. -Additionally, some firmware security version numbers (SVNs) are validated. -Currently, the only way to verify the digest's origin is to perform guest attestation with the help of the Microsoft Azure Attestation (MAA) service. -There's a [sample](https://github.com/Azure/confidential-computing-cvm-guest-attestation) on how to do this, but it's not straightforward. -So we created tooling to make things easier. - -Perform the following steps to get the ID key digest & firmware versions: - -1. Create an Ubuntu CVM on Azure with secure boot enabled and ssh into it. -2. Run - ``` - docker run --rm --privileged -v/sys/kernel/security:/sys/kernel/security ghcr.io/edgelesssys/constellation/azure-snp-reporter - ``` - This executes the guest attestation and prints the JWT received from the MAA. (It's the long base64 blob.) -3. Copy the JWT and run **on your local trusted machine**: - ``` - go run verify.go - ``` - On success it prints the ID key digest and relevant firmware SVNs. diff --git a/hack/azure-snp-report-verify/verify.go b/hack/azure-snp-report-verify/verify.go deleted file mode 100644 index 925c69ac3..000000000 --- a/hack/azure-snp-report-verify/verify.go +++ /dev/null @@ -1,166 +0,0 @@ -/* -Copyright (c) Edgeless Systems GmbH - -SPDX-License-Identifier: AGPL-3.0-only -*/ - -// Verify verifies an MAA JWT and prints the SNP ID key digest on success. -package main - -import ( - "context" - "crypto/x509" - "encoding/base64" - "encoding/json" - "errors" - "flag" - "fmt" - "io" - "net/http" - "os" - "time" - - configapi "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi" - "gopkg.in/square/go-jose.v2" - "gopkg.in/square/go-jose.v2/jwt" -) - -// IsolationTEE describes an Azure SNP TEE. -type IsolationTEE struct { - IDKeyDigest string `json:"x-ms-sevsnpvm-idkeydigest"` - TEESvn int `json:"x-ms-sevsnpvm-tee-svn"` - SNPFwSvn int `json:"x-ms-sevsnpvm-snpfw-svn"` - MicrocodeSvn int `json:"x-ms-sevsnpvm-microcode-svn"` - BootloaderSvn int `json:"x-ms-sevsnpvm-bootloader-svn"` - GuestSvn int `json:"x-ms-sevsnpvm-guestsvn"` -} - -// PrintSVNs prints the relevant Security Version Numbers (SVNs). -func (i *IsolationTEE) PrintSVNs() { - fmt.Println("\tTEE SVN:", i.TEESvn) - fmt.Println("\tSNP FW SVN:", i.SNPFwSvn) - fmt.Println("\tMicrocode SVN:", i.MicrocodeSvn) - fmt.Println("\tBootloader SVN:", i.BootloaderSvn) - fmt.Println("\tGuest SVN:", i.GuestSvn) -} - -func main() { - configAPIExportPath := flag.String("export-path", "azure-sev-snp-version.json", "Path to the exported config API file.") - maaJWT := flag.String("report", "", "MAA JWT report to verify") - flag.Parse() - if *maaJWT == "" { - fmt.Println("Must provide --report") - return - } - report, err := getTEEReport(*maaJWT) - if err != nil { - panic(err) - } - fmt.Println("Successfully validated ID key digest:", report.IDKeyDigest) - fmt.Println("Currently reported SVNs:") - report.PrintSVNs() - - if *configAPIExportPath != "" { - configAPIVersion := convertToConfigAPIFile(report) - if err := exportToJSONFile(configAPIVersion, *configAPIExportPath); err != nil { - panic(err) - } - fmt.Println("Successfully exported config API file to:", configAPIExportPath) - } -} - -func convertToConfigAPIFile(i IsolationTEE) configapi.AzureSEVSNPVersion { - return configapi.AzureSEVSNPVersion{ - Bootloader: uint8(i.BootloaderSvn), - TEE: uint8(i.TEESvn), - SNP: uint8(i.SNPFwSvn), - Microcode: uint8(i.MicrocodeSvn), - } -} - -func exportToJSONFile(configAPIVersion configapi.AzureSEVSNPVersion, configAPIExportPath string) error { - data, err := json.Marshal(configAPIVersion) - if err != nil { - return err - } - return os.WriteFile(configAPIExportPath, data, 0o644) -} - -func getTEEReport(rawToken string) (IsolationTEE, error) { - // Parse token. - token, err := jwt.ParseSigned(rawToken) - if err != nil { - return IsolationTEE{}, err - } - - // Get JSON Web Key set. - keySetBytes, err := httpGet(context.Background(), "https://sharedeus.eus.attest.azure.net/certs") - if err != nil { - return IsolationTEE{}, err - } - keySet, err := parseKeySet(keySetBytes) - if err != nil { - return IsolationTEE{}, err - } - - // Get claims. Private claims contain ID Key digest. - - var publicClaims jwt.Claims - - var privateClaims struct { - IsolationTEE IsolationTEE `json:"x-ms-isolation-tee"` - } - - if err := token.Claims(&keySet, &publicClaims, &privateClaims); err != nil { - return IsolationTEE{}, err - } - if err := publicClaims.Validate(jwt.Expected{Time: time.Now()}); err != nil { - return IsolationTEE{}, err - } - - return privateClaims.IsolationTEE, nil -} - -func parseKeySet(keySetBytes []byte) (jose.JSONWebKeySet, error) { - var rawKeySet struct { - Keys []struct { - X5c []string - Kid string - } - } - if err := json.Unmarshal(keySetBytes, &rawKeySet); err != nil { - return jose.JSONWebKeySet{}, err - } - - var keySet jose.JSONWebKeySet - for _, key := range rawKeySet.Keys { - rawCert, _ := base64.StdEncoding.DecodeString(key.X5c[0]) - cert, err := x509.ParseCertificate(rawCert) - if err != nil { - return jose.JSONWebKeySet{}, err - } - keySet.Keys = append(keySet.Keys, jose.JSONWebKey{KeyID: key.Kid, Key: cert.PublicKey}) - } - - return keySet, nil -} - -func httpGet(ctx context.Context, url string) ([]byte, error) { - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, http.NoBody) - if err != nil { - return nil, err - } - resp, err := http.DefaultClient.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return nil, errors.New(resp.Status) - } - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - return body, nil -} diff --git a/hack/go.mod b/hack/go.mod index 8614bb390..264aa87cc 100644 --- a/hack/go.mod +++ b/hack/go.mod @@ -51,7 +51,6 @@ require ( go.uber.org/zap v1.24.0 golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df golang.org/x/mod v0.12.0 - gopkg.in/square/go-jose.v2 v2.6.0 libvirt.org/go/libvirt v1.9004.0 ) @@ -297,6 +296,7 @@ require ( google.golang.org/grpc v1.56.2 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect