mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-07-30 18:48:39 -04:00
Add --insecure to config fetch-measurement (#1879)
* cli: add --insecure to fetch-measurements * cli: rename fake to stub * ci: upload measurements for debug images * fix cli docs
This commit is contained in:
parent
f7f11c32f8
commit
7c07e3be18
11 changed files with 85 additions and 77 deletions
|
@ -36,6 +36,7 @@ func newConfigFetchMeasurementsCmd() *cobra.Command {
|
|||
}
|
||||
cmd.Flags().StringP("url", "u", "", "alternative URL to fetch measurements from")
|
||||
cmd.Flags().StringP("signature-url", "s", "", "alternative URL to fetch measurements' signature from")
|
||||
cmd.Flags().Bool("insecure", false, "skip the measurement signature verification")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
@ -43,6 +44,7 @@ func newConfigFetchMeasurementsCmd() *cobra.Command {
|
|||
type fetchMeasurementsFlags struct {
|
||||
measurementsURL *url.URL
|
||||
signatureURL *url.URL
|
||||
insecure bool
|
||||
configPath string
|
||||
force bool
|
||||
}
|
||||
|
@ -115,25 +117,44 @@ func (cfm *configFetchMeasurementsCmd) configFetchMeasurements(
|
|||
}
|
||||
|
||||
var fetchedMeasurements measurements.M
|
||||
hash, err := fetchedMeasurements.FetchAndVerify(
|
||||
ctx, client, cosign,
|
||||
flags.measurementsURL,
|
||||
flags.signatureURL,
|
||||
imageVersion,
|
||||
conf.GetProvider(),
|
||||
conf.GetAttestationConfig().GetVariant(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
var hash string
|
||||
if flags.insecure {
|
||||
if err := fetchedMeasurements.FetchNoVerify(
|
||||
ctx,
|
||||
client,
|
||||
flags.measurementsURL,
|
||||
imageVersion,
|
||||
conf.GetProvider(),
|
||||
conf.GetAttestationConfig().GetVariant(),
|
||||
); err != nil {
|
||||
return fmt.Errorf("fetching measurements without verification: %w", err)
|
||||
}
|
||||
|
||||
cfm.log.Debugf("Fetched measurements without verification")
|
||||
} else {
|
||||
hash, err = fetchedMeasurements.FetchAndVerify(
|
||||
ctx,
|
||||
client,
|
||||
cosign,
|
||||
flags.measurementsURL,
|
||||
flags.signatureURL,
|
||||
imageVersion,
|
||||
conf.GetProvider(),
|
||||
conf.GetAttestationConfig().GetVariant(),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("fetching and verifying measurements: %w", err)
|
||||
}
|
||||
cfm.log.Debugf("Fetched and verified measurements, hash is %s", hash)
|
||||
if err := sigstore.VerifyWithRekor(cmd.Context(), imageVersion, rekor, hash); err != nil {
|
||||
cmd.PrintErrf("Ignoring Rekor related error: %v\n", err)
|
||||
cmd.PrintErrln("Make sure the downloaded measurements are trustworthy!")
|
||||
}
|
||||
|
||||
cfm.log.Debugf("Verified measurements with Rekor")
|
||||
}
|
||||
|
||||
cfm.log.Debugf("Fetched and verified measurements, hash is %s", hash)
|
||||
if err := sigstore.VerifyWithRekor(cmd.Context(), imageVersion, rekor, hash); err != nil {
|
||||
cmd.PrintErrf("Ignoring Rekor related error: %v\n", err)
|
||||
cmd.PrintErrln("Make sure the downloaded measurements are trustworthy!")
|
||||
}
|
||||
|
||||
cfm.log.Debugf("Verified measurements with Rekor, updating measurements in configuration")
|
||||
cfm.log.Debugf("Updating measurements in configuration")
|
||||
conf.UpdateMeasurements(fetchedMeasurements)
|
||||
if err := fileHandler.WriteYAML(flags.configPath, conf, file.OptOverwrite); err != nil {
|
||||
return err
|
||||
|
@ -170,6 +191,12 @@ func (cfm *configFetchMeasurementsCmd) parseFetchMeasurementsFlags(cmd *cobra.Co
|
|||
}
|
||||
cfm.log.Debugf("Parsed measurements signature URL as %v", measurementsSignatureURL)
|
||||
|
||||
insecure, err := cmd.Flags().GetBool("insecure")
|
||||
if err != nil {
|
||||
return &fetchMeasurementsFlags{}, fmt.Errorf("parsing insecure argument: %w", err)
|
||||
}
|
||||
cfm.log.Debugf("Insecure flag is %v", insecure)
|
||||
|
||||
config, err := cmd.Flags().GetString("config")
|
||||
if err != nil {
|
||||
return &fetchMeasurementsFlags{}, fmt.Errorf("parsing config path argument: %w", err)
|
||||
|
@ -184,6 +211,7 @@ func (cfm *configFetchMeasurementsCmd) parseFetchMeasurementsFlags(cmd *cobra.Co
|
|||
return &fetchMeasurementsFlags{
|
||||
measurementsURL: measurementsURL,
|
||||
signatureURL: measurementsSignatureURL,
|
||||
insecure: insecure,
|
||||
configPath: config,
|
||||
force: force,
|
||||
}, nil
|
||||
|
|
|
@ -9,11 +9,11 @@ package cmd
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfig"
|
||||
|
@ -233,31 +233,39 @@ func TestConfigFetchMeasurements(t *testing.T) {
|
|||
})
|
||||
|
||||
testCases := map[string]struct {
|
||||
cosign cosignVerifier
|
||||
rekor rekorVerifier
|
||||
wantErr bool
|
||||
cosign cosignVerifier
|
||||
rekor rekorVerifier
|
||||
insecureFlag bool
|
||||
wantErr bool
|
||||
}{
|
||||
"success": {
|
||||
cosign: &stubCosignVerifier{},
|
||||
rekor: singleUUIDVerifier(),
|
||||
},
|
||||
"success without cosign": {
|
||||
insecureFlag: true,
|
||||
cosign: &stubCosignVerifier{
|
||||
verifyError: assert.AnError,
|
||||
},
|
||||
rekor: singleUUIDVerifier(),
|
||||
},
|
||||
"failing search should not result in error": {
|
||||
cosign: &stubCosignVerifier{},
|
||||
rekor: &stubRekorVerifier{
|
||||
SearchByHashUUIDs: []string{},
|
||||
SearchByHashError: errors.New("some error"),
|
||||
SearchByHashError: assert.AnError,
|
||||
},
|
||||
},
|
||||
"failing verify should not result in error": {
|
||||
cosign: &stubCosignVerifier{},
|
||||
rekor: &stubRekorVerifier{
|
||||
SearchByHashUUIDs: []string{"11111111111111111111111111111111111111111111111111111111111111111111111111111111"},
|
||||
VerifyEntryError: errors.New("some error"),
|
||||
VerifyEntryError: assert.AnError,
|
||||
},
|
||||
},
|
||||
"signature verification failure": {
|
||||
cosign: &stubCosignVerifier{
|
||||
verifyError: errors.New("some error"),
|
||||
verifyError: assert.AnError,
|
||||
},
|
||||
rekor: singleUUIDVerifier(),
|
||||
wantErr: true,
|
||||
|
@ -272,6 +280,7 @@ func TestConfigFetchMeasurements(t *testing.T) {
|
|||
cmd := newConfigFetchMeasurementsCmd()
|
||||
cmd.Flags().String("config", constants.ConfigFilename, "") // register persistent flag manually
|
||||
cmd.Flags().Bool("force", true, "") // register persistent flag manually
|
||||
require.NoError(cmd.Flags().Set("insecure", strconv.FormatBool(tc.insecureFlag)))
|
||||
fileHandler := file.NewHandler(afero.NewMemMapFs())
|
||||
|
||||
gcpConfig := defaultConfigWithExpectedMeasurements(t, config.Default(), cloudprovider.GCP)
|
||||
|
@ -281,7 +290,7 @@ func TestConfigFetchMeasurements(t *testing.T) {
|
|||
require.NoError(err)
|
||||
cfm := &configFetchMeasurementsCmd{canFetchMeasurements: true, log: logger.NewTest(t)}
|
||||
|
||||
err = cfm.configFetchMeasurements(cmd, tc.cosign, tc.rekor, fileHandler, fakeAttestationFetcher{}, client)
|
||||
err = cfm.configFetchMeasurements(cmd, tc.cosign, tc.rekor, fileHandler, stubAttestationFetcher{}, client)
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
|
@ -291,21 +300,21 @@ func TestConfigFetchMeasurements(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
type fakeAttestationFetcher struct{}
|
||||
type stubAttestationFetcher struct{}
|
||||
|
||||
func (f fakeAttestationFetcher) FetchAzureSEVSNPVersionList(_ context.Context, _ attestationconfig.AzureSEVSNPVersionList) (attestationconfig.AzureSEVSNPVersionList, error) {
|
||||
func (f stubAttestationFetcher) FetchAzureSEVSNPVersionList(_ context.Context, _ attestationconfig.AzureSEVSNPVersionList) (attestationconfig.AzureSEVSNPVersionList, error) {
|
||||
return attestationconfig.AzureSEVSNPVersionList(
|
||||
[]string{},
|
||||
), nil
|
||||
}
|
||||
|
||||
func (f fakeAttestationFetcher) FetchAzureSEVSNPVersion(_ context.Context, _ attestationconfig.AzureSEVSNPVersionAPI) (attestationconfig.AzureSEVSNPVersionAPI, error) {
|
||||
func (f stubAttestationFetcher) FetchAzureSEVSNPVersion(_ context.Context, _ attestationconfig.AzureSEVSNPVersionAPI) (attestationconfig.AzureSEVSNPVersionAPI, error) {
|
||||
return attestationconfig.AzureSEVSNPVersionAPI{
|
||||
AzureSEVSNPVersion: testCfg,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f fakeAttestationFetcher) FetchAzureSEVSNPVersionLatest(_ context.Context) (attestationconfig.AzureSEVSNPVersionAPI, error) {
|
||||
func (f stubAttestationFetcher) FetchAzureSEVSNPVersionLatest(_ context.Context) (attestationconfig.AzureSEVSNPVersionAPI, error) {
|
||||
return attestationconfig.AzureSEVSNPVersionAPI{
|
||||
AzureSEVSNPVersion: testCfg,
|
||||
}, nil
|
||||
|
|
|
@ -202,7 +202,7 @@ func TestCreate(t *testing.T) {
|
|||
|
||||
fileHandler := file.NewHandler(tc.setupFs(require, tc.provider))
|
||||
c := &createCmd{log: logger.NewTest(t)}
|
||||
err := c.create(cmd, tc.creator, fileHandler, &nopSpinner{}, fakeAttestationFetcher{})
|
||||
err := c.create(cmd, tc.creator, fileHandler, &nopSpinner{}, stubAttestationFetcher{})
|
||||
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
|
|
|
@ -175,7 +175,7 @@ func TestInitialize(t *testing.T) {
|
|||
defer cancel()
|
||||
cmd.SetContext(ctx)
|
||||
i := &initCmd{log: logger.NewTest(t), spinner: &nopSpinner{}}
|
||||
err := i.initialize(cmd, newDialer, fileHandler, &stubLicenseClient{}, fakeAttestationFetcher{})
|
||||
err := i.initialize(cmd, newDialer, fileHandler, &stubLicenseClient{}, stubAttestationFetcher{})
|
||||
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
|
@ -519,7 +519,7 @@ func TestAttestation(t *testing.T) {
|
|||
cmd.SetContext(ctx)
|
||||
|
||||
i := &initCmd{log: logger.NewTest(t), spinner: &nopSpinner{}}
|
||||
err := i.initialize(cmd, newDialer, fileHandler, &stubLicenseClient{}, fakeAttestationFetcher{})
|
||||
err := i.initialize(cmd, newDialer, fileHandler, &stubLicenseClient{}, stubAttestationFetcher{})
|
||||
assert.Error(err)
|
||||
// make sure the error is actually a TLS handshake error
|
||||
assert.Contains(err.Error(), "transport: authentication handshake failed")
|
||||
|
|
|
@ -163,7 +163,7 @@ func TestRecover(t *testing.T) {
|
|||
))
|
||||
|
||||
newDialer := func(atls.Validator) *dialer.Dialer { return nil }
|
||||
r := &recoverCmd{log: logger.NewTest(t), configFetcher: fakeAttestationFetcher{}}
|
||||
r := &recoverCmd{log: logger.NewTest(t), configFetcher: stubAttestationFetcher{}}
|
||||
err := r.recover(cmd, fileHandler, time.Millisecond, tc.doer, newDialer)
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
|
|
|
@ -142,7 +142,7 @@ func TestUpgradeApply(t *testing.T) {
|
|||
require.NoError(handler.WriteYAML(constants.ConfigFilename, cfg))
|
||||
require.NoError(handler.WriteJSON(constants.ClusterIDsFileName, clusterid.File{}))
|
||||
|
||||
upgrader := upgradeApplyCmd{upgrader: tc.upgrader, log: logger.NewTest(t), imageFetcher: tc.fetcher, configFetcher: fakeAttestationFetcher{}}
|
||||
upgrader := upgradeApplyCmd{upgrader: tc.upgrader, log: logger.NewTest(t), imageFetcher: tc.fetcher, configFetcher: stubAttestationFetcher{}}
|
||||
err := upgrader.upgradeApply(cmd, handler)
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
|
|
|
@ -271,7 +271,7 @@ func TestUpgradeCheck(t *testing.T) {
|
|||
|
||||
cmd := newUpgradeCheckCmd()
|
||||
|
||||
err := checkCmd.upgradeCheck(cmd, fileHandler, fakeAttestationFetcher{}, tc.flags)
|
||||
err := checkCmd.upgradeCheck(cmd, fileHandler, stubAttestationFetcher{}, tc.flags)
|
||||
if tc.wantError {
|
||||
assert.Error(err)
|
||||
return
|
||||
|
|
|
@ -190,7 +190,7 @@ func TestVerify(t *testing.T) {
|
|||
}
|
||||
|
||||
v := &verifyCmd{log: logger.NewTest(t)}
|
||||
err := v.verify(cmd, fileHandler, tc.protoClient, tc.formatter, fakeAttestationFetcher{})
|
||||
err := v.verify(cmd, fileHandler, tc.protoClient, tc.formatter, stubAttestationFetcher{})
|
||||
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue