mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-08-01 11:36:10 -04:00
config: sign Azure versions on upload & verify on fetch (#1836)
* add SignContent() + integrate into configAPI * use static client for upload versions tool; fix staticupload calleeReference bug * use version to get proper cosign pub key. * mock fetcher in CLI tests * only provide config.New constructor with fetcher Co-authored-by: Otto Bittner <cobittner@posteo.net> Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com>
This commit is contained in:
parent
e0285c122e
commit
b51cc52945
55 changed files with 752 additions and 308 deletions
|
@ -51,6 +51,7 @@ go_test(
|
|||
embed = [":config"],
|
||||
deps = [
|
||||
"//internal/api/configapi",
|
||||
"//internal/api/versionsapi",
|
||||
"//internal/attestation/measurements",
|
||||
"//internal/cloud/cloudprovider",
|
||||
"//internal/config/instancetypes",
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
"github.com/edgelesssys/constellation/v2/internal/api/configapi"
|
||||
"github.com/edgelesssys/constellation/v2/internal/api/fetcher"
|
||||
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
|
||||
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
|
||||
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
|
||||
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||
|
@ -96,9 +97,8 @@ func (c AzureSEVSNP) EqualTo(old AttestationCfg) (bool, error) {
|
|||
}
|
||||
|
||||
// FetchAndSetLatestVersionNumbers fetches the latest version numbers from the configapi and sets them.
|
||||
func (c *AzureSEVSNP) FetchAndSetLatestVersionNumbers(client fetcher.HTTPClient) error {
|
||||
fetcher := fetcher.NewConfigAPIFetcherWithClient(client)
|
||||
versions, err := fetcher.FetchLatestAzureSEVSNPVersion(context.Background())
|
||||
func (c *AzureSEVSNP) FetchAndSetLatestVersionNumbers(fetcher fetcher.ConfigAPIFetcher, version versionsapi.Version) error {
|
||||
versions, err := fetcher.FetchLatestAzureSEVSNPVersion(context.Background(), version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import (
|
|||
en_translations "github.com/go-playground/validator/v10/translations/en"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/api/fetcher"
|
||||
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
|
||||
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
|
||||
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
|
||||
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||
|
@ -384,19 +385,19 @@ func fromFile(fileHandler file.Handler, name string) (*Config, error) {
|
|||
// 2. For "latest" version values of the attestation variants fetch the version numbers.
|
||||
// 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.
|
||||
func New(fileHandler file.Handler, name string, force bool) (*Config, error) {
|
||||
return NewWithClient(fileHandler, name, fetcher.NewHTTPClient(), force)
|
||||
}
|
||||
|
||||
// NewWithClient is New with a custom HTTP client.
|
||||
func NewWithClient(fileHandler file.Handler, name string, client fetcher.HTTPClient, force bool) (*Config, error) {
|
||||
func New(fileHandler file.Handler, name string, fetcher fetcher.ConfigAPIFetcher, force bool) (*Config, error) {
|
||||
// Read config file
|
||||
c, err := fromFile(fileHandler, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if azure := c.Attestation.AzureSEVSNP; azure != nil {
|
||||
if err := azure.FetchAndSetLatestVersionNumbers(client); err != nil {
|
||||
version, err := versionsapi.NewVersionFromShortPath(c.Image, versionsapi.VersionKindImage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := azure.FetchAndSetLatestVersionNumbers(fetcher, version); err != nil {
|
||||
return c, err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
|
@ -25,6 +22,7 @@ import (
|
|||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/api/configapi"
|
||||
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
|
||||
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
|
||||
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||
"github.com/edgelesssys/constellation/v2/internal/config/instancetypes"
|
||||
|
@ -245,7 +243,6 @@ func TestNewWithDefaultOptions(t *testing.T) {
|
|||
wantClientSecretValue: "some-secret",
|
||||
},
|
||||
}
|
||||
client := newTestClient(&fakeConfigAPIHandler{})
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
@ -260,7 +257,7 @@ func TestNewWithDefaultOptions(t *testing.T) {
|
|||
}
|
||||
|
||||
// Test
|
||||
c, err := NewWithClient(fileHandler, constants.ConfigFilename, client, false)
|
||||
c, err := New(fileHandler, constants.ConfigFilename, fakeConfigFetcher{}, false)
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
|
@ -881,44 +878,27 @@ func getConfigAsMap(conf *Config, t *testing.T) (res configMap) {
|
|||
return
|
||||
}
|
||||
|
||||
type fakeConfigAPIHandler struct{}
|
||||
type fakeConfigFetcher struct{}
|
||||
|
||||
// RoundTrip resolves the request and returns a dummy response.
|
||||
func (f *fakeConfigAPIHandler) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
if req.URL.Path == "/constellation/v1/attestation/azure-sev-snp/list" {
|
||||
res := &http.Response{}
|
||||
data := []string{"2021-01-01-01-01.json"}
|
||||
bt, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res.Body = io.NopCloser(bytes.NewReader(bt))
|
||||
res.Header = http.Header{}
|
||||
res.Header.Set("Content-Type", "application/json")
|
||||
res.StatusCode = http.StatusOK
|
||||
return res, nil
|
||||
} else if req.URL.Path == "/constellation/v1/attestation/azure-sev-snp/2021-01-01-01-01.json" {
|
||||
res := &http.Response{}
|
||||
bt, err := json.Marshal(configapi.AzureSEVSNPVersion{
|
||||
Microcode: 93,
|
||||
TEE: 0,
|
||||
SNP: 6,
|
||||
Bootloader: 2,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res.Body = io.NopCloser(bytes.NewReader(bt))
|
||||
res.StatusCode = http.StatusOK
|
||||
return res, nil
|
||||
|
||||
}
|
||||
return nil, errors.New("no endpoint found")
|
||||
func (f fakeConfigFetcher) FetchAzureSEVSNPVersionList(_ context.Context, _ configapi.AzureSEVSNPVersionList) (configapi.AzureSEVSNPVersionList, error) {
|
||||
return configapi.AzureSEVSNPVersionList(
|
||||
[]string{},
|
||||
), nil
|
||||
}
|
||||
|
||||
// newTestClient returns *http.Client with Transport replaced to avoid making real calls.
|
||||
func newTestClient(fn *fakeConfigAPIHandler) *http.Client {
|
||||
return &http.Client{
|
||||
Transport: fn,
|
||||
}
|
||||
func (f fakeConfigFetcher) FetchAzureSEVSNPVersion(_ context.Context, _ configapi.AzureSEVSNPVersionGet, _ versionsapi.Version) (configapi.AzureSEVSNPVersionGet, error) {
|
||||
return configapi.AzureSEVSNPVersionGet{
|
||||
AzureSEVSNPVersion: testCfg,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f fakeConfigFetcher) FetchLatestAzureSEVSNPVersion(_ context.Context, _ versionsapi.Version) (configapi.AzureSEVSNPVersion, error) {
|
||||
return testCfg, nil
|
||||
}
|
||||
|
||||
var testCfg = configapi.AzureSEVSNPVersion{
|
||||
Microcode: 93,
|
||||
TEE: 0,
|
||||
SNP: 6,
|
||||
Bootloader: 2,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue