mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-02-25 09:11:24 -05:00
config: automatically upload new Azure SNP versions to API + sign version with release key (#1854)
* sign version with release key and remove version from fetcher interface * extend azure-reporter GH action to upload updated version values to the Attestation API
This commit is contained in:
parent
18da9b8128
commit
a813760f96
21
.github/workflows/azure-snp-reporter.yml
vendored
21
.github/workflows/azure-snp-reporter.yml
vendored
@ -49,7 +49,10 @@ jobs:
|
|||||||
|
|
||||||
validate-snp-report:
|
validate-snp-report:
|
||||||
needs: fetch-snp-report
|
needs: fetch-snp-report
|
||||||
name: "Validate SNP report"
|
name: "Validate SNP report and update Attestation API"
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: read
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
env:
|
env:
|
||||||
SHELL: /bin/bash
|
SHELL: /bin/bash
|
||||||
@ -73,4 +76,18 @@ jobs:
|
|||||||
|
|
||||||
- name: Verify report
|
- name: Verify report
|
||||||
shell: bash
|
shell: bash
|
||||||
run: go run ./hack/azure-snp-report-verify/verify.go "$(cat ./maa-report.jwt)"
|
run: go run ./hack/azure-snp-report-verify/verify.go --report "$(cat ./maa-report.jwt)" --export-path azure-snp-version.json
|
||||||
|
|
||||||
|
- name: Login to AWS
|
||||||
|
uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # v2.0.0
|
||||||
|
with:
|
||||||
|
role-to-assume: arn:aws:iam::795746500882:role/GitHubConstellationImagePipeline
|
||||||
|
aws-region: eu-central-1
|
||||||
|
|
||||||
|
- name: Update Attestation API
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
|
||||||
|
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
|
||||||
|
run: |
|
||||||
|
go run ./hack/configapi/main.go --version-file azure-snp-version.json
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
/e2e @katexochen
|
/e2e @katexochen
|
||||||
/hack/azure-jump-host @malt3
|
/hack/azure-jump-host @malt3
|
||||||
/hack/azure-snp-report-verify @derpsteb
|
/hack/azure-snp-report-verify @derpsteb
|
||||||
|
/hack/configapi @elchead
|
||||||
/hack/bazel-deps-mirror @malt3
|
/hack/bazel-deps-mirror @malt3
|
||||||
/hack/check-licenses.sh @thomasten
|
/hack/check-licenses.sh @thomasten
|
||||||
/hack/clidocgen @thomasten
|
/hack/clidocgen @thomasten
|
||||||
|
@ -299,13 +299,13 @@ func (f fakeConfigFetcher) FetchAzureSEVSNPVersionList(_ context.Context, _ conf
|
|||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f fakeConfigFetcher) FetchAzureSEVSNPVersion(_ context.Context, _ configapi.AzureSEVSNPVersionGet, _ versionsapi.Version) (configapi.AzureSEVSNPVersionGet, error) {
|
func (f fakeConfigFetcher) FetchAzureSEVSNPVersion(_ context.Context, _ configapi.AzureSEVSNPVersionGet) (configapi.AzureSEVSNPVersionGet, error) {
|
||||||
return configapi.AzureSEVSNPVersionGet{
|
return configapi.AzureSEVSNPVersionGet{
|
||||||
AzureSEVSNPVersion: testCfg,
|
AzureSEVSNPVersion: testCfg,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f fakeConfigFetcher) FetchAzureSEVSNPVersionLatest(_ context.Context, _ versionsapi.Version) (configapi.AzureSEVSNPVersionGet, error) {
|
func (f fakeConfigFetcher) FetchAzureSEVSNPVersionLatest(_ context.Context) (configapi.AzureSEVSNPVersionGet, error) {
|
||||||
return configapi.AzureSEVSNPVersionGet{
|
return configapi.AzureSEVSNPVersionGet{
|
||||||
AzureSEVSNPVersion: testCfg,
|
AzureSEVSNPVersion: testCfg,
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -46,12 +46,13 @@ func (i *IsolationTEE) PrintSVNs() {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
configAPIExportPath := flag.String("export-path", "azure-sev-snp-version.json", "Path to the exported config API file.")
|
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()
|
flag.Parse()
|
||||||
if len(os.Args) != 2 {
|
if *maaJWT == "" {
|
||||||
fmt.Println("Usage:", os.Args[0], "<maa-jwt>")
|
fmt.Println("Must provide --report")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
report, err := getTEEReport(os.Args[1])
|
report, err := getTEEReport(*maaJWT)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
load("//bazel/go:go_test.bzl", "go_test")
|
||||||
|
|
||||||
go_library(
|
go_library(
|
||||||
name = "cmd",
|
name = "cmd",
|
||||||
@ -8,7 +9,18 @@ go_library(
|
|||||||
deps = [
|
deps = [
|
||||||
"//internal/api/attestationconfig",
|
"//internal/api/attestationconfig",
|
||||||
"//internal/api/attestationconfig/client",
|
"//internal/api/attestationconfig/client",
|
||||||
|
"//internal/api/attestationconfig/fetcher",
|
||||||
"//internal/staticupload",
|
"//internal/staticupload",
|
||||||
"@com_github_spf13_cobra//:cobra",
|
"@com_github_spf13_cobra//:cobra",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
go_test(
|
||||||
|
name = "cmd_test",
|
||||||
|
srcs = ["root_test.go"],
|
||||||
|
embed = [":cmd"],
|
||||||
|
deps = [
|
||||||
|
"//internal/api/attestationconfig",
|
||||||
|
"@com_github_stretchr_testify//assert",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@ -10,10 +10,13 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
configapi "github.com/edgelesssys/constellation/v2/internal/api/attestationconfig"
|
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfig"
|
||||||
attestationconfigclient "github.com/edgelesssys/constellation/v2/internal/api/attestationconfig/client"
|
attestationconfigclient "github.com/edgelesssys/constellation/v2/internal/api/attestationconfig/client"
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfig/fetcher"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/staticupload"
|
"github.com/edgelesssys/constellation/v2/internal/staticupload"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@ -24,13 +27,15 @@ const (
|
|||||||
invalidDefault = 0
|
invalidDefault = 0
|
||||||
envAwsKeyID = "AWS_ACCESS_KEY_ID"
|
envAwsKeyID = "AWS_ACCESS_KEY_ID"
|
||||||
envAwsKey = "AWS_ACCESS_KEY"
|
envAwsKey = "AWS_ACCESS_KEY"
|
||||||
|
envCosignPwd = "COSIGN_PASSWORD"
|
||||||
|
envCosignPrivateKey = "COSIGN_PRIVATE_KEY"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
versionFilePath string
|
versionFilePath string
|
||||||
// Cosign credentials.
|
// Cosign credentials.
|
||||||
cosignPwd string
|
cosignPwd string
|
||||||
privateKeyPath string
|
privateKey string
|
||||||
)
|
)
|
||||||
|
|
||||||
// Execute executes the root command.
|
// Execute executes the root command.
|
||||||
@ -41,58 +46,102 @@ func Execute() error {
|
|||||||
// newRootCmd creates the root command.
|
// newRootCmd creates the root command.
|
||||||
func newRootCmd() *cobra.Command {
|
func newRootCmd() *cobra.Command {
|
||||||
rootCmd := &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",
|
Use: "COSIGN_PASSWORD=$CPWD COSIGN_PRIVATE_KEY=$CKEY AWS_ACCESS_KEY_ID=$ID AWS_ACCESS_KEY=$KEY upload --version-file $FILE",
|
||||||
Short: "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.",
|
||||||
|
|
||||||
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.",
|
Long: fmt.Sprintf("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. Set the %s and %s environment variables to authenticate with cosign.", envCosignPrivateKey, envCosignPwd),
|
||||||
|
PreRunE: envCheck,
|
||||||
RunE: runCmd,
|
RunE: runCmd,
|
||||||
}
|
}
|
||||||
rootCmd.PersistentFlags().StringVarP(&versionFilePath, "version-file", "f", "", "File path to the version json file.")
|
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.")
|
must(enforceRequiredFlags(rootCmd, "version-file"))
|
||||||
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
|
return rootCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func envCheck(_ *cobra.Command, _ []string) error {
|
||||||
|
if os.Getenv(envCosignPrivateKey) == "" || os.Getenv(envCosignPwd) == "" {
|
||||||
|
return fmt.Errorf("please set both %s and %s environment variables", envCosignPrivateKey, envCosignPwd)
|
||||||
|
}
|
||||||
|
cosignPwd = os.Getenv(envCosignPwd)
|
||||||
|
privateKey = os.Getenv(envCosignPrivateKey)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func runCmd(cmd *cobra.Command, _ []string) error {
|
func runCmd(cmd *cobra.Command, _ []string) error {
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
cfg := staticupload.Config{
|
cfg := staticupload.Config{
|
||||||
Bucket: awsBucket,
|
Bucket: awsBucket,
|
||||||
Region: awsRegion,
|
Region: awsRegion,
|
||||||
}
|
}
|
||||||
privateKey, err := os.ReadFile(privateKeyPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("reading private key: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
versionBytes, err := os.ReadFile(versionFilePath)
|
versionBytes, err := os.ReadFile(versionFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("reading version file: %w", err)
|
return fmt.Errorf("reading version file: %w", err)
|
||||||
}
|
}
|
||||||
var versions configapi.AzureSEVSNPVersion
|
var inputVersion attestationconfig.AzureSEVSNPVersion
|
||||||
err = json.Unmarshal(versionBytes, &versions)
|
if err = json.Unmarshal(versionBytes, &inputVersion); err != nil {
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unmarshalling version file: %w", err)
|
return fmt.Errorf("unmarshalling version file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sut, sutClose, err := attestationconfigclient.New(ctx, cfg, []byte(cosignPwd), privateKey)
|
latestAPIVersion, err := fetcher.New().FetchAzureSEVSNPVersionLatest(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating repo: %w", err)
|
return fmt.Errorf("fetching latest version: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isNewer, err := isInputNewerThanLatestAPI(inputVersion, latestAPIVersion.AzureSEVSNPVersion)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("comparing versions: %w", err)
|
||||||
|
}
|
||||||
|
if isNewer {
|
||||||
|
fmt.Printf("Input version: %+v is newer than latest API version: %+v\n", inputVersion, latestAPIVersion)
|
||||||
|
sut, sutClose, err := attestationconfigclient.New(ctx, cfg, []byte(cosignPwd), []byte(privateKey))
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := sutClose(ctx); err != nil {
|
if err := sutClose(ctx); err != nil {
|
||||||
fmt.Printf("closing repo: %v\n", err)
|
fmt.Printf("closing repo: %v\n", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("creating repo: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
if err := sut.UploadAzureSEVSNP(ctx, versions, time.Now()); err != nil {
|
if err := sut.UploadAzureSEVSNP(ctx, inputVersion, time.Now()); err != nil {
|
||||||
return fmt.Errorf("uploading version: %w", err)
|
return fmt.Errorf("uploading version: %w", err)
|
||||||
}
|
}
|
||||||
cmd.Printf("Successfully uploaded new Azure SEV-SNP version: %+v\n", versions)
|
cmd.Printf("Successfully uploaded new Azure SEV-SNP version: %+v\n", inputVersion)
|
||||||
|
} else {
|
||||||
|
cmd.Printf("Input version: %+v is not newer than latest API version: %+v\n", inputVersion, latestAPIVersion)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isInputNewerThanLatestAPI compares all version fields with the latest API version and returns true if any input field is newer.
|
||||||
|
func isInputNewerThanLatestAPI(input, latest attestationconfig.AzureSEVSNPVersion) (bool, error) {
|
||||||
|
inputValues := reflect.ValueOf(input)
|
||||||
|
latestValues := reflect.ValueOf(latest)
|
||||||
|
fields := reflect.TypeOf(input)
|
||||||
|
num := fields.NumField()
|
||||||
|
// validate that no input field is smaller than latest
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
field := fields.Field(i)
|
||||||
|
inputValue := inputValues.Field(i).Uint()
|
||||||
|
latestValue := latestValues.Field(i).Uint()
|
||||||
|
if inputValue < latestValue {
|
||||||
|
return false, fmt.Errorf("input %s version: %d is older than latest API version: %d", field.Name, inputValue, latestValue)
|
||||||
|
} else if inputValue > latestValue {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check if any input field is greater than latest
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
inputValue := inputValues.Field(i).Uint()
|
||||||
|
latestValue := latestValues.Field(i).Uint()
|
||||||
|
if inputValue > latestValue {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
func enforceRequiredFlags(cmd *cobra.Command, flags ...string) error {
|
func enforceRequiredFlags(cmd *cobra.Command, flags ...string) error {
|
||||||
for _, flag := range flags {
|
for _, flag := range flags {
|
||||||
if err := cmd.MarkPersistentFlagRequired(flag); err != nil {
|
if err := cmd.MarkPersistentFlagRequired(flag); err != nil {
|
||||||
|
75
hack/configapi/cmd/root_test.go
Normal file
75
hack/configapi/cmd/root_test.go
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) Edgeless Systems GmbH
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfig"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testCfg = attestationconfig.AzureSEVSNPVersion{
|
||||||
|
Microcode: 93,
|
||||||
|
TEE: 0,
|
||||||
|
SNP: 6,
|
||||||
|
Bootloader: 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsInputNewerThanLatestAPI(t *testing.T) {
|
||||||
|
testCases := map[string]struct {
|
||||||
|
latest attestationconfig.AzureSEVSNPVersion
|
||||||
|
input attestationconfig.AzureSEVSNPVersion
|
||||||
|
expect bool
|
||||||
|
errMsg string
|
||||||
|
}{
|
||||||
|
"input is older than latest": {
|
||||||
|
input: func(c attestationconfig.AzureSEVSNPVersion) attestationconfig.AzureSEVSNPVersion {
|
||||||
|
c.Microcode--
|
||||||
|
return c
|
||||||
|
}(testCfg),
|
||||||
|
latest: testCfg,
|
||||||
|
expect: false,
|
||||||
|
errMsg: "input Microcode version: 92 is older than latest API version: 93",
|
||||||
|
},
|
||||||
|
"input has greater and smaller version field than latest": {
|
||||||
|
input: func(c attestationconfig.AzureSEVSNPVersion) attestationconfig.AzureSEVSNPVersion {
|
||||||
|
c.Microcode++
|
||||||
|
c.Bootloader--
|
||||||
|
return c
|
||||||
|
}(testCfg),
|
||||||
|
latest: testCfg,
|
||||||
|
expect: false,
|
||||||
|
errMsg: "input Bootloader version: 1 is older than latest API version: 2",
|
||||||
|
},
|
||||||
|
"input is newer than latest": {
|
||||||
|
input: func(c attestationconfig.AzureSEVSNPVersion) attestationconfig.AzureSEVSNPVersion {
|
||||||
|
c.TEE++
|
||||||
|
return c
|
||||||
|
}(testCfg),
|
||||||
|
latest: testCfg,
|
||||||
|
expect: true,
|
||||||
|
},
|
||||||
|
"input is equal to latest": {
|
||||||
|
input: testCfg,
|
||||||
|
latest: testCfg,
|
||||||
|
expect: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, tc := range testCases {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
isNewer, err := isInputNewerThanLatestAPI(tc.input, tc.latest)
|
||||||
|
assert := assert.New(t)
|
||||||
|
if tc.errMsg != "" {
|
||||||
|
assert.EqualError(err, tc.errMsg)
|
||||||
|
} else {
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.Equal(tc.expect, isNewer)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@ go_library(
|
|||||||
deps = [
|
deps = [
|
||||||
"//internal/api/attestationconfig",
|
"//internal/api/attestationconfig",
|
||||||
"//internal/api/fetcher",
|
"//internal/api/fetcher",
|
||||||
"//internal/api/versions",
|
"//internal/constants",
|
||||||
"//internal/sigstore",
|
"//internal/sigstore",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -20,8 +20,6 @@ go_test(
|
|||||||
embed = [":fetcher"],
|
embed = [":fetcher"],
|
||||||
deps = [
|
deps = [
|
||||||
"//internal/api/attestationconfig",
|
"//internal/api/attestationconfig",
|
||||||
"//internal/api/versions",
|
|
||||||
"@com_github_stretchr_testify//assert",
|
"@com_github_stretchr_testify//assert",
|
||||||
"@com_github_stretchr_testify//require",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -16,15 +16,17 @@ import (
|
|||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfig"
|
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfig"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/api/fetcher"
|
"github.com/edgelesssys/constellation/v2/internal/api/fetcher"
|
||||||
versionsapi "github.com/edgelesssys/constellation/v2/internal/api/versions"
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/sigstore"
|
"github.com/edgelesssys/constellation/v2/internal/sigstore"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const cosignPublicKey = constants.CosignPublicKeyReleases
|
||||||
|
|
||||||
// AttestationConfigAPIFetcher fetches config API resources without authentication.
|
// AttestationConfigAPIFetcher fetches config API resources without authentication.
|
||||||
type AttestationConfigAPIFetcher interface {
|
type AttestationConfigAPIFetcher interface {
|
||||||
FetchAzureSEVSNPVersion(ctx context.Context, azureVersion attestationconfig.AzureSEVSNPVersionGet, version versionsapi.Version) (attestationconfig.AzureSEVSNPVersionGet, error)
|
FetchAzureSEVSNPVersion(ctx context.Context, azureVersion attestationconfig.AzureSEVSNPVersionGet) (attestationconfig.AzureSEVSNPVersionGet, error)
|
||||||
FetchAzureSEVSNPVersionList(ctx context.Context, attestation attestationconfig.AzureSEVSNPVersionList) (attestationconfig.AzureSEVSNPVersionList, error)
|
FetchAzureSEVSNPVersionList(ctx context.Context, attestation attestationconfig.AzureSEVSNPVersionList) (attestationconfig.AzureSEVSNPVersionList, error)
|
||||||
FetchAzureSEVSNPVersionLatest(ctx context.Context, version versionsapi.Version) (attestationconfig.AzureSEVSNPVersionGet, error)
|
FetchAzureSEVSNPVersionLatest(ctx context.Context) (attestationconfig.AzureSEVSNPVersionGet, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetcher fetches AttestationCfg API resources without authentication.
|
// Fetcher fetches AttestationCfg API resources without authentication.
|
||||||
@ -48,16 +50,12 @@ func (f *Fetcher) FetchAzureSEVSNPVersionList(ctx context.Context, attestation a
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FetchAzureSEVSNPVersion fetches the version information from the config API.
|
// FetchAzureSEVSNPVersion fetches the version information from the config API.
|
||||||
func (f *Fetcher) FetchAzureSEVSNPVersion(ctx context.Context, attestation attestationconfig.AzureSEVSNPVersionGet, version versionsapi.Version) (attestationconfig.AzureSEVSNPVersionGet, error) {
|
func (f *Fetcher) FetchAzureSEVSNPVersion(ctx context.Context, azureVersion attestationconfig.AzureSEVSNPVersionGet) (attestationconfig.AzureSEVSNPVersionGet, error) {
|
||||||
cosignPublicKey, err := sigstore.CosignPublicKeyForVersion(version)
|
urlString, err := azureVersion.URL()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return attestationconfig.AzureSEVSNPVersionGet{}, fmt.Errorf("get public key for config: %w", err)
|
return azureVersion, err
|
||||||
}
|
}
|
||||||
urlString, err := attestation.URL()
|
fetchedVersion, err := fetcher.Fetch(ctx, f.HTTPClient, azureVersion)
|
||||||
if err != nil {
|
|
||||||
return attestationconfig.AzureSEVSNPVersionGet{}, err
|
|
||||||
}
|
|
||||||
fetchedVersion, err := fetcher.Fetch(ctx, f.HTTPClient, attestation)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fetchedVersion, fmt.Errorf("fetch version %s: %w", fetchedVersion.Version, err)
|
return fetchedVersion, fmt.Errorf("fetch version %s: %w", fetchedVersion.Version, err)
|
||||||
}
|
}
|
||||||
@ -71,7 +69,7 @@ func (f *Fetcher) FetchAzureSEVSNPVersion(ctx context.Context, attestation attes
|
|||||||
return fetchedVersion, fmt.Errorf("fetch version %s signature: %w", fetchedVersion.Version, err)
|
return fetchedVersion, fmt.Errorf("fetch version %s signature: %w", fetchedVersion.Version, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sigstore.CosignVerifier{}.VerifySignature(versionBytes, signature, cosignPublicKey)
|
err = sigstore.CosignVerifier{}.VerifySignature(versionBytes, signature, []byte(cosignPublicKey))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fetchedVersion, fmt.Errorf("verify version %s signature: %w", fetchedVersion.Version, err)
|
return fetchedVersion, fmt.Errorf("verify version %s signature: %w", fetchedVersion.Version, err)
|
||||||
}
|
}
|
||||||
@ -79,14 +77,14 @@ func (f *Fetcher) FetchAzureSEVSNPVersion(ctx context.Context, attestation attes
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FetchAzureSEVSNPVersionLatest returns the latest versions of the given type.
|
// FetchAzureSEVSNPVersionLatest returns the latest versions of the given type.
|
||||||
func (f *Fetcher) FetchAzureSEVSNPVersionLatest(ctx context.Context, version versionsapi.Version) (res attestationconfig.AzureSEVSNPVersionGet, err error) {
|
func (f *Fetcher) FetchAzureSEVSNPVersionLatest(ctx context.Context) (res attestationconfig.AzureSEVSNPVersionGet, err error) {
|
||||||
var list attestationconfig.AzureSEVSNPVersionList
|
var list attestationconfig.AzureSEVSNPVersionList
|
||||||
list, err = f.FetchAzureSEVSNPVersionList(ctx, list)
|
list, err = f.FetchAzureSEVSNPVersionList(ctx, list)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, fmt.Errorf("fetching versions list: %w", err)
|
return res, fmt.Errorf("fetching versions list: %w", err)
|
||||||
}
|
}
|
||||||
get := attestationconfig.AzureSEVSNPVersionGet{Version: list[0]} // get latest version (as sorted reversely alphanumerically)
|
get := attestationconfig.AzureSEVSNPVersionGet{Version: list[0]} // get latest version (as sorted reversely alphanumerically)
|
||||||
get, err = f.FetchAzureSEVSNPVersion(ctx, get, version)
|
get, err = f.FetchAzureSEVSNPVersion(ctx, get)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, fmt.Errorf("failed fetching version: %w", err)
|
return res, fmt.Errorf("failed fetching version: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
configapi "github.com/edgelesssys/constellation/v2/internal/api/attestationconfig"
|
configapi "github.com/edgelesssys/constellation/v2/internal/api/attestationconfig"
|
||||||
versionsapi "github.com/edgelesssys/constellation/v2/internal/api/versions"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var testCfg = configapi.AzureSEVSNPVersionGet{
|
var testCfg = configapi.AzureSEVSNPVersionGet{
|
||||||
@ -36,7 +34,7 @@ func TestFetchLatestAzureSEVSNPVersion(t *testing.T) {
|
|||||||
want configapi.AzureSEVSNPVersionGet
|
want configapi.AzureSEVSNPVersionGet
|
||||||
}{
|
}{
|
||||||
"get version with valid signature": {
|
"get version with valid signature": {
|
||||||
signature: []byte("MEUCIQDNn6wiSh9Nz9mtU9RvxvfkH3fNDFGeqopjTIRoBNkyrAIgSsKgdYNQXvPevaLWmmpnj/9WcgrltAQ+KfI+bQfklAo="),
|
signature: []byte("MEQCIBPEbYg89MIQuaGStLhKGLGMKvKFoYCaAniDLwoIwulqAiB+rj7KMaMOMGxmUsjI7KheCXSNM8NzN+tuDw6AywI75A=="), // signed with release key
|
||||||
want: testCfg,
|
want: testCfg,
|
||||||
},
|
},
|
||||||
"fail with invalid signature": {
|
"fail with invalid signature": {
|
||||||
@ -51,13 +49,10 @@ func TestFetchLatestAzureSEVSNPVersion(t *testing.T) {
|
|||||||
signature: tc.signature,
|
signature: tc.signature,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
require := require.New(t)
|
|
||||||
version, err := versionsapi.NewVersionFromShortPath("stream/debug/v9.9.9", versionsapi.VersionKindImage)
|
|
||||||
require.NoError(err)
|
|
||||||
fetcher := NewWithClient(client)
|
fetcher := NewWithClient(client)
|
||||||
|
res, err := fetcher.FetchAzureSEVSNPVersionLatest(context.Background())
|
||||||
|
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
res, err := fetcher.FetchAzureSEVSNPVersionLatest(context.Background(), version)
|
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
} else {
|
} else {
|
||||||
|
@ -53,7 +53,6 @@ go_test(
|
|||||||
embed = [":config"],
|
embed = [":config"],
|
||||||
deps = [
|
deps = [
|
||||||
"//internal/api/attestationconfig",
|
"//internal/api/attestationconfig",
|
||||||
"//internal/api/versions",
|
|
||||||
"//internal/attestation/measurements",
|
"//internal/attestation/measurements",
|
||||||
"//internal/cloud/cloudprovider",
|
"//internal/cloud/cloudprovider",
|
||||||
"//internal/config/instancetypes",
|
"//internal/config/instancetypes",
|
||||||
|
@ -13,7 +13,6 @@ import (
|
|||||||
|
|
||||||
configapi "github.com/edgelesssys/constellation/v2/internal/api/attestationconfig"
|
configapi "github.com/edgelesssys/constellation/v2/internal/api/attestationconfig"
|
||||||
attestationconfigfetcher "github.com/edgelesssys/constellation/v2/internal/api/attestationconfig/fetcher"
|
attestationconfigfetcher "github.com/edgelesssys/constellation/v2/internal/api/attestationconfig/fetcher"
|
||||||
versionsapi "github.com/edgelesssys/constellation/v2/internal/api/versions"
|
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
|
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
|
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
|
||||||
@ -98,8 +97,8 @@ func (c AzureSEVSNP) EqualTo(old AttestationCfg) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FetchAndSetLatestVersionNumbers fetches the latest version numbers from the configapi and sets them.
|
// FetchAndSetLatestVersionNumbers fetches the latest version numbers from the configapi and sets them.
|
||||||
func (c *AzureSEVSNP) FetchAndSetLatestVersionNumbers(fetcher attestationconfigfetcher.AttestationConfigAPIFetcher, version versionsapi.Version) error {
|
func (c *AzureSEVSNP) FetchAndSetLatestVersionNumbers(fetcher attestationconfigfetcher.AttestationConfigAPIFetcher) error {
|
||||||
versions, err := fetcher.FetchAzureSEVSNPVersionLatest(context.Background(), version)
|
versions, err := fetcher.FetchAzureSEVSNPVersionLatest(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,6 @@ import (
|
|||||||
en_translations "github.com/go-playground/validator/v10/translations/en"
|
en_translations "github.com/go-playground/validator/v10/translations/en"
|
||||||
|
|
||||||
attestationconfigfetcher "github.com/edgelesssys/constellation/v2/internal/api/attestationconfig/fetcher"
|
attestationconfigfetcher "github.com/edgelesssys/constellation/v2/internal/api/attestationconfig/fetcher"
|
||||||
versionsapi "github.com/edgelesssys/constellation/v2/internal/api/versions"
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
|
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
|
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||||
@ -393,11 +392,7 @@ func New(fileHandler file.Handler, name string, fetcher attestationconfigfetcher
|
|||||||
}
|
}
|
||||||
|
|
||||||
if azure := c.Attestation.AzureSEVSNP; azure != nil {
|
if azure := c.Attestation.AzureSEVSNP; azure != nil {
|
||||||
version, err := versionsapi.NewVersionFromShortPath(c.Image, versionsapi.VersionKindImage)
|
if err := azure.FetchAndSetLatestVersionNumbers(fetcher); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := azure.FetchAndSetLatestVersionNumbers(fetcher, version); err != nil {
|
|
||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ import (
|
|||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
configapi "github.com/edgelesssys/constellation/v2/internal/api/attestationconfig"
|
configapi "github.com/edgelesssys/constellation/v2/internal/api/attestationconfig"
|
||||||
versionsapi "github.com/edgelesssys/constellation/v2/internal/api/versions"
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
|
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/config/instancetypes"
|
"github.com/edgelesssys/constellation/v2/internal/config/instancetypes"
|
||||||
@ -886,13 +885,13 @@ func (f fakeConfigFetcher) FetchAzureSEVSNPVersionList(_ context.Context, _ conf
|
|||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f fakeConfigFetcher) FetchAzureSEVSNPVersion(_ context.Context, _ configapi.AzureSEVSNPVersionGet, _ versionsapi.Version) (configapi.AzureSEVSNPVersionGet, error) {
|
func (f fakeConfigFetcher) FetchAzureSEVSNPVersion(_ context.Context, _ configapi.AzureSEVSNPVersionGet) (configapi.AzureSEVSNPVersionGet, error) {
|
||||||
return configapi.AzureSEVSNPVersionGet{
|
return configapi.AzureSEVSNPVersionGet{
|
||||||
AzureSEVSNPVersion: testCfg,
|
AzureSEVSNPVersion: testCfg,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f fakeConfigFetcher) FetchAzureSEVSNPVersionLatest(_ context.Context, _ versionsapi.Version) (configapi.AzureSEVSNPVersionGet, error) {
|
func (f fakeConfigFetcher) FetchAzureSEVSNPVersionLatest(_ context.Context) (configapi.AzureSEVSNPVersionGet, error) {
|
||||||
return configapi.AzureSEVSNPVersionGet{
|
return configapi.AzureSEVSNPVersionGet{
|
||||||
AzureSEVSNPVersion: testCfg,
|
AzureSEVSNPVersion: testCfg,
|
||||||
}, nil
|
}, nil
|
||||||
|
Loading…
x
Reference in New Issue
Block a user