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:
Adrian Stobbe 2023-06-01 13:55:46 +02:00 committed by GitHub
parent e0285c122e
commit b51cc52945
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
55 changed files with 752 additions and 308 deletions

View file

@ -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(

View 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
View 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)
}
}

View file

@ -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(&microcodeVersion, "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)
}