Improve measurements verification with Rekor (#206)

Fetched measurements are now verified using Rekor in addition to a signature check.
Signed-off-by: Fabian Kammel <fk@edgeless.systems>
This commit is contained in:
Fabian Kammel 2022-10-11 13:57:52 +02:00 committed by GitHub
parent 1c29638421
commit 57b8efd1ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 1320 additions and 322 deletions

View file

@ -21,6 +21,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/sigstore"
"github.com/manifoldco/promptui"
"github.com/spf13/afero"
"github.com/spf13/cobra"
@ -60,13 +61,17 @@ func runUpgradePlan(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
rekor, err := sigstore.NewRekor()
if err != nil {
return fmt.Errorf("constructing Rekor client: %w", err)
}
return upgradePlan(cmd, planner, fileHandler, http.DefaultClient, flags)
return upgradePlan(cmd, planner, fileHandler, http.DefaultClient, rekor, flags)
}
// upgradePlan plans an upgrade of a Constellation cluster.
func upgradePlan(cmd *cobra.Command, planner upgradePlanner,
fileHandler file.Handler, client *http.Client, flags upgradePlanFlags,
fileHandler file.Handler, client *http.Client, rekor rekorVerifier, flags upgradePlanFlags,
) error {
config, err := config.FromFile(fileHandler, flags.configPath)
if err != nil {
@ -93,7 +98,7 @@ func upgradePlan(cmd *cobra.Command, planner upgradePlanner,
}
// get expected measurements for each image
if err := getCompatibleImageMeasurements(cmd.Context(), client, []byte(flags.cosignPubKey), compatibleImages); err != nil {
if err := getCompatibleImageMeasurements(cmd.Context(), client, rekor, []byte(flags.cosignPubKey), compatibleImages); err != nil {
return fmt.Errorf("fetching measurements for compatible images: %w", err)
}
@ -174,7 +179,7 @@ func getCompatibleImages(csp cloudprovider.Provider, currentVersion string, imag
}
// getCompatibleImageMeasurements retrieves the expected measurements for each image.
func getCompatibleImageMeasurements(ctx context.Context, client *http.Client, pubK []byte, images map[string]config.UpgradeConfig) error {
func getCompatibleImageMeasurements(ctx context.Context, client *http.Client, rekor rekorVerifier, pubK []byte, images map[string]config.UpgradeConfig) error {
for idx, img := range images {
measurementsURL, err := url.Parse(constants.S3PublicBucket + img.Image + "/measurements.yaml")
if err != nil {
@ -186,9 +191,16 @@ func getCompatibleImageMeasurements(ctx context.Context, client *http.Client, pu
return err
}
if err := img.Measurements.FetchAndVerify(ctx, client, measurementsURL, signatureURL, pubK); err != nil {
hash, err := img.Measurements.FetchAndVerify(ctx, client, measurementsURL, signatureURL, pubK)
if err != nil {
return err
}
if err = verifyWithRekor(ctx, rekor, hash); err != nil {
fmt.Printf("Warning: Unable to verify '%s' in Rekor.\n", hash)
fmt.Printf("Make sure measurements are correct.\n")
}
images[idx] = img
}