Skip to content

Commit

Permalink
Enable versions API to handle TDX versions
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Weiße <[email protected]>
  • Loading branch information
daniel-weisse committed Jun 12, 2024
1 parent 139f66d commit 2685666
Show file tree
Hide file tree
Showing 13 changed files with 253 additions and 245 deletions.
14 changes: 2 additions & 12 deletions cli/internal/cmd/configfetchmeasurements_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,18 +204,8 @@ func (f stubVerifyFetcher) FetchAndVerifyMeasurements(_ context.Context, _ strin

type stubAttestationFetcher struct{}

func (f stubAttestationFetcher) FetchSEVSNPVersionList(_ context.Context, _ attestationconfigapi.SEVSNPVersionList) (attestationconfigapi.SEVSNPVersionList, error) {
return attestationconfigapi.SEVSNPVersionList{}, nil
}

func (f stubAttestationFetcher) FetchSEVSNPVersion(_ context.Context, _ attestationconfigapi.SEVSNPVersionAPI) (attestationconfigapi.SEVSNPVersionAPI, error) {
return attestationconfigapi.SEVSNPVersionAPI{
SEVSNPVersion: testCfg,
}, nil
}

func (f stubAttestationFetcher) FetchLatestVersion(_ context.Context, _ variant.Variant) (attestationconfigapi.SEVSNPVersionAPI, error) {
return attestationconfigapi.SEVSNPVersionAPI{
func (f stubAttestationFetcher) FetchLatestVersion(_ context.Context, _ variant.Variant) (attestationconfigapi.VersionAPIEntry, error) {
return attestationconfigapi.VersionAPIEntry{
SEVSNPVersion: testCfg,
}, nil
}
Expand Down
12 changes: 2 additions & 10 deletions cli/internal/cmd/iamupgradeapply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,14 +171,6 @@ type stubConfigFetcher struct {
fetchLatestErr error
}

func (s *stubConfigFetcher) FetchSEVSNPVersion(context.Context, attestationconfigapi.SEVSNPVersionAPI) (attestationconfigapi.SEVSNPVersionAPI, error) {
panic("not implemented")
}

func (s *stubConfigFetcher) FetchSEVSNPVersionList(context.Context, attestationconfigapi.SEVSNPVersionList) (attestationconfigapi.SEVSNPVersionList, error) {
panic("not implemented")
}

func (s *stubConfigFetcher) FetchLatestVersion(context.Context, variant.Variant) (attestationconfigapi.SEVSNPVersionAPI, error) {
return attestationconfigapi.SEVSNPVersionAPI{}, s.fetchLatestErr
func (s *stubConfigFetcher) FetchLatestVersion(context.Context, variant.Variant) (attestationconfigapi.VersionAPIEntry, error) {
return attestationconfigapi.VersionAPIEntry{}, s.fetchLatestErr
}
26 changes: 13 additions & 13 deletions internal/api/attestationconfigapi/cli/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,31 +80,31 @@ 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) (attestationconfigapi.SEVSNPVersionList, error) {
func (a Client) List(ctx context.Context, attestation variant.Variant) (attestationconfigapi.VersionList, error) {
if !attestation.Equal(variant.AzureSEVSNP{}) &&
!attestation.Equal(variant.AWSSEVSNP{}) &&
!attestation.Equal(variant.GCPSEVSNP{}) {
return attestationconfigapi.SEVSNPVersionList{}, fmt.Errorf("unsupported attestation variant: %s", attestation)
return attestationconfigapi.VersionList{}, fmt.Errorf("unsupported attestation variant: %s", attestation)
}

versions, err := apiclient.Fetch(ctx, a.s3Client, attestationconfigapi.SEVSNPVersionList{Variant: attestation})
versions, err := apiclient.Fetch(ctx, a.s3Client, attestationconfigapi.VersionList{Variant: attestation})
if err != nil {
var notFoundErr *apiclient.NotFoundError
if errors.As(err, &notFoundErr) {
return attestationconfigapi.SEVSNPVersionList{Variant: attestation}, nil
return attestationconfigapi.VersionList{Variant: attestation}, nil
}
return attestationconfigapi.SEVSNPVersionList{}, err
return attestationconfigapi.VersionList{}, err
}

versions.Variant = attestation

return versions, nil
}

func (a Client) deleteSEVSNPVersion(versions attestationconfigapi.SEVSNPVersionList, versionStr string) (ops []crudCmd, err error) {
func (a Client) deleteSEVSNPVersion(versions attestationconfigapi.VersionList, versionStr string) (ops []crudCmd, err error) {
versionStr = versionStr + ".json"
ops = append(ops, deleteCmd{
apiObject: attestationconfigapi.SEVSNPVersionAPI{
apiObject: attestationconfigapi.VersionAPIEntry{
Variant: versions.Variant,
Version: versionStr,
},
Expand All @@ -121,7 +121,7 @@ func (a Client) deleteSEVSNPVersion(versions attestationconfigapi.SEVSNPVersionL
return ops, nil
}

func (a Client) constructUploadCmd(attestation variant.Variant, version attestationconfigapi.SEVSNPVersion, versionNames attestationconfigapi.SEVSNPVersionList, date time.Time) []crudCmd {
func (a Client) constructUploadCmd(attestation variant.Variant, version attestationconfigapi.SEVSNPVersion, versionNames attestationconfigapi.VersionList, date time.Time) []crudCmd {
if !attestation.Equal(versionNames.Variant) {
return nil
}
Expand All @@ -130,7 +130,7 @@ func (a Client) constructUploadCmd(attestation variant.Variant, version attestat
var res []crudCmd

res = append(res, putCmd{
apiObject: attestationconfigapi.SEVSNPVersionAPI{Version: dateStr, Variant: attestation, SEVSNPVersion: version},
apiObject: attestationconfigapi.VersionAPIEntry{Version: dateStr, Variant: attestation, SEVSNPVersion: version},
signer: a.signer,
})

Expand All @@ -144,19 +144,19 @@ func (a Client) constructUploadCmd(attestation variant.Variant, version attestat
return res
}

func removeVersion(list attestationconfigapi.SEVSNPVersionList, versionStr string) (removedVersions attestationconfigapi.SEVSNPVersionList, err error) {
func removeVersion(list attestationconfigapi.VersionList, versionStr string) (removedVersions attestationconfigapi.VersionList, err error) {
versions := list.List
for i, v := range versions {
if v == versionStr {
if i == len(versions)-1 {
removedVersions = attestationconfigapi.SEVSNPVersionList{List: versions[:i], Variant: list.Variant}
removedVersions = attestationconfigapi.VersionList{List: versions[:i], Variant: list.Variant}
} else {
removedVersions = attestationconfigapi.SEVSNPVersionList{List: append(versions[:i], versions[i+1:]...), Variant: list.Variant}
removedVersions = attestationconfigapi.VersionList{List: append(versions[:i], versions[i+1:]...), Variant: list.Variant}
}
return removedVersions, nil
}
}
return attestationconfigapi.SEVSNPVersionList{}, fmt.Errorf("version %s not found in list %v", versionStr, versions)
return attestationconfigapi.VersionList{}, fmt.Errorf("version %s not found in list %v", versionStr, versions)
}

type crudCmd interface {
Expand Down
12 changes: 6 additions & 6 deletions internal/api/attestationconfigapi/cli/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ func TestUploadAzureSEVSNP(t *testing.T) {
}
version := attestationconfigapi.SEVSNPVersion{}
date := time.Date(2023, 1, 1, 1, 1, 1, 1, time.UTC)
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)
ops := sut.constructUploadCmd(variant.AzureSEVSNP{}, version, attestationconfigapi.VersionList{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: attestationconfigapi.SEVSNPVersionAPI{
apiObject: attestationconfigapi.VersionAPIEntry{
Variant: variant.AzureSEVSNP{},
Version: dateStr,
SEVSNPVersion: version,
},
signer: fakeSigner{},
})
assert.Contains(ops, putCmd{
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"}},
apiObject: attestationconfigapi.VersionList{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{},
})
}
Expand All @@ -42,20 +42,20 @@ func TestDeleteAzureSEVSNPVersions(t *testing.T) {
sut := Client{
bucketID: "bucket",
}
versions := attestationconfigapi.SEVSNPVersionList{List: []string{"2023-01-01.json", "2021-01-01.json", "2019-01-01.json"}}
versions := attestationconfigapi.VersionList{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: attestationconfigapi.SEVSNPVersionAPI{
apiObject: attestationconfigapi.VersionAPIEntry{
Version: "2021-01-01.json",
},
})

assert.Contains(ops, putCmd{
apiObject: attestationconfigapi.SEVSNPVersionList{List: []string{"2023-01-01.json", "2019-01-01.json"}},
apiObject: attestationconfigapi.VersionList{List: []string{"2023-01-01.json", "2019-01-01.json"}},
})
}

Expand Down
4 changes: 3 additions & 1 deletion internal/api/attestationconfigapi/cli/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi/cli/client"
"github.com/edgelesssys/constellation/v2/internal/api/fetcher"
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/file"
Expand Down Expand Up @@ -127,7 +128,8 @@ func uploadReport(ctx context.Context,

latestAPIVersionAPI, err := attestationconfigapi.NewFetcherWithCustomCDNAndCosignKey(cfg.url, cfg.cosignPublicKey).FetchLatestVersion(ctx, attestation)
if err != nil {
if errors.Is(err, attestationconfigapi.ErrNoVersionsFound) {
var notFoundErr *fetcher.NotFoundError
if errors.As(err, &notFoundErr) {
log.Info("No versions found in API, but assuming that we are uploading the first version.")
} else {
return fmt.Errorf("fetching latest version: %w", err)
Expand Down
49 changes: 21 additions & 28 deletions internal/api/attestationconfigapi/fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package attestationconfigapi

import (
"context"
"errors"
"fmt"

apifetcher "github.com/edgelesssys/constellation/v2/internal/api/fetcher"
Expand All @@ -19,12 +18,9 @@ import (

const cosignPublicKey = constants.CosignPublicKeyReleases

// ErrNoVersionsFound is returned if no versions are found.
var ErrNoVersionsFound = errors.New("no versions found")

// Fetcher fetches config API resources without authentication.
type Fetcher interface {
FetchLatestVersion(ctx context.Context, attestation variant.Variant) (SEVSNPVersionAPI, error)
FetchLatestVersion(ctx context.Context, attestation variant.Variant) (VersionAPIEntry, error)
}

// fetcher fetches AttestationCfg API resources without authentication.
Expand Down Expand Up @@ -64,46 +60,43 @@ func newFetcherWithClientAndVerifier(client apifetcher.HTTPClient, cosignVerifie
}

// FetchLatestVersion returns the latest versions of the given type.
func (f *fetcher) FetchLatestVersion(ctx context.Context, attesation variant.Variant) (res SEVSNPVersionAPI, err error) {
list, err := f.fetchVersionList(ctx, SEVSNPVersionList{Variant: attesation})
func (f *fetcher) FetchLatestVersion(ctx context.Context, variant variant.Variant) (VersionAPIEntry, error) {
list, err := f.fetchVersionList(ctx, variant)
if err != nil {
return res, ErrNoVersionsFound
return VersionAPIEntry{}, err
}

getVersionRequest := SEVSNPVersionAPI{
Version: list.List[0], // latest version is first in list
Variant: attesation,
}
res, err = f.fetchVersion(ctx, getVersionRequest)
if err != nil {
return res, err
}
return
// latest version is first in list
return f.fetchVersion(ctx, list.List[0], variant)
}

// fetchVersionList fetches the version list information from the config API.
func (f *fetcher) fetchVersionList(ctx context.Context, list SEVSNPVersionList) (SEVSNPVersionList, error) {
// TODO(derpsteb): Replace with FetchAndVerify once we move to v2 of the config API.
fetchedList, err := apifetcher.Fetch(ctx, f.HTTPClient, f.cdnURL, list)
func (f *fetcher) fetchVersionList(ctx context.Context, variant variant.Variant) (VersionList, error) {
// TODO(derpsteb): Replace with FetchAndVerify once we move to v2 of the config API and the list is saved as (.json) file.
fetchedList, err := apifetcher.Fetch(ctx, f.HTTPClient, f.cdnURL, VersionList{Variant: variant})
if err != nil {
return list, fmt.Errorf("fetching version list: %w", err)
return VersionList{}, fmt.Errorf("fetching version list: %w", err)
}

// Need to set this explicitly as the variant is not part of the marshalled JSON.
fetchedList.Variant = list.Variant
// Set the attestation variant of the list as it is not part of the marshalled JSON retrieved by Fetch
fetchedList.Variant = variant

return fetchedList, nil
}

// fetchVersion fetches the version information from the config API.
func (f *fetcher) fetchVersion(ctx context.Context, version SEVSNPVersionAPI) (SEVSNPVersionAPI, error) {
fetchedVersion, err := apifetcher.FetchAndVerify(ctx, f.HTTPClient, f.cdnURL, version, f.verifier)
func (f *fetcher) fetchVersion(ctx context.Context, version string, variant variant.Variant) (VersionAPIEntry, error) {
obj := VersionAPIEntry{
Version: version,
Variant: variant,
}
fetchedVersion, err := apifetcher.FetchAndVerify(ctx, f.HTTPClient, f.cdnURL, obj, f.verifier)
if err != nil {
return fetchedVersion, fmt.Errorf("fetching version %s: %w", version.Version, err)
return VersionAPIEntry{}, fmt.Errorf("fetching version %q: %w", version, err)
}

// Need to set this explicitly as the variant is not part of the marshalled JSON.
fetchedVersion.Variant = version.Variant
// Set the attestation variant of the list as it is not part of the marshalled JSON retrieved by FetchAndVerify
fetchedVersion.Variant = variant

return fetchedVersion, nil
}
Loading

0 comments on commit 2685666

Please sign in to comment.