mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-10-11 10:08:33 -04:00
cli: image measurements (v2)
This commit is contained in:
parent
2ebc0cf2c8
commit
e5b394db87
18 changed files with 274 additions and 195 deletions
|
@ -100,16 +100,19 @@ func (cfm *configFetchMeasurementsCmd) configFetchMeasurements(
|
|||
}
|
||||
|
||||
cfm.log.Debugf("Fetching and verifying measurements")
|
||||
imageVersion, err := versionsapi.NewVersionFromShortPath(conf.Image, versionsapi.VersionKindImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var fetchedMeasurements measurements.M
|
||||
hash, err := fetchedMeasurements.FetchAndVerify(
|
||||
ctx, client,
|
||||
flags.measurementsURL,
|
||||
flags.signatureURL,
|
||||
cosignPublicKey,
|
||||
measurements.WithMetadata{
|
||||
CSP: conf.GetProvider(),
|
||||
Image: conf.Image,
|
||||
},
|
||||
imageVersion,
|
||||
conf.GetProvider(),
|
||||
conf.GetAttestationConfig().GetVariant(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -182,7 +185,7 @@ func (f *fetchMeasurementsFlags) updateURLs(conf *config.Config) error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("creating version from image name: %w", err)
|
||||
}
|
||||
measurementsURL, signatureURL, err := versionsapi.MeasurementURL(ver, conf.GetProvider())
|
||||
measurementsURL, signatureURL, err := versionsapi.MeasurementURL(ver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -119,8 +119,8 @@ func TestUpdateURLs(t *testing.T) {
|
|||
},
|
||||
},
|
||||
flags: &fetchMeasurementsFlags{},
|
||||
wantMeasurementsURL: ver.ArtifactsURL() + "/image/csp/gcp/measurements.json",
|
||||
wantMeasurementsSigURL: ver.ArtifactsURL() + "/image/csp/gcp/measurements.json.sig",
|
||||
wantMeasurementsURL: ver.ArtifactsURL("v2") + "/image/measurements.json",
|
||||
wantMeasurementsSigURL: ver.ArtifactsURL("v2") + "/image/measurements.json.sig",
|
||||
},
|
||||
"both set by user": {
|
||||
conf: &config.Config{
|
||||
|
@ -181,30 +181,58 @@ func TestConfigFetchMeasurements(t *testing.T) {
|
|||
cosignPublicKey := []byte("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEu78QgxOOcao6U91CSzEXxrKhvFTt\nJHNy+eX6EMePtDm8CnDF9HSwnTlD0itGJ/XHPQA5YX10fJAqI1y+ehlFMw==\n-----END PUBLIC KEY-----")
|
||||
|
||||
measurements := `{
|
||||
"csp": "gcp",
|
||||
"image": "v999.999.999",
|
||||
"measurements": {
|
||||
"0": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"1": "1111111111111111111111111111111111111111111111111111111111111111",
|
||||
"2": "2222222222222222222222222222222222222222222222222222222222222222",
|
||||
"3": "3333333333333333333333333333333333333333333333333333333333333333",
|
||||
"4": "4444444444444444444444444444444444444444444444444444444444444444",
|
||||
"5": "5555555555555555555555555555555555555555555555555555555555555555",
|
||||
"6": "6666666666666666666666666666666666666666666666666666666666666666"
|
||||
}
|
||||
"version": "v999.999.999",
|
||||
"ref": "-",
|
||||
"stream": "stable",
|
||||
"list": [
|
||||
{
|
||||
"csp": "GCP",
|
||||
"attestationVariant":"gcp-sev-es",
|
||||
"measurements": {
|
||||
"0": {
|
||||
"expected": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"warnOnly":false
|
||||
},
|
||||
"1": {
|
||||
"expected": "1111111111111111111111111111111111111111111111111111111111111111",
|
||||
"warnOnly":false
|
||||
},
|
||||
"2": {
|
||||
"expected": "2222222222222222222222222222222222222222222222222222222222222222",
|
||||
"warnOnly":false
|
||||
},
|
||||
"3": {
|
||||
"expected": "3333333333333333333333333333333333333333333333333333333333333333",
|
||||
"warnOnly":false
|
||||
},
|
||||
"4": {
|
||||
"expected": "4444444444444444444444444444444444444444444444444444444444444444",
|
||||
"warnOnly":false
|
||||
},
|
||||
"5": {
|
||||
"expected": "5555555555555555555555555555555555555555555555555555555555555555",
|
||||
"warnOnly":false
|
||||
},
|
||||
"6": {
|
||||
"expected": "6666666666666666666666666666666666666666666666666666666666666666",
|
||||
"warnOnly":false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
signature := "MEYCIQDRAQNK2NjHJBGrnw3HQAyBsXMCmVCptBdgA6VZ3IlyiAIhAPG42waF1aFZq7dnjP3b2jsMNUtaKYDQQSazW1AX8jgF"
|
||||
signature := "MEUCIHQETkvMRy8WaWMroX4Aa2J86bTW0kGMp8NG0YLXJKZJAiEA7ZdxoQzSTyBFNhZ1bwB5eT3av0biAdb66dJRFxQlKLA="
|
||||
|
||||
client := newTestClient(func(req *http.Request) *http.Response {
|
||||
if req.URL.Path == "/constellation/v1/ref/-/stream/stable/v999.999.999/image/csp/gcp/measurements.json" {
|
||||
if req.URL.Path == "/constellation/v2/ref/-/stream/stable/v999.999.999/image/measurements.json" {
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: io.NopCloser(bytes.NewBufferString(measurements)),
|
||||
Header: make(http.Header),
|
||||
}
|
||||
}
|
||||
if req.URL.Path == "/constellation/v1/ref/-/stream/stable/v999.999.999/image/csp/gcp/measurements.json.sig" {
|
||||
if req.URL.Path == "/constellation/v2/ref/-/stream/stable/v999.999.999/image/measurements.json.sig" {
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: io.NopCloser(bytes.NewBufferString(signature)),
|
||||
|
|
|
@ -26,6 +26,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/variant"
|
||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
||||
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
|
||||
"github.com/edgelesssys/constellation/v2/internal/versionsapi/fetcher"
|
||||
|
@ -139,7 +140,8 @@ func (u *upgradeCheckCmd) upgradeCheck(cmd *cobra.Command, fileHandler file.Hand
|
|||
u.log.Debugf("Read configuration from %q", flags.configPath)
|
||||
// get current image version of the cluster
|
||||
csp := conf.GetProvider()
|
||||
u.log.Debugf("Using provider %s", csp.String())
|
||||
attestationVariant := conf.GetAttestationConfig().GetVariant()
|
||||
u.log.Debugf("Using provider %s with attestation variant %s", csp.String(), attestationVariant.String())
|
||||
|
||||
current, err := u.collect.currentVersions(cmd.Context())
|
||||
if err != nil {
|
||||
|
@ -167,7 +169,7 @@ func (u *upgradeCheckCmd) upgradeCheck(cmd *cobra.Command, fileHandler file.Hand
|
|||
semver.Sort(newKubernetes)
|
||||
|
||||
supported.image = filterImageUpgrades(current.image, supported.image)
|
||||
newImages, err := u.collect.newMeasurements(cmd.Context(), csp, supported.image)
|
||||
newImages, err := u.collect.newMeasurements(cmd.Context(), csp, attestationVariant, supported.image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -240,7 +242,7 @@ type collector interface {
|
|||
currentVersions(ctx context.Context) (currentVersionInfo, error)
|
||||
supportedVersions(ctx context.Context, version, currentK8sVersion string) (supportedVersionInfo, error)
|
||||
newImages(ctx context.Context, version string) ([]versionsapi.Version, error)
|
||||
newMeasurements(ctx context.Context, csp cloudprovider.Provider, images []versionsapi.Version) (map[string]measurements.M, error)
|
||||
newMeasurements(ctx context.Context, csp cloudprovider.Provider, attestationVariant variant.Variant, images []versionsapi.Version) (map[string]measurements.M, error)
|
||||
newerVersions(ctx context.Context, allowedVersions []string) ([]versionsapi.Version, error)
|
||||
newCLIVersions(ctx context.Context) ([]string, error)
|
||||
filterCompatibleCLIVersions(ctx context.Context, cliPatchVersions []string, currentK8sVersion string) ([]string, error)
|
||||
|
@ -259,9 +261,9 @@ type versionCollector struct {
|
|||
log debugLog
|
||||
}
|
||||
|
||||
func (v *versionCollector) newMeasurements(ctx context.Context, csp cloudprovider.Provider, images []versionsapi.Version) (map[string]measurements.M, error) {
|
||||
func (v *versionCollector) newMeasurements(ctx context.Context, csp cloudprovider.Provider, attestationVariant variant.Variant, images []versionsapi.Version) (map[string]measurements.M, error) {
|
||||
// get expected measurements for each image
|
||||
upgrades, err := getCompatibleImageMeasurements(ctx, v.writer, v.client, v.rekor, []byte(v.flags.cosignPubKey), csp, images, v.log)
|
||||
upgrades, err := getCompatibleImageMeasurements(ctx, v.writer, v.client, v.rekor, []byte(v.flags.cosignPubKey), csp, attestationVariant, images, v.log)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fetching measurements for compatible images: %w", err)
|
||||
}
|
||||
|
@ -524,13 +526,13 @@ 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, rekor rekorVerifier, pubK []byte,
|
||||
csp cloudprovider.Provider, versions []versionsapi.Version, log debugLog,
|
||||
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, csp)
|
||||
measurementsURL, signatureURL, err := versionsapi.MeasurementURL(version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -542,10 +544,9 @@ func getCompatibleImageMeasurements(ctx context.Context, writer io.Writer, clien
|
|||
measurementsURL,
|
||||
signatureURL,
|
||||
pubK,
|
||||
measurements.WithMetadata{
|
||||
CSP: csp,
|
||||
Image: shortPath,
|
||||
},
|
||||
version,
|
||||
csp,
|
||||
attestationVariant,
|
||||
)
|
||||
if err != nil {
|
||||
if _, err := fmt.Fprintf(writer, "Skipping compatible image %q: %s\n", shortPath, err); err != nil {
|
||||
|
|
|
@ -150,6 +150,7 @@ func TestGetCompatibleImageMeasurements(t *testing.T) {
|
|||
assert := assert.New(t)
|
||||
|
||||
csp := cloudprovider.Azure
|
||||
attestationVariant := variant.AzureSEVSNP{}
|
||||
zero := versionsapi.Version{
|
||||
Ref: "-",
|
||||
Stream: "stable",
|
||||
|
@ -204,7 +205,7 @@ func TestGetCompatibleImageMeasurements(t *testing.T) {
|
|||
|
||||
pubK := []byte("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEu78QgxOOcao6U91CSzEXxrKhvFTt\nJHNy+eX6EMePtDm8CnDF9HSwnTlD0itGJ/XHPQA5YX10fJAqI1y+ehlFMw==\n-----END PUBLIC KEY-----")
|
||||
|
||||
upgrades, err := getCompatibleImageMeasurements(context.Background(), &bytes.Buffer{}, client, singleUUIDVerifier(), pubK, csp, images, logger.NewTest(t))
|
||||
upgrades, err := getCompatibleImageMeasurements(context.Background(), &bytes.Buffer{}, client, singleUUIDVerifier(), pubK, csp, attestationVariant, images, logger.NewTest(t))
|
||||
assert.NoError(err)
|
||||
|
||||
for _, measurement := range upgrades {
|
||||
|
@ -297,7 +298,7 @@ type stubVersionCollector struct {
|
|||
someErr error
|
||||
}
|
||||
|
||||
func (s *stubVersionCollector) newMeasurements(_ context.Context, _ cloudprovider.Provider, _ []versionsapi.Version) (map[string]measurements.M, error) {
|
||||
func (s *stubVersionCollector) newMeasurements(_ context.Context, _ cloudprovider.Provider, _ variant.Variant, _ []versionsapi.Version) (map[string]measurements.M, error) {
|
||||
return s.supportedImageVersions, nil
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue