mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-05-02 14:26:23 -04:00
config: sign Azure versions on upload & verify on fetch (#1836)
* add SignContent() + integrate into configAPI * use static client for upload versions tool; fix staticupload calleeReference bug * use version to get proper cosign pub key. * mock fetcher in CLI tests * only provide config.New constructor with fetcher Co-authored-by: Otto Bittner <cobittner@posteo.net> Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com>
This commit is contained in:
parent
e0285c122e
commit
b51cc52945
55 changed files with 752 additions and 308 deletions
|
@ -6,6 +6,7 @@ go_library(
|
|||
importpath = "github.com/edgelesssys/constellation/v2/hack/azure-snp-report-verify",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//internal/api/configapi",
|
||||
"@in_gopkg_square_go_jose_v2//:go-jose_v2",
|
||||
"@in_gopkg_square_go_jose_v2//jwt",
|
||||
],
|
||||
|
|
|
@ -13,12 +13,14 @@ import (
|
|||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/api/configapi"
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
)
|
||||
|
@ -43,6 +45,8 @@ func (i *IsolationTEE) PrintSVNs() {
|
|||
}
|
||||
|
||||
func main() {
|
||||
configAPIExportPath := flag.String("export-path", "azure-sev-snp-version.json", "Path to the exported config API file.")
|
||||
flag.Parse()
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Println("Usage:", os.Args[0], "<maa-jwt>")
|
||||
return
|
||||
|
@ -54,6 +58,31 @@ func main() {
|
|||
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) {
|
||||
|
|
|
@ -5,11 +5,7 @@ go_library(
|
|||
srcs = ["main.go"],
|
||||
importpath = "github.com/edgelesssys/constellation/v2/hack/configapi",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//internal/api/configapi",
|
||||
"//internal/kms/uri",
|
||||
"@com_github_spf13_cobra//:cobra",
|
||||
],
|
||||
deps = ["//hack/configapi/cmd"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
|
|
13
hack/configapi/cmd/BUILD.bazel
Normal file
13
hack/configapi/cmd/BUILD.bazel
Normal file
|
@ -0,0 +1,13 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "cmd",
|
||||
srcs = ["root.go"],
|
||||
importpath = "github.com/edgelesssys/constellation/v2/hack/configapi/cmd",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//internal/api/configapi",
|
||||
"//internal/staticupload",
|
||||
"@com_github_spf13_cobra//:cobra",
|
||||
],
|
||||
)
|
103
hack/configapi/cmd/root.go
Normal file
103
hack/configapi/cmd/root.go
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
Copyright (c) Edgeless Systems GmbH
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/api/configapi"
|
||||
"github.com/edgelesssys/constellation/v2/internal/staticupload"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
awsRegion = "eu-central-1"
|
||||
awsBucket = "cdn-constellation-backend"
|
||||
invalidDefault = 0
|
||||
envAwsKeyID = "AWS_ACCESS_KEY_ID"
|
||||
envAwsKey = "AWS_ACCESS_KEY"
|
||||
)
|
||||
|
||||
var (
|
||||
versionFilePath string
|
||||
// Cosign credentials.
|
||||
cosignPwd string
|
||||
privateKeyPath string
|
||||
)
|
||||
|
||||
// Execute executes the root command.
|
||||
func Execute() error {
|
||||
return newRootCmd().Execute()
|
||||
}
|
||||
|
||||
// newRootCmd creates the root command.
|
||||
func newRootCmd() *cobra.Command {
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "AWS_ACCESS_KEY_ID=$ID AWS_ACCESS_KEY=$KEY upload -b 2 -t 0 -s 6 -m 93 --cosign-pwd $PWD --private-key $FILE_PATH",
|
||||
Short: "Upload a set of versions specific to the azure-sev-snp attestation variant to the config api.",
|
||||
|
||||
Long: "Upload a set of versions specific to the azure-sev-snp attestation variant to the config api. Please authenticate with AWS through your preferred method (e.g. environment variables, CLI) to be able to upload to S3.",
|
||||
RunE: runCmd,
|
||||
}
|
||||
rootCmd.PersistentFlags().StringVarP(&versionFilePath, "version-file", "f", "", "File path to the version json file.")
|
||||
rootCmd.PersistentFlags().StringVar(&cosignPwd, "cosign-pwd", "", "Cosign password used to decrpyt the private key.")
|
||||
rootCmd.PersistentFlags().StringVar(&privateKeyPath, "private-key", "", "File path of private key used to sign the payload.")
|
||||
must(enforceRequiredFlags(rootCmd, "version-file", "cosign-pwd", "private-key"))
|
||||
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
func runCmd(cmd *cobra.Command, _ []string) error {
|
||||
ctx := cmd.Context()
|
||||
cfg := staticupload.Config{
|
||||
Bucket: awsBucket,
|
||||
Region: awsRegion,
|
||||
}
|
||||
privateKey, err := os.ReadFile(privateKeyPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading private key: %w", err)
|
||||
}
|
||||
|
||||
versionBytes, err := os.ReadFile(versionFilePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading version file: %w", err)
|
||||
}
|
||||
var versions configapi.AzureSEVSNPVersion
|
||||
err = json.Unmarshal(versionBytes, &versions)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unmarshalling version file: %w", err)
|
||||
}
|
||||
|
||||
sut, err := configapi.NewAttestationVersionRepo(ctx, cfg, []byte(cosignPwd), privateKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating repo: %w", err)
|
||||
}
|
||||
|
||||
if err := sut.UploadAzureSEVSNP(ctx, versions, time.Now()); err != nil {
|
||||
return fmt.Errorf("uploading version: %w", err)
|
||||
}
|
||||
cmd.Printf("Successfully uploaded new Azure SEV-SNP version: %+v\n", versions)
|
||||
return nil
|
||||
}
|
||||
|
||||
func enforceRequiredFlags(cmd *cobra.Command, flags ...string) error {
|
||||
for _, flag := range flags {
|
||||
if err := cmd.MarkPersistentFlagRequired(flag); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func must(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
|
@ -7,85 +7,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
"os"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/api/configapi"
|
||||
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/edgelesssys/constellation/v2/hack/configapi/cmd"
|
||||
)
|
||||
|
||||
const (
|
||||
awsRegion = "eu-central-1"
|
||||
awsBucket = "cdn-constellation-backend"
|
||||
invalidDefault = 0
|
||||
)
|
||||
|
||||
var (
|
||||
// AWS S3 credentials.
|
||||
awsAccessKeyID string
|
||||
awsAccessKey string
|
||||
|
||||
// Azure SEV-SNP version numbers.
|
||||
bootloaderVersion uint8
|
||||
teeVersion uint8
|
||||
snpVersion uint8
|
||||
microcodeVersion uint8
|
||||
)
|
||||
|
||||
func handleError(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
myCmd := &cobra.Command{
|
||||
Use: "upload a set of versions specific to the azure-sev-snp attestation variant to the config api",
|
||||
Short: "upload a set of versions specific to the azure-sev-snp attestation variant to the config api",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
ctx := context.Background()
|
||||
cfg := uri.AWSS3Config{
|
||||
Bucket: awsBucket,
|
||||
AccessKeyID: awsAccessKeyID,
|
||||
AccessKey: awsAccessKey,
|
||||
Region: awsRegion,
|
||||
}
|
||||
sut, err := configapi.NewAttestationVersionRepo(ctx, cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
versions := configapi.AzureSEVSNPVersion{
|
||||
Bootloader: bootloaderVersion,
|
||||
TEE: teeVersion,
|
||||
SNP: snpVersion,
|
||||
Microcode: microcodeVersion,
|
||||
}
|
||||
|
||||
if err := sut.UploadAzureSEVSNP(ctx, versions, time.Now()); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
fmt.Println("Successfully uploaded version numbers", versions)
|
||||
}
|
||||
},
|
||||
if err := cmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
myCmd.PersistentFlags().Uint8VarP(&bootloaderVersion, "bootloader-version", "b", invalidDefault, "Bootloader version number")
|
||||
handleError(myCmd.MarkPersistentFlagRequired("bootloader-version"))
|
||||
|
||||
myCmd.PersistentFlags().Uint8VarP(&teeVersion, "tee-version", "t", invalidDefault, "TEE version number")
|
||||
handleError(myCmd.MarkPersistentFlagRequired("tee-version"))
|
||||
|
||||
myCmd.PersistentFlags().Uint8VarP(&snpVersion, "snp-version", "s", invalidDefault, "SNP version number")
|
||||
handleError(myCmd.MarkPersistentFlagRequired("snp-version"))
|
||||
|
||||
myCmd.PersistentFlags().Uint8VarP(µcodeVersion, "microcode-version", "m", invalidDefault, "Microcode version number")
|
||||
handleError(myCmd.MarkPersistentFlagRequired("microcode-version"))
|
||||
|
||||
myCmd.PersistentFlags().StringVar(&awsAccessKeyID, "key-id", "", "ID of the Access key to use for AWS tests. Required for AWS KMS and storage test.")
|
||||
handleError(myCmd.MarkPersistentFlagRequired("key-id"))
|
||||
|
||||
myCmd.PersistentFlags().StringVar(&awsAccessKey, "key", "", "Access key to use for AWS tests. Required for AWS KMS and storage test.")
|
||||
handleError(myCmd.MarkPersistentFlagRequired("key"))
|
||||
handleError(myCmd.Execute())
|
||||
os.Exit(0)
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ require (
|
|||
github.com/google/gnostic v0.5.7-v3refs // indirect
|
||||
github.com/google/go-attestation v0.4.4-0.20221011162210-17f9c05652a9 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/go-containerregistry v0.14.0 // indirect
|
||||
github.com/google/go-containerregistry v0.14.1-0.20230409045903-ed5c185df419 // indirect
|
||||
github.com/google/go-sev-guest v0.6.1 // indirect
|
||||
github.com/google/go-tpm v0.3.3 // indirect
|
||||
github.com/google/go-tpm-tools v0.3.12 // indirect
|
||||
|
@ -219,7 +219,7 @@ require (
|
|||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/locker v1.0.1 // indirect
|
||||
|
|
|
@ -664,8 +664,8 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8
|
|||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-containerregistry v0.14.0 h1:z58vMqHxuwvAsVwvKEkmVBz2TlgBgH5k6koEXBtlYkw=
|
||||
github.com/google/go-containerregistry v0.14.0/go.mod h1:aiJ2fp/SXvkWgmYHioXnbMdlgB8eXiiYOY55gfN91Wk=
|
||||
github.com/google/go-containerregistry v0.14.1-0.20230409045903-ed5c185df419 h1:gMlTWagRJgCJ3EnISyF5+p9phYpFyWEI70Z56T+o2MY=
|
||||
github.com/google/go-containerregistry v0.14.1-0.20230409045903-ed5c185df419/go.mod h1:ETSJmRH9iO4Q0WQILIMkDUiKk+CaxItZW+gEDjyw8Ug=
|
||||
github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=
|
||||
github.com/google/go-licenses v0.0.0-20210329231322-ce1d9163b77d/go.mod h1:+TYOmkVoJOpwnS0wfdsJCV9CoD5nJYsHoFk/0CrTK4M=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
|
@ -1019,8 +1019,8 @@ github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
|
|||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue