Skip to content

Commit

Permalink
fixup! init
Browse files Browse the repository at this point in the history
  • Loading branch information
elchead committed Nov 24, 2023
1 parent 3cf9786 commit 259e540
Show file tree
Hide file tree
Showing 13 changed files with 259 additions and 326 deletions.
54 changes: 5 additions & 49 deletions cli/internal/cmd/configfetchmeasurements.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"github.com/edgelesssys/constellation/v2/internal/featureset"
"github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/sigstore"
"github.com/edgelesssys/constellation/v2/internal/sigstore/keyselect"
"github.com/spf13/afero"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
Expand Down Expand Up @@ -132,58 +131,15 @@ func (cfm *configFetchMeasurementsCmd) configFetchMeasurements(
if err := cfm.flags.updateURLs(conf); err != nil {
return err
}

cfm.log.Debugf("Fetching and verifying measurements")
imageVersion, err := versionsapi.NewVersionFromShortPath(conf.Image, versionsapi.VersionKindImage)
if err != nil {
return err
}

publicKey, err := keyselect.CosignPublicKeyForVersion(imageVersion)
if err != nil {
return fmt.Errorf("getting public key: %w", err)
}
cosign, err := newCosignVerifier(publicKey)
verifyFetcher := measurements.NewVerifyFetcherWith(newCosignVerifier, cfm.flags.insecure, rekor, client)
fetchedMeasurements, err := verifyFetcher.FetchAndVerifyMeasurements(ctx, conf.Image, conf.GetProvider(), conf.GetAttestationConfig().GetVariant())
if err != nil {
return fmt.Errorf("creating cosign verifier: %w", err)
}

var fetchedMeasurements measurements.M
var hash string
if cfm.flags.insecure {
if err := fetchedMeasurements.FetchNoVerify(
ctx,
client,
cfm.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,
cfm.flags.measurementsURL,
cfm.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(), publicKey, rekor, hash); err != nil {
if _, ok := err.(measurements.ErrRekor); ok {
cmd.PrintErrf("Ignoring Rekor related error: %v\n", err)
cmd.PrintErrln("Make sure the downloaded measurements are trustworthy!")
} else {
return fmt.Errorf("fetching and verifying measurements: %w", err)
}

cfm.log.Debugf("Verified measurements with Rekor")
}
cfm.log.Debugf("Measurements:\n", fetchedMeasurements)

Expand Down
3 changes: 3 additions & 0 deletions internal/attestation/measurements/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ load("//bazel/go:go_test.bzl", "go_test")
go_library(
name = "measurements",
srcs = [
"fetchmeasurements.go",
"measurements.go",
# keep
"measurements_enterprise.go",
Expand All @@ -16,6 +17,8 @@ go_library(
"//internal/api/versionsapi",
"//internal/attestation/variant",
"//internal/cloud/cloudprovider",
"//internal/sigstore",
"//internal/sigstore/keyselect",
"@com_github_google_go_tpm//tpmutil",
"@com_github_siderolabs_talos_pkg_machinery//config/encoder",
"@in_gopkg_yaml_v3//:yaml_v3",
Expand Down
123 changes: 123 additions & 0 deletions internal/attestation/measurements/fetchmeasurements.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/

package measurements

import (
"context"
"fmt"
"net/http"

"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/sigstore"
"github.com/edgelesssys/constellation/v2/internal/sigstore/keyselect"
)

// ErrRekor is returned when verifying measurements with Rekor fails.
type ErrRekor struct {
error
}

func newRekorErr(err error) error {
return ErrRekor{
error: fmt.Errorf("verifying measurements with Rekor: %w", err),
}
}

type cosignVerifierConstructor func([]byte) (sigstore.Verifier, error)

// VerifyFetcher is a high-level fetcher that fetches measurements and verifies them.
type VerifyFetcher struct {
client *http.Client
newCosignVerifier cosignVerifierConstructor
rekor rekorVerifier
noVerify bool // do not verify measurements
}

// NewVerifyFetcher creates a new MeasurementFetcher.
func NewVerifyFetcher(client *http.Client) (*VerifyFetcher, error) {
rekor, err := sigstore.NewRekor()
if err != nil {
return nil, fmt.Errorf("constructing Rekor client: %w", err)
}
return &VerifyFetcher{
newCosignVerifier: sigstore.NewCosignVerifier,
rekor: rekor,
client: client,
}, nil
}

type rekorVerifier interface {
SearchByHash(context.Context, string) ([]string, error)
VerifyEntry(context.Context, string, string) error
}

// NewVerifyFetcherWith creates a new MeasurementFetcher with custom clients.
func NewVerifyFetcherWith(newCosignVerifier func([]byte) (sigstore.Verifier, error), noVerify bool, rekor rekorVerifier, client *http.Client) *VerifyFetcher {
return &VerifyFetcher{
newCosignVerifier: newCosignVerifier,
rekor: rekor,
client: client,
noVerify: noVerify,
}
}

// FetchAndVerifyMeasurements fetches and verifies measurements for the given version and attestation variant.
func (m *VerifyFetcher) FetchAndVerifyMeasurements(ctx context.Context,
image string, csp cloudprovider.Provider, attestationVariant variant.Variant,
) (M, error) {
version, err := versionsapi.NewVersionFromShortPath(image, versionsapi.VersionKindImage)
if err != nil {
return nil, fmt.Errorf("parsing image version: %w", err)
}
publicKey, err := keyselect.CosignPublicKeyForVersion(version)
if err != nil {
return nil, fmt.Errorf("getting public key: %w", err)
}

cosign, err := m.newCosignVerifier(publicKey)
if err != nil {
return nil, fmt.Errorf("creating cosign verifier: %w", err)
}

measurementsURL, signatureURL, err := versionsapi.MeasurementURL(version)
if err != nil {
return nil, err
}
var fetchedMeasurements M
if m.noVerify {
if err := fetchedMeasurements.FetchNoVerify(
ctx,
m.client,
measurementsURL,
version,
csp,
attestationVariant,
); err != nil {
return nil, fmt.Errorf("fetching measurements: %w", err)
}
} else {
hash, err := fetchedMeasurements.FetchAndVerify(
ctx,
m.client,
cosign,
measurementsURL,
signatureURL,
version,
csp,
attestationVariant,
)
if err != nil {
return nil, fmt.Errorf("fetching and verifying measurements: %w", err)
}
if err := sigstore.VerifyWithRekor(ctx, publicKey, m.rekor, hash); err != nil {
return nil, newRekorErr(err)
}
}
return fetchedMeasurements, nil
}
7 changes: 7 additions & 0 deletions internal/attestation/measurements/measurements_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"io"
"net/http"
"net/url"
Expand Down Expand Up @@ -1043,3 +1044,9 @@ func TestMeasurementsCompare(t *testing.T) {
})
}
}

func TestRekorErrCheck(t *testing.T) {
err := newRekorErr(errors.New("test"))
_, ok := err.(ErrRekor)
assert.True(t, ok)
}
9 changes: 4 additions & 5 deletions internal/config/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,24 @@ import (
"fmt"

"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/constellation"
)

// 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].
func DefaultForAzureSEVSNP() *AzureSEVSNP {
azureFirmwareSignerCfg := constellation.DefaultAzureSEVSNPFirmwareSignerConfig()
return &AzureSEVSNP{
Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureSEVSNP{}),
BootloaderVersion: NewLatestPlaceholderVersion(),
TEEVersion: NewLatestPlaceholderVersion(),
SNPVersion: NewLatestPlaceholderVersion(),
MicrocodeVersion: NewLatestPlaceholderVersion(),
FirmwareSignerConfig: SNPFirmwareSignerConfig{ // need to duplicate the struct here to generate docs
AcceptedKeyDigests: azureFirmwareSignerCfg.AcceptedKeyDigests,
EnforcementPolicy: azureFirmwareSignerCfg.EnforcementPolicy,
FirmwareSignerConfig: SNPFirmwareSignerConfig{
AcceptedKeyDigests: idkeydigest.DefaultList(),
EnforcementPolicy: idkeydigest.MAAFallback,
},
// AMD root key. Received from the AMD Key Distribution System API (KDS).
AMDRootKey: mustParsePEM(`-----BEGIN CERTIFICATE-----\nMIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC\nBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS\nBgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg\nQ2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp\nY2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy\nMTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS\nBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j\nZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG\n9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg\nW41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta\n1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2\nSzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0\n60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05\ngmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg\nbKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs\n+gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi\nQi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ\neTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18\nfHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j\nWhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI\nrFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG\nKWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG\nSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI\nAWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel\nETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw\nSTjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK\ndHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq\nzT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp\nKGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e\npmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq\nHnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh\n3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn\nJZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH\nCViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4\nAFZEAwoKCQ==\n-----END CERTIFICATE-----\n`),
Expand Down
105 changes: 0 additions & 105 deletions internal/constellation/azureattestation.go

This file was deleted.

Loading

0 comments on commit 259e540

Please sign in to comment.