diff --git a/cli/internal/cmd/BUILD.bazel b/cli/internal/cmd/BUILD.bazel index 446561891..3340734c6 100644 --- a/cli/internal/cmd/BUILD.bazel +++ b/cli/internal/cmd/BUILD.bazel @@ -40,6 +40,7 @@ go_library( "//bootstrapper/initproto", "//cli/internal/cloudcmd", "//cli/internal/clusterid", + "//cli/internal/featureset", "//cli/internal/helm", "//cli/internal/iamid", "//cli/internal/kubernetes", diff --git a/cli/internal/cmd/configfetchmeasurements.go b/cli/internal/cmd/configfetchmeasurements.go index 1c796a03e..0fc98984d 100644 --- a/cli/internal/cmd/configfetchmeasurements.go +++ b/cli/internal/cmd/configfetchmeasurements.go @@ -14,10 +14,10 @@ import ( "net/url" "time" + "github.com/edgelesssys/constellation/v2/cli/internal/featureset" "github.com/edgelesssys/constellation/v2/internal/api/versionsapi" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "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/spf13/afero" @@ -47,7 +47,8 @@ type fetchMeasurementsFlags struct { } type configFetchMeasurementsCmd struct { - log debugLog + canFetchMeasurements bool + log debugLog } func runConfigFetchMeasurements(cmd *cobra.Command, _ []string) error { @@ -61,7 +62,7 @@ func runConfigFetchMeasurements(cmd *cobra.Command, _ []string) error { if err != nil { return fmt.Errorf("constructing Rekor client: %w", err) } - cfm := &configFetchMeasurementsCmd{log: log} + cfm := &configFetchMeasurementsCmd{log: log, canFetchMeasurements: featureset.CanFetchMeasurements} return cfm.configFetchMeasurements(cmd, sigstore.CosignVerifier{}, rekor, fileHandler, http.DefaultClient) } @@ -76,6 +77,11 @@ func (cfm *configFetchMeasurementsCmd) configFetchMeasurements( } cfm.log.Debugf("Using flags %v", flags) + if !cfm.canFetchMeasurements { + cmd.PrintErrln("Fetching measurements is not supported in the OSS build of the Constellation CLI. Consult the documentation for instructions on where to download the enterprise version.") + return errors.New("fetching measurements is not supported") + } + cfm.log.Debugf("Loading configuration file from %q", flags.configPath) conf, err := config.NewWithClient(fileHandler, flags.configPath, client, flags.force) var configValidationErr *config.ValidationError diff --git a/cli/internal/cmd/configfetchmeasurements_test.go b/cli/internal/cmd/configfetchmeasurements_test.go index 952f09eee..1a5f35d1f 100644 --- a/cli/internal/cmd/configfetchmeasurements_test.go +++ b/cli/internal/cmd/configfetchmeasurements_test.go @@ -277,7 +277,7 @@ func TestConfigFetchMeasurements(t *testing.T) { err := fileHandler.WriteYAML(constants.ConfigFilename, gcpConfig, file.OptMkdirAll) require.NoError(err) - cfm := &configFetchMeasurementsCmd{log: logger.NewTest(t)} + cfm := &configFetchMeasurementsCmd{canFetchMeasurements: true, log: logger.NewTest(t)} err = cfm.configFetchMeasurements(cmd, tc.cosign, tc.rekor, fileHandler, client) if tc.wantErr { diff --git a/cli/internal/cmd/upgradecheck.go b/cli/internal/cmd/upgradecheck.go index c48554bc5..5f6d539d1 100644 --- a/cli/internal/cmd/upgradecheck.go +++ b/cli/internal/cmd/upgradecheck.go @@ -15,6 +15,7 @@ import ( "sort" "strings" + "github.com/edgelesssys/constellation/v2/cli/internal/featureset" "github.com/edgelesssys/constellation/v2/cli/internal/helm" "github.com/edgelesssys/constellation/v2/cli/internal/kubernetes" "github.com/edgelesssys/constellation/v2/internal/api/fetcher" @@ -73,6 +74,7 @@ func runUpgradeCheck(cmd *cobra.Command, _ []string) error { return fmt.Errorf("constructing Rekor client: %w", err) } up := &upgradeCheckCmd{ + canUpgradeCheck: featureset.CanUpgradeCheck, collect: &versionCollector{ writer: cmd.OutOrStderr(), checker: checker, @@ -123,8 +125,9 @@ func parseUpgradeCheckFlags(cmd *cobra.Command) (upgradeCheckFlags, error) { } type upgradeCheckCmd struct { - collect collector - log debugLog + canUpgradeCheck bool + collect collector + log debugLog } // upgradePlan plans an upgrade of a Constellation cluster. @@ -138,6 +141,12 @@ func (u *upgradeCheckCmd) upgradeCheck(cmd *cobra.Command, fileHandler file.Hand return err } u.log.Debugf("Read configuration from %q", flags.configPath) + + if !u.canUpgradeCheck { + cmd.PrintErrln("Planning Constellation upgrades automatically is not supported in the OSS build of the Constellation CLI. Consult the documentation for instructions on where to download the enterprise version.") + return errors.New("upgrade check is not supported") + } + // get current image version of the cluster csp := conf.GetProvider() attestationVariant := conf.GetAttestationConfig().GetVariant() diff --git a/cli/internal/cmd/upgradecheck_test.go b/cli/internal/cmd/upgradecheck_test.go index 5663d55ec..47d02a4de 100644 --- a/cli/internal/cmd/upgradecheck_test.go +++ b/cli/internal/cmd/upgradecheck_test.go @@ -264,8 +264,9 @@ func TestUpgradeCheck(t *testing.T) { require.NoError(fileHandler.WriteYAML(tc.flags.configPath, cfg)) checkCmd := upgradeCheckCmd{ - collect: &tc.collector, - log: logger.NewTest(t), + canUpgradeCheck: true, + collect: &tc.collector, + log: logger.NewTest(t), } cmd := newUpgradeCheckCmd() diff --git a/cli/internal/featureset/BUILD.bazel b/cli/internal/featureset/BUILD.bazel new file mode 100644 index 000000000..17e2db12a --- /dev/null +++ b/cli/internal/featureset/BUILD.bazel @@ -0,0 +1,14 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "featureset", + srcs = [ + "featureset.go", + # keep + "featureset_enterprise.go", + # keep + "featureset_oss.go", + ], + importpath = "github.com/edgelesssys/constellation/v2/cli/internal/featureset", + visibility = ["//cli:__subpackages__"], +) diff --git a/cli/internal/featureset/featureset.go b/cli/internal/featureset/featureset.go new file mode 100644 index 000000000..ae0c9f050 --- /dev/null +++ b/cli/internal/featureset/featureset.go @@ -0,0 +1,28 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +// package featureset provides a way to check whether a feature is enabled in the current build. +package featureset + +// Edition is the edition of a build. +type Edition int + +const ( + // EditionOSS is the open-source software edition. + EditionOSS Edition = iota + // EditionEnterprise is the enterprise edition. + EditionEnterprise +) + +// CanFetchMeasurements returns whether the current build can fetch measurements. +const CanFetchMeasurements = canFetchMeasurements + +// CanUpgradeCheck returns whether the current build can check for upgrades. +// This also includes fetching new measurements. +const CanUpgradeCheck = canUpgradeCheck + +// CurrentEdition is the edition of the current build. +const CurrentEdition = edition diff --git a/cli/internal/featureset/featureset_enterprise.go b/cli/internal/featureset/featureset_enterprise.go new file mode 100644 index 000000000..cb1b0157f --- /dev/null +++ b/cli/internal/featureset/featureset_enterprise.go @@ -0,0 +1,15 @@ +//go:build enterprise + +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package featureset + +const ( + edition = EditionEnterprise + canFetchMeasurements = true + canUpgradeCheck = true +) diff --git a/cli/internal/featureset/featureset_oss.go b/cli/internal/featureset/featureset_oss.go new file mode 100644 index 000000000..426be123f --- /dev/null +++ b/cli/internal/featureset/featureset_oss.go @@ -0,0 +1,15 @@ +//go:build !enterprise + +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package featureset + +const ( + edition = EditionOSS + canFetchMeasurements = false + canUpgradeCheck = false +)