mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-08-06 05:54:28 -04:00
api: add functions to transparently handle signatures upon API interaction (#2142)
This commit is contained in:
parent
002c3a9a32
commit
dac690656e
45 changed files with 707 additions and 472 deletions
|
@ -35,6 +35,7 @@ import (
|
|||
"github.com/edgelesssys/constellation/v2/internal/kubernetes/kubectl"
|
||||
consemver "github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
"github.com/edgelesssys/constellation/v2/internal/sigstore"
|
||||
"github.com/edgelesssys/constellation/v2/internal/sigstore/keyselect"
|
||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
|
||||
"github.com/spf13/afero"
|
||||
|
@ -86,7 +87,6 @@ func runUpgradeCheck(cmd *cobra.Command, _ []string) error {
|
|||
verListFetcher: versionfetcher,
|
||||
fileHandler: fileHandler,
|
||||
client: http.DefaultClient,
|
||||
cosign: sigstore.CosignVerifier{},
|
||||
rekor: rekor,
|
||||
flags: flags,
|
||||
cliVersion: constants.BinaryVersion(),
|
||||
|
@ -301,7 +301,7 @@ func sortedMapKeys[T any](a map[string]T) []string {
|
|||
func filterImageUpgrades(currentVersion string, newVersions []versionsapi.Version) []versionsapi.Version {
|
||||
newImages := []versionsapi.Version{}
|
||||
for i := range newVersions {
|
||||
if err := compatibility.IsValidUpgrade(currentVersion, newVersions[i].Version); err != nil {
|
||||
if err := compatibility.IsValidUpgrade(currentVersion, newVersions[i].Version()); err != nil {
|
||||
continue
|
||||
}
|
||||
newImages = append(newImages, newVersions[i])
|
||||
|
@ -338,7 +338,6 @@ type versionCollector struct {
|
|||
verListFetcher versionListFetcher
|
||||
fileHandler file.Handler
|
||||
client *http.Client
|
||||
cosign cosignVerifier
|
||||
rekor rekorVerifier
|
||||
flags upgradeCheckFlags
|
||||
versionsapi versionFetcher
|
||||
|
@ -346,11 +345,30 @@ type versionCollector struct {
|
|||
log debugLog
|
||||
}
|
||||
|
||||
func (v *versionCollector) newMeasurements(ctx context.Context, csp cloudprovider.Provider, attestationVariant variant.Variant, images []versionsapi.Version) (map[string]measurements.M, error) {
|
||||
func (v *versionCollector) newMeasurements(ctx context.Context, csp cloudprovider.Provider, attestationVariant variant.Variant, versions []versionsapi.Version) (map[string]measurements.M, error) {
|
||||
// get expected measurements for each image
|
||||
upgrades, err := getCompatibleImageMeasurements(ctx, v.writer, v.client, v.cosign, v.rekor, csp, attestationVariant, images, v.log)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fetching measurements for compatible images: %w", err)
|
||||
upgrades := make(map[string]measurements.M)
|
||||
for _, version := range versions {
|
||||
v.log.Debugf("Fetching measurements for image: %s", version)
|
||||
shortPath := version.ShortPath()
|
||||
|
||||
publicKey, err := keyselect.CosignPublicKeyForVersion(version)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting public key: %w", err)
|
||||
}
|
||||
cosign, err := sigstore.NewCosignVerifier(publicKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("setting public key: %w", err)
|
||||
}
|
||||
|
||||
measurements, err := getCompatibleImageMeasurements(ctx, v.writer, v.client, cosign, v.rekor, csp, attestationVariant, version, v.log)
|
||||
if err != nil {
|
||||
if _, err := fmt.Fprintf(v.writer, "Skipping compatible image %q: %s\n", shortPath, err); err != nil {
|
||||
return nil, fmt.Errorf("writing to buffer: %w", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
upgrades[shortPath] = measurements
|
||||
}
|
||||
v.log.Debugf("Compatible image measurements are %v", upgrades)
|
||||
|
||||
|
@ -609,49 +627,41 @@ func getCurrentKubernetesVersion(ctx context.Context, checker upgradeChecker) (s
|
|||
}
|
||||
|
||||
// getCompatibleImageMeasurements retrieves the expected measurements for each image.
|
||||
func getCompatibleImageMeasurements(ctx context.Context, writer io.Writer, client *http.Client, cosign cosignVerifier, rekor rekorVerifier,
|
||||
csp cloudprovider.Provider, attestationVariant variant.Variant, versions []versionsapi.Version, log debugLog,
|
||||
) (map[string]measurements.M, error) {
|
||||
upgrades := make(map[string]measurements.M)
|
||||
for _, version := range versions {
|
||||
log.Debugf("Fetching measurements for image: %s", version)
|
||||
shortPath := version.ShortPath()
|
||||
measurementsURL, signatureURL, err := versionsapi.MeasurementURL(version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var fetchedMeasurements measurements.M
|
||||
log.Debugf("Fetching for measurement url: %s", measurementsURL)
|
||||
hash, err := fetchedMeasurements.FetchAndVerify(
|
||||
ctx, client, cosign,
|
||||
measurementsURL,
|
||||
signatureURL,
|
||||
version,
|
||||
csp,
|
||||
attestationVariant,
|
||||
)
|
||||
if err != nil {
|
||||
if _, err := fmt.Fprintf(writer, "Skipping compatible image %q: %s\n", shortPath, err); err != nil {
|
||||
return nil, fmt.Errorf("writing to buffer: %w", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if err = sigstore.VerifyWithRekor(ctx, version, rekor, hash); err != nil {
|
||||
if _, err := fmt.Fprintf(writer, "Warning: Unable to verify '%s' in Rekor.\n", hash); err != nil {
|
||||
return nil, fmt.Errorf("writing to buffer: %w", err)
|
||||
}
|
||||
if _, err := fmt.Fprintf(writer, "Make sure measurements are correct.\n"); err != nil {
|
||||
return nil, fmt.Errorf("writing to buffer: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
upgrades[shortPath] = fetchedMeasurements
|
||||
|
||||
func getCompatibleImageMeasurements(ctx context.Context, writer io.Writer, client *http.Client, cosign sigstore.Verifier, rekor rekorVerifier,
|
||||
csp cloudprovider.Provider, attestationVariant variant.Variant, version versionsapi.Version, log debugLog,
|
||||
) (measurements.M, error) {
|
||||
measurementsURL, signatureURL, err := versionsapi.MeasurementURL(version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return upgrades, nil
|
||||
var fetchedMeasurements measurements.M
|
||||
log.Debugf("Fetching for measurement url: %s", measurementsURL)
|
||||
|
||||
hash, err := fetchedMeasurements.FetchAndVerify(
|
||||
ctx, client, cosign,
|
||||
measurementsURL,
|
||||
signatureURL,
|
||||
version,
|
||||
csp,
|
||||
attestationVariant,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fetching measurements: %w", err)
|
||||
}
|
||||
|
||||
pubkey, err := keyselect.CosignPublicKeyForVersion(version)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting public key: %w", err)
|
||||
}
|
||||
|
||||
if err = sigstore.VerifyWithRekor(ctx, pubkey, rekor, hash); err != nil {
|
||||
if _, err := fmt.Fprintf(writer, "Warning: Unable to verify '%s' in Rekor.\nMake sure measurements are correct.\n", hash); err != nil {
|
||||
return nil, fmt.Errorf("writing to buffer: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return fetchedMeasurements, nil
|
||||
}
|
||||
|
||||
type versionFetcher interface {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue