Move upload/delete code to its own package

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
Daniel Weiße 2024-06-11 14:50:38 +02:00 committed by Daniel Weiße
parent 5654e76f7e
commit 52a65c20ac
13 changed files with 129 additions and 100 deletions

View File

@ -5,31 +5,23 @@ go_library(
name = "attestationconfigapi",
srcs = [
"attestationconfigapi.go",
"client.go",
"fetcher.go",
"reporter.go",
"snp.go",
],
importpath = "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi",
visibility = ["//:__subpackages__"],
deps = [
"//internal/api/client",
"//internal/api/fetcher",
"//internal/attestation/variant",
"//internal/constants",
"//internal/sigstore",
"//internal/staticupload",
"@com_github_aws_aws_sdk_go//aws",
"@com_github_aws_aws_sdk_go_v2_service_s3//:s3",
],
)
go_test(
name = "attestationconfigapi_test",
srcs = [
"client_test.go",
"fetcher_test.go",
"reporter_test.go",
"snp_test.go",
],
embed = [":attestationconfigapi"],

View File

@ -19,6 +19,7 @@ go_library(
visibility = ["//visibility:private"],
deps = [
"//internal/api/attestationconfigapi",
"//internal/api/attestationconfigapi/cli/client",
"//internal/attestation/variant",
"//internal/cloud/cloudprovider",
"//internal/constants",

View File

@ -0,0 +1,35 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("//bazel/go:go_test.bzl", "go_test")
go_library(
name = "client",
srcs = [
"client.go",
"reporter.go",
],
importpath = "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi/cli/client",
visibility = ["//:__subpackages__"],
deps = [
"//internal/api/attestationconfigapi",
"//internal/api/client",
"//internal/attestation/variant",
"//internal/sigstore",
"//internal/staticupload",
"@com_github_aws_aws_sdk_go//aws",
"@com_github_aws_aws_sdk_go_v2_service_s3//:s3",
],
)
go_test(
name = "client_test",
srcs = [
"client_test.go",
"reporter_test.go",
],
embed = [":client"],
deps = [
"//internal/api/attestationconfigapi",
"//internal/attestation/variant",
"@com_github_stretchr_testify//assert",
],
)

View File

@ -3,7 +3,12 @@ Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package attestationconfigapi
/*
package client contains code to manage CVM versions in Constellation's CDN API.
It is used to upload and delete "latest" versions for AMD SEV-SNP and Intel TDX.
*/
package client
import (
"context"
@ -12,6 +17,7 @@ import (
"log/slog"
"time"
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
apiclient "github.com/edgelesssys/constellation/v2/internal/api/client"
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
"github.com/edgelesssys/constellation/v2/internal/sigstore"
@ -31,8 +37,8 @@ type Client struct {
cacheWindowSize int
}
// NewClient returns a new Client.
func NewClient(ctx context.Context, cfg staticupload.Config, cosignPwd, privateKey []byte, dryRun bool, versionWindowSize int, log *slog.Logger) (*Client, apiclient.CloseFunc, error) {
// New returns a new Client.
func New(ctx context.Context, cfg staticupload.Config, cosignPwd, privateKey []byte, dryRun bool, versionWindowSize int, log *slog.Logger) (*Client, apiclient.CloseFunc, error) {
s3Client, clientClose, err := apiclient.NewClient(ctx, cfg.Region, cfg.Bucket, cfg.DistributionID, dryRun, log)
if err != nil {
return nil, nil, fmt.Errorf("failed to create s3 storage: %w", err)
@ -49,7 +55,7 @@ func NewClient(ctx context.Context, cfg staticupload.Config, cosignPwd, privateK
}
// uploadSEVSNPVersion uploads the latest version numbers of the SEVSNP. Then version name is the UTC timestamp of the date. The /list entry stores the version name + .json suffix.
func (a Client) uploadSEVSNPVersion(ctx context.Context, attestation variant.Variant, version SEVSNPVersion, date time.Time) error {
func (a Client) uploadSEVSNPVersion(ctx context.Context, attestation variant.Variant, version attestationconfigapi.SEVSNPVersion, date time.Time) error {
versions, err := a.List(ctx, attestation)
if err != nil {
return fmt.Errorf("fetch version list: %w", err)
@ -74,32 +80,32 @@ func (a Client) DeleteSEVSNPVersion(ctx context.Context, attestation variant.Var
}
// List returns the list of versions for the given attestation variant.
func (a Client) List(ctx context.Context, attestation variant.Variant) (SEVSNPVersionList, error) {
func (a Client) List(ctx context.Context, attestation variant.Variant) (attestationconfigapi.SEVSNPVersionList, error) {
if !attestation.Equal(variant.AzureSEVSNP{}) &&
!attestation.Equal(variant.AWSSEVSNP{}) &&
!attestation.Equal(variant.GCPSEVSNP{}) {
return SEVSNPVersionList{}, fmt.Errorf("unsupported attestation variant: %s", attestation)
return attestationconfigapi.SEVSNPVersionList{}, fmt.Errorf("unsupported attestation variant: %s", attestation)
}
versions, err := apiclient.Fetch(ctx, a.s3Client, SEVSNPVersionList{variant: attestation})
versions, err := apiclient.Fetch(ctx, a.s3Client, attestationconfigapi.SEVSNPVersionList{Variant: attestation})
if err != nil {
var notFoundErr *apiclient.NotFoundError
if errors.As(err, &notFoundErr) {
return SEVSNPVersionList{variant: attestation}, nil
return attestationconfigapi.SEVSNPVersionList{Variant: attestation}, nil
}
return SEVSNPVersionList{}, err
return attestationconfigapi.SEVSNPVersionList{}, err
}
versions.variant = attestation
versions.Variant = attestation
return versions, nil
}
func (a Client) deleteSEVSNPVersion(versions SEVSNPVersionList, versionStr string) (ops []crudCmd, err error) {
func (a Client) deleteSEVSNPVersion(versions attestationconfigapi.SEVSNPVersionList, versionStr string) (ops []crudCmd, err error) {
versionStr = versionStr + ".json"
ops = append(ops, deleteCmd{
apiObject: SEVSNPVersionAPI{
Variant: versions.variant,
apiObject: attestationconfigapi.SEVSNPVersionAPI{
Variant: versions.Variant,
Version: versionStr,
},
})
@ -115,8 +121,8 @@ func (a Client) deleteSEVSNPVersion(versions SEVSNPVersionList, versionStr strin
return ops, nil
}
func (a Client) constructUploadCmd(attestation variant.Variant, version SEVSNPVersion, versionNames SEVSNPVersionList, date time.Time) []crudCmd {
if !attestation.Equal(versionNames.variant) {
func (a Client) constructUploadCmd(attestation variant.Variant, version attestationconfigapi.SEVSNPVersion, versionNames attestationconfigapi.SEVSNPVersionList, date time.Time) []crudCmd {
if !attestation.Equal(versionNames.Variant) {
return nil
}
@ -124,11 +130,11 @@ func (a Client) constructUploadCmd(attestation variant.Variant, version SEVSNPVe
var res []crudCmd
res = append(res, putCmd{
apiObject: SEVSNPVersionAPI{Version: dateStr, Variant: attestation, SEVSNPVersion: version},
apiObject: attestationconfigapi.SEVSNPVersionAPI{Version: dateStr, Variant: attestation, SEVSNPVersion: version},
signer: a.signer,
})
versionNames.addVersion(dateStr)
versionNames.AddVersion(dateStr)
res = append(res, putCmd{
apiObject: versionNames,
@ -138,19 +144,19 @@ func (a Client) constructUploadCmd(attestation variant.Variant, version SEVSNPVe
return res
}
func removeVersion(list SEVSNPVersionList, versionStr string) (removedVersions SEVSNPVersionList, err error) {
versions := list.List()
func removeVersion(list attestationconfigapi.SEVSNPVersionList, versionStr string) (removedVersions attestationconfigapi.SEVSNPVersionList, err error) {
versions := list.List
for i, v := range versions {
if v == versionStr {
if i == len(versions)-1 {
removedVersions = SEVSNPVersionList{list: versions[:i], variant: list.variant}
removedVersions = attestationconfigapi.SEVSNPVersionList{List: versions[:i], Variant: list.Variant}
} else {
removedVersions = SEVSNPVersionList{list: append(versions[:i], versions[i+1:]...), variant: list.variant}
removedVersions = attestationconfigapi.SEVSNPVersionList{List: append(versions[:i], versions[i+1:]...), Variant: list.Variant}
}
return removedVersions, nil
}
}
return SEVSNPVersionList{}, fmt.Errorf("version %s not found in list %v", versionStr, versions)
return attestationconfigapi.SEVSNPVersionList{}, fmt.Errorf("version %s not found in list %v", versionStr, versions)
}
type crudCmd interface {

View File

@ -3,12 +3,13 @@ Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package attestationconfigapi
package client
import (
"testing"
"time"
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
"github.com/stretchr/testify/assert"
)
@ -18,13 +19,13 @@ func TestUploadAzureSEVSNP(t *testing.T) {
bucketID: "bucket",
signer: fakeSigner{},
}
version := SEVSNPVersion{}
version := attestationconfigapi.SEVSNPVersion{}
date := time.Date(2023, 1, 1, 1, 1, 1, 1, time.UTC)
ops := sut.constructUploadCmd(variant.AzureSEVSNP{}, version, SEVSNPVersionList{list: []string{"2021-01-01-01-01.json", "2019-01-01-01-01.json"}, variant: variant.AzureSEVSNP{}}, date)
ops := sut.constructUploadCmd(variant.AzureSEVSNP{}, version, attestationconfigapi.SEVSNPVersionList{List: []string{"2021-01-01-01-01.json", "2019-01-01-01-01.json"}, Variant: variant.AzureSEVSNP{}}, date)
dateStr := "2023-01-01-01-01.json"
assert := assert.New(t)
assert.Contains(ops, putCmd{
apiObject: SEVSNPVersionAPI{
apiObject: attestationconfigapi.SEVSNPVersionAPI{
Variant: variant.AzureSEVSNP{},
Version: dateStr,
SEVSNPVersion: version,
@ -32,7 +33,7 @@ func TestUploadAzureSEVSNP(t *testing.T) {
signer: fakeSigner{},
})
assert.Contains(ops, putCmd{
apiObject: SEVSNPVersionList{variant: variant.AzureSEVSNP{}, list: []string{"2023-01-01-01-01.json", "2021-01-01-01-01.json", "2019-01-01-01-01.json"}},
apiObject: attestationconfigapi.SEVSNPVersionList{Variant: variant.AzureSEVSNP{}, List: []string{"2023-01-01-01-01.json", "2021-01-01-01-01.json", "2019-01-01-01-01.json"}},
signer: fakeSigner{},
})
}
@ -41,20 +42,20 @@ func TestDeleteAzureSEVSNPVersions(t *testing.T) {
sut := Client{
bucketID: "bucket",
}
versions := SEVSNPVersionList{list: []string{"2023-01-01.json", "2021-01-01.json", "2019-01-01.json"}}
versions := attestationconfigapi.SEVSNPVersionList{List: []string{"2023-01-01.json", "2021-01-01.json", "2019-01-01.json"}}
ops, err := sut.deleteSEVSNPVersion(versions, "2021-01-01")
assert := assert.New(t)
assert.NoError(err)
assert.Contains(ops, deleteCmd{
apiObject: SEVSNPVersionAPI{
apiObject: attestationconfigapi.SEVSNPVersionAPI{
Version: "2021-01-01.json",
},
})
assert.Contains(ops, putCmd{
apiObject: SEVSNPVersionList{list: []string{"2023-01-01.json", "2019-01-01.json"}},
apiObject: attestationconfigapi.SEVSNPVersionList{List: []string{"2023-01-01.json", "2019-01-01.json"}},
})
}

View File

@ -4,12 +4,7 @@ Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
/*
The reporter contains the logic to determine a latest version for SEVSNP based on cached version values observed on CVM instances.
Some code in this file (e.g. listing cached files) does not rely on dedicated API objects and instead uses the AWS SDK directly,
for no other reason than original development speed.
*/
package attestationconfigapi
package client
import (
"context"
@ -23,6 +18,7 @@ import (
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go/aws"
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
"github.com/edgelesssys/constellation/v2/internal/api/client"
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
)
@ -34,7 +30,7 @@ const cachedVersionsSubDir = "cached-versions"
var ErrNoNewerVersion = errors.New("input version is not newer than latest API version")
func reportVersionDir(attestation variant.Variant) string {
return path.Join(AttestationURLPath, attestation.String(), cachedVersionsSubDir)
return path.Join(attestationconfigapi.AttestationURLPath, attestation.String(), cachedVersionsSubDir)
}
// UploadSEVSNPVersionLatest saves the given version to the cache, determines the smallest
@ -42,7 +38,7 @@ func reportVersionDir(attestation variant.Variant) string {
// the latest version in the API if there is an update.
// force can be used to bypass the validation logic against the cached versions.
func (c Client) UploadSEVSNPVersionLatest(ctx context.Context, attestation variant.Variant, inputVersion,
latestAPIVersion SEVSNPVersion, now time.Time, force bool,
latestAPIVersion attestationconfigapi.SEVSNPVersion, now time.Time, force bool,
) error {
if err := c.cacheSEVSNPVersion(ctx, attestation, inputVersion, now); err != nil {
return fmt.Errorf("reporting version: %w", err)
@ -84,7 +80,7 @@ func (c Client) UploadSEVSNPVersionLatest(ctx context.Context, attestation varia
}
// cacheSEVSNPVersion uploads the latest observed version numbers of the SEVSNP. This version is used to later report the latest version numbers to the API.
func (c Client) cacheSEVSNPVersion(ctx context.Context, attestation variant.Variant, version SEVSNPVersion, date time.Time) error {
func (c Client) cacheSEVSNPVersion(ctx context.Context, attestation variant.Variant, version attestationconfigapi.SEVSNPVersion, date time.Time) error {
dateStr := date.Format(VersionFormat) + ".json"
res := putCmd{
apiObject: reportedSEVSNPVersionAPI{Version: dateStr, variant: attestation, SEVSNPVersion: version},
@ -112,8 +108,8 @@ func (c Client) listCachedVersions(ctx context.Context, attestation variant.Vari
}
// findMinVersion finds the minimal version of the given version dates among the latest values in the version window size.
func (c Client) findMinVersion(ctx context.Context, attesation variant.Variant, versionDates []string) (SEVSNPVersion, string, error) {
var minimalVersion *SEVSNPVersion
func (c Client) findMinVersion(ctx context.Context, attesation variant.Variant, versionDates []string) (attestationconfigapi.SEVSNPVersion, string, error) {
var minimalVersion *attestationconfigapi.SEVSNPVersion
var minimalDate string
sort.Sort(sort.Reverse(sort.StringSlice(versionDates))) // sort in reverse order to slice the latest versions
versionDates = versionDates[:c.cacheWindowSize]
@ -121,7 +117,7 @@ func (c Client) findMinVersion(ctx context.Context, attesation variant.Variant,
for _, date := range versionDates {
obj, err := client.Fetch(ctx, c.s3Client, reportedSEVSNPVersionAPI{Version: date + ".json", variant: attesation})
if err != nil {
return SEVSNPVersion{}, "", fmt.Errorf("get object: %w", err)
return attestationconfigapi.SEVSNPVersion{}, "", fmt.Errorf("get object: %w", err)
}
// Need to set this explicitly as the variant is not part of the marshalled JSON.
obj.variant = attesation
@ -144,7 +140,7 @@ func (c Client) findMinVersion(ctx context.Context, attesation variant.Variant,
}
// isInputNewerThanOtherVersion compares all version fields and returns true if any input field is newer.
func isInputNewerThanOtherVersion(input, other SEVSNPVersion) (bool, error) {
func isInputNewerThanOtherVersion(input, other attestationconfigapi.SEVSNPVersion) (bool, error) {
if input == other {
return false, nil
}
@ -167,7 +163,7 @@ func isInputNewerThanOtherVersion(input, other SEVSNPVersion) (bool, error) {
type reportedSEVSNPVersionAPI struct {
Version string `json:"-"`
variant variant.Variant `json:"-"`
SEVSNPVersion
attestationconfigapi.SEVSNPVersion
}
// JSONPath returns the path to the JSON file for the request to the config api.

View File

@ -2,17 +2,18 @@
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package attestationconfigapi
package client
import (
"testing"
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
"github.com/stretchr/testify/assert"
)
func TestIsInputNewerThanLatestAPI(t *testing.T) {
newTestCfg := func() SEVSNPVersion {
return SEVSNPVersion{
newTestCfg := func() attestationconfigapi.SEVSNPVersion {
return attestationconfigapi.SEVSNPVersion{
Microcode: 93,
TEE: 0,
SNP: 6,
@ -21,13 +22,13 @@ func TestIsInputNewerThanLatestAPI(t *testing.T) {
}
testCases := map[string]struct {
latest SEVSNPVersion
input SEVSNPVersion
latest attestationconfigapi.SEVSNPVersion
input attestationconfigapi.SEVSNPVersion
expect bool
errMsg string
}{
"input is older than latest": {
input: func(c SEVSNPVersion) SEVSNPVersion {
input: func(c attestationconfigapi.SEVSNPVersion) attestationconfigapi.SEVSNPVersion {
c.Microcode--
return c
}(newTestCfg()),
@ -36,7 +37,7 @@ func TestIsInputNewerThanLatestAPI(t *testing.T) {
errMsg: "input Microcode version: 92 is older than latest API version: 93",
},
"input has greater and smaller version field than latest": {
input: func(c SEVSNPVersion) SEVSNPVersion {
input: func(c attestationconfigapi.SEVSNPVersion) attestationconfigapi.SEVSNPVersion {
c.Microcode++
c.Bootloader--
return c
@ -46,7 +47,7 @@ func TestIsInputNewerThanLatestAPI(t *testing.T) {
errMsg: "input Bootloader version: 1 is older than latest API version: 2",
},
"input is newer than latest": {
input: func(c SEVSNPVersion) SEVSNPVersion {
input: func(c attestationconfigapi.SEVSNPVersion) attestationconfigapi.SEVSNPVersion {
c.TEE++
return c
}(newTestCfg()),

View File

@ -16,6 +16,7 @@ import (
"github.com/aws/aws-sdk-go-v2/service/s3"
s3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi/cli/client"
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/logger"
@ -62,7 +63,7 @@ func runDelete(cmd *cobra.Command, args []string) (retErr error) {
Region: deleteCfg.region,
DistributionID: deleteCfg.distribution,
}
client, clientClose, err := attestationconfigapi.NewClient(cmd.Context(), cfg,
client, clientClose, err := client.New(cmd.Context(), cfg,
[]byte(cosignPwd), []byte(privateKey), false, 1, log)
if err != nil {
return fmt.Errorf("create attestation client: %w", err)
@ -170,7 +171,7 @@ func newDeleteConfig(cmd *cobra.Command, args [3]string) (deleteConfig, error) {
}, nil
}
func deleteEntry(ctx context.Context, attvar variant.Variant, client *attestationconfigapi.Client, cfg deleteConfig) error {
func deleteEntry(ctx context.Context, attvar variant.Variant, client *client.Client, cfg deleteConfig) error {
if cfg.kind != snpReport {
return fmt.Errorf("kind %s not supported", cfg.kind)
}

View File

@ -14,6 +14,7 @@ import (
"time"
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi/cli/client"
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/file"
@ -68,18 +69,15 @@ func runUpload(cmd *cobra.Command, args []string) (retErr error) {
return fmt.Errorf("parsing cli flags: %w", err)
}
client, clientClose, err := attestationconfigapi.NewClient(
ctx,
client, clientClose, err := client.New(ctx,
staticupload.Config{
Bucket: uploadCfg.bucket,
Region: uploadCfg.region,
DistributionID: uploadCfg.distribution,
},
[]byte(cosignPwd),
[]byte(privateKey),
false,
uploadCfg.cacheWindowSize,
log)
[]byte(cosignPwd), []byte(privateKey),
false, uploadCfg.cacheWindowSize, log,
)
defer func() {
err := clientClose(cmd.Context())
@ -109,7 +107,7 @@ func runUpload(cmd *cobra.Command, args []string) (retErr error) {
func uploadReport(ctx context.Context,
attestation variant.Variant,
client *attestationconfigapi.Client,
apiClient *client.Client,
cfg uploadConfig,
fs file.Handler,
log *slog.Logger,
@ -137,8 +135,8 @@ func uploadReport(ctx context.Context,
}
latestAPIVersion := latestAPIVersionAPI.SEVSNPVersion
if err := client.UploadSEVSNPVersionLatest(ctx, attestation, inputVersion, latestAPIVersion, cfg.uploadDate, cfg.force); err != nil {
if errors.Is(err, attestationconfigapi.ErrNoNewerVersion) {
if err := apiClient.UploadSEVSNPVersionLatest(ctx, attestation, inputVersion, latestAPIVersion, cfg.uploadDate, cfg.force); err != nil {
if errors.Is(err, client.ErrNoNewerVersion) {
log.Info(fmt.Sprintf("Input version: %+v is not newer than latest API version: %+v", inputVersion, latestAPIVersion))
return nil
}
@ -178,7 +176,7 @@ func newConfig(cmd *cobra.Command, args [3]string) (uploadConfig, error) {
}
uploadDate := time.Now()
if dateStr != "" {
uploadDate, err = time.Parse(attestationconfigapi.VersionFormat, dateStr)
uploadDate, err = time.Parse(client.VersionFormat, dateStr)
if err != nil {
return uploadConfig{}, fmt.Errorf("parsing date: %w", err)
}

View File

@ -39,13 +39,14 @@ const (
// unknown is the default objectKind and does nothing.
unknown objectKind = "unknown-kind"
snpReport objectKind = "snp-report"
tdxReport objectKind = "tdx-report"
guestFirmware objectKind = "guest-firmware"
)
func kindFromString(s string) objectKind {
lower := strings.ToLower(s)
switch objectKind(lower) {
case snpReport, guestFirmware:
case snpReport, guestFirmware, tdxReport:
return objectKind(lower)
default:
return unknown

View File

@ -74,7 +74,7 @@ func (f *fetcher) FetchSEVSNPVersionList(ctx context.Context, list SEVSNPVersion
}
// Need to set this explicitly as the variant is not part of the marshalled JSON.
fetchedList.variant = list.variant
fetchedList.Variant = list.Variant
return fetchedList, nil
}
@ -94,13 +94,13 @@ func (f *fetcher) FetchSEVSNPVersion(ctx context.Context, version SEVSNPVersionA
// FetchSEVSNPVersionLatest returns the latest versions of the given type.
func (f *fetcher) FetchSEVSNPVersionLatest(ctx context.Context, attesation variant.Variant) (res SEVSNPVersionAPI, err error) {
list, err := f.FetchSEVSNPVersionList(ctx, SEVSNPVersionList{variant: attesation})
list, err := f.FetchSEVSNPVersionList(ctx, SEVSNPVersionList{Variant: attesation})
if err != nil {
return res, ErrNoVersionsFound
}
getVersionRequest := SEVSNPVersionAPI{
Version: list.List()[0], // latest version is first in list
Version: list.List[0], // latest version is first in list
Variant: attesation,
}
res, err = f.FetchSEVSNPVersion(ctx, getVersionRequest)

View File

@ -64,26 +64,23 @@ func (i SEVSNPVersionAPI) Validate() error {
// Once we switch to v2 of the API we could embed the variant in the object and remove some code from fetcher & client.
// That would remove the possibility of some fetcher/client code forgetting to set the variant.
type SEVSNPVersionList struct {
variant variant.Variant
list []string
Variant variant.Variant
List []string
}
// MarshalJSON marshals the i's list property to JSON.
func (i SEVSNPVersionList) MarshalJSON() ([]byte, error) {
return json.Marshal(i.list)
return json.Marshal(i.List)
}
// UnmarshalJSON unmarshals a list of strings into i's list property.
func (i *SEVSNPVersionList) UnmarshalJSON(data []byte) error {
return json.Unmarshal(data, &i.list)
return json.Unmarshal(data, &i.List)
}
// List returns i's list property.
func (i SEVSNPVersionList) List() []string { return i.list }
// JSONPath returns the path to the JSON file for the request to the config api.
func (i SEVSNPVersionList) JSONPath() string {
return path.Join(AttestationURLPath, i.variant.String(), "list")
return path.Join(AttestationURLPath, i.Variant.String(), "list")
}
// ValidateRequest is a NoOp as there is no input.
@ -93,20 +90,20 @@ func (i SEVSNPVersionList) ValidateRequest() error {
// SortReverse sorts the list of versions in reverse order.
func (i *SEVSNPVersionList) SortReverse() {
sort.Sort(sort.Reverse(sort.StringSlice(i.list)))
sort.Sort(sort.Reverse(sort.StringSlice(i.List)))
}
// addVersion adds new to i's list and sorts the element in descending order.
func (i *SEVSNPVersionList) addVersion(new string) {
i.list = append(i.list, new)
i.list = variant.RemoveDuplicate(i.list)
// AddVersion adds new to i's list and sorts the element in descending order.
func (i *SEVSNPVersionList) AddVersion(new string) {
i.List = append(i.List, new)
i.List = variant.RemoveDuplicate(i.List)
i.SortReverse()
}
// Validate validates the response.
func (i SEVSNPVersionList) Validate() error {
if len(i.list) < 1 {
if len(i.List) < 1 {
return fmt.Errorf("no versions found in /list")
}
return nil

View File

@ -21,16 +21,16 @@ func TestSEVSNPVersionListMarshalUnmarshalJSON(t *testing.T) {
wantDiff bool
}{
"success": {
input: SEVSNPVersionList{list: []string{"v1", "v2"}},
output: SEVSNPVersionList{list: []string{"v1", "v2"}},
input: SEVSNPVersionList{List: []string{"v1", "v2"}},
output: SEVSNPVersionList{List: []string{"v1", "v2"}},
},
"variant is lost": {
input: SEVSNPVersionList{list: []string{"v1", "v2"}, variant: variant.AzureSEVSNP{}},
output: SEVSNPVersionList{list: []string{"v1", "v2"}},
input: SEVSNPVersionList{List: []string{"v1", "v2"}, Variant: variant.AzureSEVSNP{}},
output: SEVSNPVersionList{List: []string{"v1", "v2"}},
},
"wrong order": {
input: SEVSNPVersionList{list: []string{"v1", "v2"}},
output: SEVSNPVersionList{list: []string{"v2", "v1"}},
input: SEVSNPVersionList{List: []string{"v1", "v2"}},
output: SEVSNPVersionList{List: []string{"v2", "v1"}},
wantDiff: true,
},
}
@ -68,10 +68,10 @@ func TestSEVSNPVersionListAddVersion(t *testing.T) {
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
v := SEVSNPVersionList{list: tc.versions}
v.addVersion(tc.new)
v := SEVSNPVersionList{List: tc.versions}
v.AddVersion(tc.new)
assert.Equal(t, tc.expected, v.list)
assert.Equal(t, tc.expected, v.List)
})
}
}