mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-09-19 15:56:03 +00:00
config: enable azure snp version fetcher again + minimum age for latest version (#1899)
* fetch latest version when older than 2 weeks
* extend hack upload tool to pass an upload date
* Revert "config: disable user-facing version Azure SEV SNP fetch for v2.8 (#1882)"
This reverts commit c7b22d314a
.
* fix tests
* use NewAzureSEVSNPVersionList for type guarantees
* Revert "use NewAzureSEVSNPVersionList for type guarantees"
This reverts commit 942566453f4b4a2b6dc16f8689248abf1dc47db4.
* assure list is sorted
* improve root.go style
* daniel feedback
This commit is contained in:
parent
72e168e653
commit
3fde118b33
@ -15,6 +15,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
|
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
|
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
|
||||||
@ -314,7 +315,7 @@ func (f stubAttestationFetcher) FetchAzureSEVSNPVersion(_ context.Context, _ att
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f stubAttestationFetcher) FetchAzureSEVSNPVersionLatest(_ context.Context) (attestationconfigapi.AzureSEVSNPVersionAPI, error) {
|
func (f stubAttestationFetcher) FetchAzureSEVSNPVersionLatest(_ context.Context, _ time.Time) (attestationconfigapi.AzureSEVSNPVersionAPI, error) {
|
||||||
return attestationconfigapi.AzureSEVSNPVersionAPI{
|
return attestationconfigapi.AzureSEVSNPVersionAPI{
|
||||||
AzureSEVSNPVersion: testCfg,
|
AzureSEVSNPVersion: testCfg,
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -56,6 +56,7 @@ func newRootCmd() *cobra.Command {
|
|||||||
}
|
}
|
||||||
rootCmd.Flags().StringVarP(&versionFilePath, "version-file", "f", "", "File path to the version json file.")
|
rootCmd.Flags().StringVarP(&versionFilePath, "version-file", "f", "", "File path to the version json file.")
|
||||||
rootCmd.Flags().BoolVar(&force, "force", false, "force to upload version regardless of comparison to latest API value.")
|
rootCmd.Flags().BoolVar(&force, "force", false, "force to upload version regardless of comparison to latest API value.")
|
||||||
|
rootCmd.Flags().StringP("upload-date", "d", "", "upload a version with this date as version name. Setting it implies --force.")
|
||||||
must(enforceRequiredFlags(rootCmd, "version-file"))
|
must(enforceRequiredFlags(rootCmd, "version-file"))
|
||||||
rootCmd.AddCommand(newDeleteCmd())
|
rootCmd.AddCommand(newDeleteCmd())
|
||||||
return rootCmd
|
return rootCmd
|
||||||
@ -85,21 +86,40 @@ func runCmd(cmd *cobra.Command, _ []string) error {
|
|||||||
return fmt.Errorf("unmarshalling version file: %w", err)
|
return fmt.Errorf("unmarshalling version file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
latestAPIVersion, err := attestationconfigapi.NewFetcher().FetchAzureSEVSNPVersionLatest(ctx)
|
dateStr, err := cmd.Flags().GetString("upload-date")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("fetching latest version: %w", err)
|
return fmt.Errorf("getting upload date: %w", err)
|
||||||
|
}
|
||||||
|
var uploadDate time.Time
|
||||||
|
if dateStr != "" {
|
||||||
|
uploadDate, err = time.Parse("2006-01-01-01-01", dateStr)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("parsing date: %w", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uploadDate = time.Now()
|
||||||
|
force = true
|
||||||
}
|
}
|
||||||
|
|
||||||
isNewer, err := isInputNewerThanLatestAPI(inputVersion, latestAPIVersion.AzureSEVSNPVersion)
|
doUpload := false
|
||||||
if err != nil {
|
if !force {
|
||||||
return fmt.Errorf("comparing versions: %w", err)
|
latestAPIVersion, err := attestationconfigapi.NewFetcher().FetchAzureSEVSNPVersionLatest(ctx, time.Now())
|
||||||
}
|
if err != nil {
|
||||||
if isNewer || force {
|
return fmt.Errorf("fetching latest version: %w", err)
|
||||||
if force {
|
|
||||||
cmd.Println("Forcing upload of new version")
|
|
||||||
} else {
|
|
||||||
cmd.Printf("Input version: %+v is newer than latest API version: %+v\n", inputVersion, latestAPIVersion)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isNewer, err := isInputNewerThanLatestAPI(inputVersion, latestAPIVersion.AzureSEVSNPVersion)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("comparing versions: %w", err)
|
||||||
|
}
|
||||||
|
cmd.Print(versionComparisonInformation(isNewer, inputVersion, latestAPIVersion.AzureSEVSNPVersion))
|
||||||
|
doUpload = isNewer
|
||||||
|
} else {
|
||||||
|
doUpload = true
|
||||||
|
cmd.Println("Forcing upload of new version")
|
||||||
|
}
|
||||||
|
|
||||||
|
if doUpload {
|
||||||
sut, sutClose, err := attestationconfigapi.NewClient(ctx, cfg, []byte(cosignPwd), []byte(privateKey), false, log())
|
sut, sutClose, err := attestationconfigapi.NewClient(ctx, cfg, []byte(cosignPwd), []byte(privateKey), false, log())
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := sutClose(ctx); err != nil {
|
if err := sutClose(ctx); err != nil {
|
||||||
@ -110,16 +130,21 @@ func runCmd(cmd *cobra.Command, _ []string) error {
|
|||||||
return fmt.Errorf("creating repo: %w", err)
|
return fmt.Errorf("creating repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sut.UploadAzureSEVSNP(ctx, inputVersion, time.Now()); err != nil {
|
if err := sut.UploadAzureSEVSNP(ctx, inputVersion, uploadDate); 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", inputVersion)
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func versionComparisonInformation(isNewer bool, inputVersion attestationconfigapi.AzureSEVSNPVersion, latestAPIVersion attestationconfigapi.AzureSEVSNPVersion) string {
|
||||||
|
if isNewer {
|
||||||
|
return fmt.Sprintf("Input version: %+v is newer than latest API version: %+v\n", inputVersion, latestAPIVersion)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Input version: %+v is not newer than latest API version: %+v\n", inputVersion, latestAPIVersion)
|
||||||
|
}
|
||||||
|
|
||||||
// isInputNewerThanLatestAPI compares all version fields with the latest API version and returns true if any input field is newer.
|
// isInputNewerThanLatestAPI compares all version fields with the latest API version and returns true if any input field is newer.
|
||||||
func isInputNewerThanLatestAPI(input, latest attestationconfigapi.AzureSEVSNPVersion) (bool, error) {
|
func isInputNewerThanLatestAPI(input, latest attestationconfigapi.AzureSEVSNPVersion) (bool, error) {
|
||||||
inputValues := reflect.ValueOf(input)
|
inputValues := reflect.ValueOf(input)
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||||
@ -110,6 +111,11 @@ func (i AzureSEVSNPVersionList) ValidateRequest() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SortAzureSEVSNPVersionList sorts the list of versions in reverse order.
|
||||||
|
func SortAzureSEVSNPVersionList(versions AzureSEVSNPVersionList) {
|
||||||
|
sort.Sort(sort.Reverse(sort.StringSlice(versions)))
|
||||||
|
}
|
||||||
|
|
||||||
// Validate validates the response.
|
// Validate validates the response.
|
||||||
func (i AzureSEVSNPVersionList) Validate() error {
|
func (i AzureSEVSNPVersionList) Validate() error {
|
||||||
if len(i) < 1 {
|
if len(i) < 1 {
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
apiclient "github.com/edgelesssys/constellation/v2/internal/api/client"
|
apiclient "github.com/edgelesssys/constellation/v2/internal/api/client"
|
||||||
@ -43,7 +42,7 @@ func NewClient(ctx context.Context, cfg staticupload.Config, cosignPwd, privateK
|
|||||||
return repo, clientClose, nil
|
return repo, clientClose, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UploadAzureSEVSNP uploads the latest version numbers of the Azure SEVSNP.
|
// UploadAzureSEVSNP uploads the latest version numbers of the Azure SEVSNP. Then version name is the UTC timestamp of the date. The /list entry stores the version name + .json suffix.
|
||||||
func (a Client) UploadAzureSEVSNP(ctx context.Context, version AzureSEVSNPVersion, date time.Time) error {
|
func (a Client) UploadAzureSEVSNP(ctx context.Context, version AzureSEVSNPVersion, date time.Time) error {
|
||||||
versions, err := a.List(ctx, variant.AzureSEVSNP{})
|
versions, err := a.List(ctx, variant.AzureSEVSNP{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -181,6 +180,6 @@ func executeAllCmds(ctx context.Context, client *apiclient.Client, cmds []crudCm
|
|||||||
func addVersion(versions []string, newVersion string) []string {
|
func addVersion(versions []string, newVersion string) []string {
|
||||||
versions = append(versions, newVersion)
|
versions = append(versions, newVersion)
|
||||||
versions = variant.RemoveDuplicate(versions)
|
versions = variant.RemoveDuplicate(versions)
|
||||||
sort.Sort(sort.Reverse(sort.StringSlice(versions)))
|
SortAzureSEVSNPVersionList(versions)
|
||||||
return versions
|
return versions
|
||||||
}
|
}
|
||||||
|
@ -10,24 +10,30 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
apifetcher "github.com/edgelesssys/constellation/v2/internal/api/fetcher"
|
apifetcher "github.com/edgelesssys/constellation/v2/internal/api/fetcher"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/sigstore"
|
"github.com/edgelesssys/constellation/v2/internal/sigstore"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// minimumAgeVersion is the minimum age to accept the version as latest.
|
||||||
|
const minimumAgeVersion = 14 * 24 * time.Hour
|
||||||
|
|
||||||
const cosignPublicKey = constants.CosignPublicKeyReleases
|
const cosignPublicKey = constants.CosignPublicKeyReleases
|
||||||
|
|
||||||
// Fetcher fetches config API resources without authentication.
|
// Fetcher fetches config API resources without authentication.
|
||||||
type Fetcher interface {
|
type Fetcher interface {
|
||||||
FetchAzureSEVSNPVersion(ctx context.Context, azureVersion AzureSEVSNPVersionAPI) (AzureSEVSNPVersionAPI, error)
|
FetchAzureSEVSNPVersion(ctx context.Context, azureVersion AzureSEVSNPVersionAPI) (AzureSEVSNPVersionAPI, error)
|
||||||
FetchAzureSEVSNPVersionList(ctx context.Context, attestation AzureSEVSNPVersionList) (AzureSEVSNPVersionList, error)
|
FetchAzureSEVSNPVersionList(ctx context.Context, attestation AzureSEVSNPVersionList) (AzureSEVSNPVersionList, error)
|
||||||
FetchAzureSEVSNPVersionLatest(ctx context.Context) (AzureSEVSNPVersionAPI, error)
|
FetchAzureSEVSNPVersionLatest(ctx context.Context, now time.Time) (AzureSEVSNPVersionAPI, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetcher fetches AttestationCfg API resources without authentication.
|
// fetcher fetches AttestationCfg API resources without authentication.
|
||||||
type fetcher struct {
|
type fetcher struct {
|
||||||
apifetcher.HTTPClient
|
apifetcher.HTTPClient
|
||||||
|
verifier sigstore.Verifier
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFetcher returns a new apifetcher.
|
// NewFetcher returns a new apifetcher.
|
||||||
@ -37,7 +43,11 @@ func NewFetcher() Fetcher {
|
|||||||
|
|
||||||
// NewFetcherWithClient returns a new fetcher with custom http client.
|
// NewFetcherWithClient returns a new fetcher with custom http client.
|
||||||
func NewFetcherWithClient(client apifetcher.HTTPClient) Fetcher {
|
func NewFetcherWithClient(client apifetcher.HTTPClient) Fetcher {
|
||||||
return &fetcher{client}
|
return newFetcherWithClientAndVerifier(client, sigstore.CosignVerifier{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFetcherWithClientAndVerifier(client apifetcher.HTTPClient, cosignVerifier sigstore.Verifier) Fetcher {
|
||||||
|
return &fetcher{client, cosignVerifier}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchAzureSEVSNPVersionList fetches the version list information from the config API.
|
// FetchAzureSEVSNPVersionList fetches the version list information from the config API.
|
||||||
@ -63,7 +73,7 @@ func (f *fetcher) FetchAzureSEVSNPVersion(ctx context.Context, azureVersion Azur
|
|||||||
return fetchedVersion, fmt.Errorf("fetch version %s signature: %w", azureVersion.Version, err)
|
return fetchedVersion, fmt.Errorf("fetch version %s signature: %w", azureVersion.Version, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sigstore.CosignVerifier{}.VerifySignature(versionBytes, signature.Signature, []byte(cosignPublicKey))
|
err = f.verifier.VerifySignature(versionBytes, signature.Signature, []byte(cosignPublicKey))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fetchedVersion, fmt.Errorf("verify version %s signature: %w", azureVersion.Version, err)
|
return fetchedVersion, fmt.Errorf("verify version %s signature: %w", azureVersion.Version, err)
|
||||||
}
|
}
|
||||||
@ -71,16 +81,34 @@ func (f *fetcher) FetchAzureSEVSNPVersion(ctx context.Context, azureVersion Azur
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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) (res AzureSEVSNPVersionAPI, err error) {
|
func (f *fetcher) FetchAzureSEVSNPVersionLatest(ctx context.Context, now time.Time) (res AzureSEVSNPVersionAPI, err error) {
|
||||||
var list AzureSEVSNPVersionList
|
var list 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 := AzureSEVSNPVersionAPI{Version: list[0]} // get latest version (as sorted reversely alphanumerically)
|
getVersionRequest, err := getLatestVersionOlderThanMinimumAge(list, now, minimumAgeVersion)
|
||||||
get, err = f.FetchAzureSEVSNPVersion(ctx, get)
|
if err != nil {
|
||||||
|
return res, fmt.Errorf("finding latest valid version: %w", err)
|
||||||
|
}
|
||||||
|
res, err = f.FetchAzureSEVSNPVersion(ctx, getVersionRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, fmt.Errorf("fetching version: %w", err)
|
return res, fmt.Errorf("fetching version: %w", err)
|
||||||
}
|
}
|
||||||
return get, nil
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLatestVersionOlderThanMinimumAge(list AzureSEVSNPVersionList, now time.Time, minimumAgeVersion time.Duration) (AzureSEVSNPVersionAPI, error) {
|
||||||
|
SortAzureSEVSNPVersionList(list)
|
||||||
|
for _, v := range list {
|
||||||
|
dateStr := strings.TrimSuffix(v, ".json")
|
||||||
|
versionDate, err := time.Parse("2006-01-01-01-01", dateStr)
|
||||||
|
if err != nil {
|
||||||
|
return AzureSEVSNPVersionAPI{}, fmt.Errorf("parsing version date %s: %w", dateStr, err)
|
||||||
|
}
|
||||||
|
if now.Sub(versionDate) > minimumAgeVersion {
|
||||||
|
return AzureSEVSNPVersionAPI{Version: v}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AzureSEVSNPVersionAPI{}, fmt.Errorf("no valid version fulfilling minimum age found")
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,56 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
var testCfg = AzureSEVSNPVersionAPI{
|
func TestFetchLatestAzureSEVSNPVersion(t *testing.T) {
|
||||||
|
now := time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
testcases := map[string]struct {
|
||||||
|
fetcherVersions []string
|
||||||
|
timeAtTest time.Time
|
||||||
|
wantErr bool
|
||||||
|
want AzureSEVSNPVersionAPI
|
||||||
|
}{
|
||||||
|
"get latest version if older than 2 weeks": {
|
||||||
|
fetcherVersions: []string{"2021-01-01-01-01.json", "2019-01-01-01-01.json"},
|
||||||
|
timeAtTest: now.Add(days(15)),
|
||||||
|
want: latestVersion,
|
||||||
|
},
|
||||||
|
"get older version if latest version is not older than minimum age": {
|
||||||
|
fetcherVersions: []string{"2021-01-01-01-01.json", "2019-01-01-01-01.json"},
|
||||||
|
timeAtTest: now.Add(days(7)),
|
||||||
|
want: olderVersion,
|
||||||
|
},
|
||||||
|
"fail when no version is older minimum age": {
|
||||||
|
fetcherVersions: []string{"2021-01-01-01-01.json", "2020-12-31-00-00.json"},
|
||||||
|
timeAtTest: now.Add(days(2)),
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, tc := range testcases {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
client := &http.Client{
|
||||||
|
Transport: &fakeConfigAPIHandler{
|
||||||
|
versions: tc.fetcherVersions,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
fetcher := newFetcherWithClientAndVerifier(client, dummyVerifier{})
|
||||||
|
res, err := fetcher.FetchAzureSEVSNPVersionLatest(context.Background(), tc.timeAtTest)
|
||||||
|
assert := assert.New(t)
|
||||||
|
if tc.wantErr {
|
||||||
|
assert.Error(err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.Equal(tc.want, res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var latestVersion = AzureSEVSNPVersionAPI{
|
||||||
AzureSEVSNPVersion: AzureSEVSNPVersion{
|
AzureSEVSNPVersion: AzureSEVSNPVersion{
|
||||||
Microcode: 93,
|
Microcode: 93,
|
||||||
TEE: 0,
|
TEE: 0,
|
||||||
@ -26,52 +71,29 @@ var testCfg = AzureSEVSNPVersionAPI{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFetchLatestAzureSEVSNPVersion(t *testing.T) {
|
var olderVersion = AzureSEVSNPVersionAPI{
|
||||||
testcases := map[string]struct {
|
AzureSEVSNPVersion: AzureSEVSNPVersion{
|
||||||
signature []byte
|
Microcode: 1,
|
||||||
wantErr bool
|
TEE: 0,
|
||||||
want AzureSEVSNPVersionAPI
|
SNP: 1,
|
||||||
}{
|
Bootloader: 1,
|
||||||
"get version with valid signature": {
|
},
|
||||||
signature: []byte("MEQCIBPEbYg89MIQuaGStLhKGLGMKvKFoYCaAniDLwoIwulqAiB+rj7KMaMOMGxmUsjI7KheCXSNM8NzN+tuDw6AywI75A=="), // signed with release key
|
}
|
||||||
want: testCfg,
|
|
||||||
},
|
|
||||||
"fail with invalid signature": {
|
|
||||||
signature: []byte("invalid"),
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for name, tc := range testcases {
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
client := &http.Client{
|
|
||||||
Transport: &fakeConfigAPIHandler{
|
|
||||||
signature: tc.signature,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
fetcher := NewFetcherWithClient(client)
|
|
||||||
res, err := fetcher.FetchAzureSEVSNPVersionLatest(context.Background())
|
|
||||||
|
|
||||||
assert := assert.New(t)
|
func days(days int) time.Duration {
|
||||||
if tc.wantErr {
|
return time.Duration(days*24) * time.Hour
|
||||||
assert.Error(err)
|
|
||||||
} else {
|
|
||||||
assert.NoError(err)
|
|
||||||
assert.Equal(testCfg, res)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type fakeConfigAPIHandler struct {
|
type fakeConfigAPIHandler struct {
|
||||||
signature []byte
|
versions []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// RoundTrip resolves the request and returns a dummy response.
|
// RoundTrip resolves the request and returns a dummy response.
|
||||||
func (f *fakeConfigAPIHandler) RoundTrip(req *http.Request) (*http.Response, error) {
|
func (f *fakeConfigAPIHandler) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
signature := []byte("placeholderSignature")
|
||||||
if req.URL.Path == "/constellation/v1/attestation/azure-sev-snp/list" {
|
if req.URL.Path == "/constellation/v1/attestation/azure-sev-snp/list" {
|
||||||
res := &http.Response{}
|
res := &http.Response{}
|
||||||
data := []string{"2021-01-01-01-01.json", "2019-01-01-01-02.json"} // return multiple versions to check that latest version is correctly selected
|
bt, err := json.Marshal(f.versions)
|
||||||
bt, err := json.Marshal(data)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -82,7 +104,17 @@ func (f *fakeConfigAPIHandler) RoundTrip(req *http.Request) (*http.Response, err
|
|||||||
return res, nil
|
return res, nil
|
||||||
} else if req.URL.Path == "/constellation/v1/attestation/azure-sev-snp/2021-01-01-01-01.json" {
|
} else if req.URL.Path == "/constellation/v1/attestation/azure-sev-snp/2021-01-01-01-01.json" {
|
||||||
res := &http.Response{}
|
res := &http.Response{}
|
||||||
bt, err := json.Marshal(testCfg)
|
bt, err := json.Marshal(latestVersion)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res.Body = io.NopCloser(bytes.NewReader(bt))
|
||||||
|
res.StatusCode = http.StatusOK
|
||||||
|
return res, nil
|
||||||
|
|
||||||
|
} else if req.URL.Path == "/constellation/v1/attestation/azure-sev-snp/2019-01-01-01-01.json" {
|
||||||
|
res := &http.Response{}
|
||||||
|
bt, err := json.Marshal(olderVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -93,7 +125,20 @@ func (f *fakeConfigAPIHandler) RoundTrip(req *http.Request) (*http.Response, err
|
|||||||
} else if req.URL.Path == "/constellation/v1/attestation/azure-sev-snp/2021-01-01-01-01.json.sig" {
|
} else if req.URL.Path == "/constellation/v1/attestation/azure-sev-snp/2021-01-01-01-01.json.sig" {
|
||||||
res := &http.Response{}
|
res := &http.Response{}
|
||||||
obj := AzureSEVSNPVersionSignature{
|
obj := AzureSEVSNPVersionSignature{
|
||||||
Signature: f.signature,
|
Signature: signature,
|
||||||
|
}
|
||||||
|
bt, err := json.Marshal(obj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res.Body = io.NopCloser(bytes.NewReader(bt))
|
||||||
|
res.StatusCode = http.StatusOK
|
||||||
|
return res, nil
|
||||||
|
|
||||||
|
} else if req.URL.Path == "/constellation/v1/attestation/azure-sev-snp/2019-01-01-01-01.json.sig" {
|
||||||
|
res := &http.Response{}
|
||||||
|
obj := AzureSEVSNPVersionSignature{
|
||||||
|
Signature: signature,
|
||||||
}
|
}
|
||||||
bt, err := json.Marshal(obj)
|
bt, err := json.Marshal(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -106,3 +151,9 @@ func (f *fakeConfigAPIHandler) RoundTrip(req *http.Request) (*http.Response, err
|
|||||||
}
|
}
|
||||||
return nil, errors.New("no endpoint found")
|
return nil, errors.New("no endpoint found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type dummyVerifier struct{}
|
||||||
|
|
||||||
|
func (s dummyVerifier) VerifySignature(_, _, _ []byte) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -218,10 +218,6 @@ func TestTrustedKeyFromSNP(t *testing.T) {
|
|||||||
AcceptedKeyDigests: tc.idkeydigests,
|
AcceptedKeyDigests: tc.idkeydigests,
|
||||||
EnforcementPolicy: tc.enforceIDKeyDigest,
|
EnforcementPolicy: tc.enforceIDKeyDigest,
|
||||||
}
|
}
|
||||||
cfg.BootloaderVersion = config.AttestationVersion{Value: 2}
|
|
||||||
cfg.TEEVersion = config.AttestationVersion{Value: 0}
|
|
||||||
cfg.MicrocodeVersion = config.AttestationVersion{Value: 93}
|
|
||||||
cfg.SNPVersion = config.AttestationVersion{Value: 6}
|
|
||||||
|
|
||||||
validator := &Validator{
|
validator := &Validator{
|
||||||
hclValidator: &instanceInfo,
|
hclValidator: &instanceInfo,
|
||||||
@ -353,12 +349,6 @@ func TestNewSNPReportFromBytes(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
cfg := config.DefaultForAzureSEVSNP()
|
cfg := config.DefaultForAzureSEVSNP()
|
||||||
|
|
||||||
cfg.BootloaderVersion = config.AttestationVersion{Value: 2}
|
|
||||||
cfg.TEEVersion = config.AttestationVersion{Value: 0}
|
|
||||||
cfg.MicrocodeVersion = config.AttestationVersion{Value: 93}
|
|
||||||
cfg.SNPVersion = config.AttestationVersion{Value: 6}
|
|
||||||
|
|
||||||
for name, tc := range testCases {
|
for name, tc := range testCases {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
@ -8,7 +8,6 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@ -34,7 +33,7 @@ func (v AttestationVersion) MarshalYAML() (any, error) {
|
|||||||
if v.IsLatest {
|
if v.IsLatest {
|
||||||
return "latest", nil
|
return "latest", nil
|
||||||
}
|
}
|
||||||
return int(v.Value), nil
|
return v.Value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalYAML implements a custom unmarshaller to resolve "atest" values.
|
// UnmarshalYAML implements a custom unmarshaller to resolve "atest" values.
|
||||||
@ -68,12 +67,11 @@ func (v *AttestationVersion) parseRawUnmarshal(rawUnmarshal any) error {
|
|||||||
switch s := rawUnmarshal.(type) {
|
switch s := rawUnmarshal.(type) {
|
||||||
case string:
|
case string:
|
||||||
if strings.ToLower(s) == "latest" {
|
if strings.ToLower(s) == "latest" {
|
||||||
// TODO(elchead): activate latest logic for next release AB#3036
|
v.IsLatest = true
|
||||||
return errors.New("latest is not supported as a version value")
|
v.Value = placeholderVersionValue
|
||||||
// v.IsLatest = true
|
} else {
|
||||||
// v.Value = placeholderVersionValue
|
return fmt.Errorf("invalid version value: %s", s)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("invalid version value: %s", s)
|
|
||||||
case int:
|
case int:
|
||||||
v.Value = uint8(s)
|
v.Value = uint8(s)
|
||||||
// yaml spec allows "1" as float64, so version number might come as a float: https://github.com/go-yaml/yaml/issues/430
|
// yaml spec allows "1" as float64, so version number might come as a float: https://github.com/go-yaml/yaml/issues/430
|
||||||
|
@ -9,7 +9,6 @@ package config
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
@ -45,39 +44,3 @@ func TestVersionMarshalYAML(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVersionUnmarshalYAML(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
expected AttestationVersion
|
|
||||||
yamlInput string
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
// TODO(elchead): activate latest logic for next release AB#3036
|
|
||||||
{
|
|
||||||
name: "latest value is not allowed",
|
|
||||||
expected: AttestationVersion{},
|
|
||||||
yamlInput: "latest\n",
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "value 5 resolves to 5",
|
|
||||||
expected: AttestationVersion{
|
|
||||||
Value: 5,
|
|
||||||
},
|
|
||||||
yamlInput: "5\n",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
sut := AttestationVersion{}
|
|
||||||
err := yaml.Unmarshal([]byte(tt.yamlInput), &sut)
|
|
||||||
if tt.wantErr {
|
|
||||||
assert.Error(t, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, tt.expected.IsLatest, sut.IsLatest)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/go-playground/locales/en"
|
"github.com/go-playground/locales/en"
|
||||||
ut "github.com/go-playground/universal-translator"
|
ut "github.com/go-playground/universal-translator"
|
||||||
@ -386,19 +387,18 @@ func fromFile(fileHandler file.Handler, name string) (*Config, error) {
|
|||||||
// 2. For "latest" version values of the attestation variants fetch the version numbers.
|
// 2. For "latest" version values of the attestation variants fetch the version numbers.
|
||||||
// 3. Read secrets from environment variables.
|
// 3. Read secrets from environment variables.
|
||||||
// 4. Validate config. If `--force` is set the version validation will be disabled and any version combination is allowed.
|
// 4. Validate config. If `--force` is set the version validation will be disabled and any version combination is allowed.
|
||||||
func New(fileHandler file.Handler, name string, _ attestationconfigapi.Fetcher, force bool) (*Config, error) {
|
func New(fileHandler file.Handler, name string, fetcher attestationconfigapi.Fetcher, force bool) (*Config, error) {
|
||||||
// Read config file
|
// Read config file
|
||||||
c, err := fromFile(fileHandler, name)
|
c, err := fromFile(fileHandler, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(elchead): activate latest logic for next release AB#3036
|
if azure := c.Attestation.AzureSEVSNP; azure != nil {
|
||||||
//if azure := c.Attestation.AzureSEVSNP; azure != nil {
|
if err := azure.FetchAndSetLatestVersionNumbers(context.Background(), fetcher, time.Now()); err != nil {
|
||||||
// if err := azure.FetchAndSetLatestVersionNumbers(fetcher); err != nil {
|
return c, err
|
||||||
// return c, err
|
}
|
||||||
// }
|
}
|
||||||
//}
|
|
||||||
|
|
||||||
// Read secrets from env-vars.
|
// Read secrets from env-vars.
|
||||||
clientSecretValue := os.Getenv(constants.EnvVarAzureClientSecretValue)
|
clientSecretValue := os.Getenv(constants.EnvVarAzureClientSecretValue)
|
||||||
@ -925,19 +925,12 @@ type AzureSEVSNP struct {
|
|||||||
// DefaultForAzureSEVSNP returns the default configuration for Azure SEV-SNP attestation.
|
// DefaultForAzureSEVSNP returns the default configuration for Azure SEV-SNP attestation.
|
||||||
// Version numbers have placeholder values and the latest available values can be fetched using [AzureSEVSNP.FetchAndSetLatestVersionNumbers].
|
// Version numbers have placeholder values and the latest available values can be fetched using [AzureSEVSNP.FetchAndSetLatestVersionNumbers].
|
||||||
func DefaultForAzureSEVSNP() *AzureSEVSNP {
|
func DefaultForAzureSEVSNP() *AzureSEVSNP {
|
||||||
// TODO(elchead): activate latest logic for next release AB#3036
|
|
||||||
azureSNPCfg := attestationconfigapi.AzureSEVSNPVersion{
|
|
||||||
Bootloader: 3,
|
|
||||||
TEE: 0,
|
|
||||||
SNP: 8,
|
|
||||||
Microcode: 115,
|
|
||||||
}
|
|
||||||
return &AzureSEVSNP{
|
return &AzureSEVSNP{
|
||||||
Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureSEVSNP{}),
|
Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureSEVSNP{}),
|
||||||
BootloaderVersion: AttestationVersion{Value: azureSNPCfg.Bootloader}, // NewLatestPlaceholderVersion(),
|
BootloaderVersion: NewLatestPlaceholderVersion(),
|
||||||
TEEVersion: AttestationVersion{Value: azureSNPCfg.TEE}, // NewLatestPlaceholderVersion(),
|
TEEVersion: NewLatestPlaceholderVersion(),
|
||||||
SNPVersion: AttestationVersion{Value: azureSNPCfg.SNP}, // NewLatestPlaceholderVersion(),
|
SNPVersion: NewLatestPlaceholderVersion(),
|
||||||
MicrocodeVersion: AttestationVersion{Value: azureSNPCfg.Microcode}, // NewLatestPlaceholderVersion(),
|
MicrocodeVersion: NewLatestPlaceholderVersion(),
|
||||||
FirmwareSignerConfig: SNPFirmwareSignerConfig{
|
FirmwareSignerConfig: SNPFirmwareSignerConfig{
|
||||||
AcceptedKeyDigests: idkeydigest.DefaultList(),
|
AcceptedKeyDigests: idkeydigest.DefaultList(),
|
||||||
EnforcementPolicy: idkeydigest.MAAFallback,
|
EnforcementPolicy: idkeydigest.MAAFallback,
|
||||||
@ -981,8 +974,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 attestationconfigapi.Fetcher) error {
|
func (c *AzureSEVSNP) FetchAndSetLatestVersionNumbers(ctx context.Context, fetcher attestationconfigapi.Fetcher, now time.Time) error {
|
||||||
versions, err := fetcher.FetchAzureSEVSNPVersionLatest(context.Background())
|
versions, err := fetcher.FetchAzureSEVSNPVersionLatest(ctx, now)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/go-playground/locales/en"
|
"github.com/go-playground/locales/en"
|
||||||
ut "github.com/go-playground/universal-translator"
|
ut "github.com/go-playground/universal-translator"
|
||||||
@ -41,21 +42,20 @@ func TestDefaultConfig(t *testing.T) {
|
|||||||
assert.NotNil(def)
|
assert.NotNil(def)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(elchead): activate latest logic for next release AB#3036
|
func TestDefaultConfigWritesLatestVersion(t *testing.T) {
|
||||||
// func TestDefaultConfigWritesLatestVersion(t *testing.T) {
|
conf := Default()
|
||||||
// conf := Default()
|
bt, err := yaml.Marshal(conf)
|
||||||
// bt, err := yaml.Marshal(conf)
|
require := require.New(t)
|
||||||
// require := require.New(t)
|
require.NoError(err)
|
||||||
// require.NoError(err)
|
|
||||||
|
|
||||||
// var mp configMap
|
var mp configMap
|
||||||
// require.NoError(yaml.Unmarshal(bt, &mp))
|
require.NoError(yaml.Unmarshal(bt, &mp))
|
||||||
// assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
// assert.Equal("latest", mp.getAzureSEVSNPVersion("microcodeVersion"))
|
assert.Equal("latest", mp.getAzureSEVSNPVersion("microcodeVersion"))
|
||||||
// assert.Equal("latest", mp.getAzureSEVSNPVersion("teeVersion"))
|
assert.Equal("latest", mp.getAzureSEVSNPVersion("teeVersion"))
|
||||||
// assert.Equal("latest", mp.getAzureSEVSNPVersion("snpVersion"))
|
assert.Equal("latest", mp.getAzureSEVSNPVersion("snpVersion"))
|
||||||
// assert.Equal("latest", mp.getAzureSEVSNPVersion("bootloaderVersion"))
|
assert.Equal("latest", mp.getAzureSEVSNPVersion("bootloaderVersion"))
|
||||||
//}
|
}
|
||||||
|
|
||||||
func TestReadConfigFile(t *testing.T) {
|
func TestReadConfigFile(t *testing.T) {
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
@ -64,41 +64,29 @@ func TestReadConfigFile(t *testing.T) {
|
|||||||
wantResult *Config
|
wantResult *Config
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
// TODO(elchead): activate latest logic for next release AB#3036
|
"mix of Latest and uint as version value": {
|
||||||
//"mix of Latest and uint as version value": {
|
|
||||||
// config: func() configMap {
|
|
||||||
// conf := Default()
|
|
||||||
// m := getConfigAsMap(conf, t)
|
|
||||||
// m.setAzureSEVSNPVersion("microcodeVersion", "Latest") // check uppercase also works
|
|
||||||
// m.setAzureSEVSNPVersion("teeVersion", 2)
|
|
||||||
// m.setAzureSEVSNPVersion("bootloaderVersion", 1)
|
|
||||||
// return m
|
|
||||||
// }(),
|
|
||||||
|
|
||||||
// configName: constants.ConfigFilename,
|
|
||||||
// wantResult: func() *Config {
|
|
||||||
// conf := Default()
|
|
||||||
// conf.Attestation.AzureSEVSNP.BootloaderVersion = AttestationVersion{
|
|
||||||
// Value: 1,
|
|
||||||
// IsLatest: false,
|
|
||||||
// }
|
|
||||||
// conf.Attestation.AzureSEVSNP.TEEVersion = AttestationVersion{
|
|
||||||
// Value: 2,
|
|
||||||
// IsLatest: false,
|
|
||||||
// }
|
|
||||||
// return conf
|
|
||||||
// }(),
|
|
||||||
//},
|
|
||||||
// TODO(elchead): activate latest logic for next release AB#3036
|
|
||||||
"refuse invalid latest value": {
|
|
||||||
config: func() configMap {
|
config: func() configMap {
|
||||||
conf := Default()
|
conf := Default()
|
||||||
m := getConfigAsMap(conf, t)
|
m := getConfigAsMap(conf, t)
|
||||||
m.setAzureSEVSNPVersion("microcodeVersion", "latest")
|
m.setAzureSEVSNPVersion("microcodeVersion", "Latest") // check uppercase also works
|
||||||
|
m.setAzureSEVSNPVersion("teeVersion", 2)
|
||||||
|
m.setAzureSEVSNPVersion("bootloaderVersion", 1)
|
||||||
return m
|
return m
|
||||||
}(),
|
}(),
|
||||||
|
|
||||||
configName: constants.ConfigFilename,
|
configName: constants.ConfigFilename,
|
||||||
wantErr: true,
|
wantResult: func() *Config {
|
||||||
|
conf := Default()
|
||||||
|
conf.Attestation.AzureSEVSNP.BootloaderVersion = AttestationVersion{
|
||||||
|
Value: 1,
|
||||||
|
IsLatest: false,
|
||||||
|
}
|
||||||
|
conf.Attestation.AzureSEVSNP.TEEVersion = AttestationVersion{
|
||||||
|
Value: 2,
|
||||||
|
IsLatest: false,
|
||||||
|
}
|
||||||
|
return conf
|
||||||
|
}(),
|
||||||
},
|
},
|
||||||
"refuse invalid version value": {
|
"refuse invalid version value": {
|
||||||
config: func() configMap {
|
config: func() configMap {
|
||||||
@ -271,7 +259,7 @@ func TestNewWithDefaultOptions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test
|
// Test
|
||||||
c, err := New(fileHandler, constants.ConfigFilename, fakeConfigFetcher{}, false)
|
c, err := New(fileHandler, constants.ConfigFilename, stubAttestationFetcher{}, false)
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
return
|
return
|
||||||
@ -889,9 +877,9 @@ func (c configMap) setAzureSEVSNPVersion(versionType string, value interface{})
|
|||||||
c["attestation"].(configMap)["azureSEVSNP"].(configMap)[versionType] = value
|
c["attestation"].(configMap)["azureSEVSNP"].(configMap)[versionType] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (c configMap) getAzureSEVSNPVersion(versionType string) interface{} {
|
func (c configMap) getAzureSEVSNPVersion(versionType string) interface{} {
|
||||||
// return c["attestation"].(configMap)["azureSEVSNP"].(configMap)[versionType]
|
return c["attestation"].(configMap)["azureSEVSNP"].(configMap)[versionType]
|
||||||
//}
|
}
|
||||||
|
|
||||||
// getConfigAsMap returns a map of the config.
|
// getConfigAsMap returns a map of the config.
|
||||||
func getConfigAsMap(conf *Config, t *testing.T) (res configMap) {
|
func getConfigAsMap(conf *Config, t *testing.T) (res configMap) {
|
||||||
@ -905,21 +893,21 @@ func getConfigAsMap(conf *Config, t *testing.T) (res configMap) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type fakeConfigFetcher struct{}
|
type stubAttestationFetcher struct{}
|
||||||
|
|
||||||
func (f fakeConfigFetcher) FetchAzureSEVSNPVersionList(_ context.Context, _ configapi.AzureSEVSNPVersionList) (configapi.AzureSEVSNPVersionList, error) {
|
func (f stubAttestationFetcher) FetchAzureSEVSNPVersionList(_ context.Context, _ configapi.AzureSEVSNPVersionList) (configapi.AzureSEVSNPVersionList, error) {
|
||||||
return configapi.AzureSEVSNPVersionList(
|
return configapi.AzureSEVSNPVersionList(
|
||||||
[]string{},
|
[]string{},
|
||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f fakeConfigFetcher) FetchAzureSEVSNPVersion(_ context.Context, _ configapi.AzureSEVSNPVersionAPI) (configapi.AzureSEVSNPVersionAPI, error) {
|
func (f stubAttestationFetcher) FetchAzureSEVSNPVersion(_ context.Context, _ configapi.AzureSEVSNPVersionAPI) (configapi.AzureSEVSNPVersionAPI, error) {
|
||||||
return configapi.AzureSEVSNPVersionAPI{
|
return configapi.AzureSEVSNPVersionAPI{
|
||||||
AzureSEVSNPVersion: testCfg,
|
AzureSEVSNPVersion: testCfg,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f fakeConfigFetcher) FetchAzureSEVSNPVersionLatest(_ context.Context) (configapi.AzureSEVSNPVersionAPI, error) {
|
func (f stubAttestationFetcher) FetchAzureSEVSNPVersionLatest(_ context.Context, _ time.Time) (configapi.AzureSEVSNPVersionAPI, error) {
|
||||||
return configapi.AzureSEVSNPVersionAPI{
|
return configapi.AzureSEVSNPVersionAPI{
|
||||||
AzureSEVSNPVersion: testCfg,
|
AzureSEVSNPVersion: testCfg,
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -18,6 +18,11 @@ import (
|
|||||||
sigsig "github.com/sigstore/sigstore/pkg/signature"
|
sigsig "github.com/sigstore/sigstore/pkg/signature"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Verifier checks if the signature of content can be verified.
|
||||||
|
type Verifier interface {
|
||||||
|
VerifySignature(content, signature, publicKey []byte) error
|
||||||
|
}
|
||||||
|
|
||||||
// CosignVerifier checks if the signature of content can be verified
|
// CosignVerifier checks if the signature of content can be verified
|
||||||
// using a cosign public key.
|
// using a cosign public key.
|
||||||
type CosignVerifier struct{}
|
type CosignVerifier struct{}
|
||||||
|
@ -129,6 +129,9 @@ While this API should stay compatible with old release, extensive changes to our
|
|||||||
In this case a new API version will be used to retrieve the config in the updated format, e.g. `/constellation/v2/attestation/<ATTESTATION_VARIANT>/`.
|
In this case a new API version will be used to retrieve the config in the updated format, e.g. `/constellation/v2/attestation/<ATTESTATION_VARIANT>/`.
|
||||||
The old API will still receive updates for at least the next release cycle, during this time this API version will also return a deprecation warning when requesting `list`.
|
The old API will still receive updates for at least the next release cycle, during this time this API version will also return a deprecation warning when requesting `list`.
|
||||||
|
|
||||||
|
### Azure SEV-SNP
|
||||||
|
IMPORTANT: Since the current version fetches from the Azure SEV-SNP report are not guaranteed to be globally rolled out at the time of the report, we introduce a minimum age (2 weeks) of the version to consider it a valid latest version.
|
||||||
|
This validation is only enforced on the fetcher side! This means that the HTTP endpoints contain all versions, even those that do not yet have the minimum age.
|
||||||
### AWS
|
### AWS
|
||||||
|
|
||||||
AWS provides a way to precalculate launch-measurements for their firmware in SEV-SNP CVMs.
|
AWS provides a way to precalculate launch-measurements for their firmware in SEV-SNP CVMs.
|
||||||
|
Loading…
Reference in New Issue
Block a user