constellation/cli/internal/cmd/configfetchmeasurements.go
Fabian Kammel 170a8bf5e0 AB#2306 Public image sharing in Google (#358)
* document how to publicly share images in gcloud
* Write disclamer in debugd
* Add disclamer about debug images to contributing file
* Print debug banner on startup
Signed-off-by: Fabian Kammel <fk@edgeless.systems>
2022-08-16 15:53:54 +02:00

130 lines
3.6 KiB
Go

package cmd
import (
"context"
"fmt"
"net/http"
"net/url"
"time"
"github.com/edgelesssys/constellation/internal/config"
"github.com/edgelesssys/constellation/internal/constants"
"github.com/edgelesssys/constellation/internal/file"
"github.com/spf13/afero"
"github.com/spf13/cobra"
)
func newConfigFetchMeasurementsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "fetch-measurements",
Short: "Fetch measurements for configured cloud provider and image",
Long: "Fetch measurements for configured cloud provider and image. A config needs to be generated first!",
Args: cobra.ExactArgs(0),
RunE: runConfigFetchMeasurements,
}
cmd.Flags().StringP("url", "u", "", "alternative URL to fetch measurements from")
cmd.Flags().StringP("signature-url", "s", "", "alternative URL to fetch measurements' signature from")
return cmd
}
type fetchMeasurementsFlags struct {
measurementsURL *url.URL
signatureURL *url.URL
config string
}
func runConfigFetchMeasurements(cmd *cobra.Command, args []string) error {
fileHandler := file.NewHandler(afero.NewOsFs())
return configFetchMeasurements(cmd, fileHandler, http.DefaultClient)
}
func configFetchMeasurements(cmd *cobra.Command, fileHandler file.Handler, client *http.Client) error {
flags, err := parseFetchMeasurementsFlags(cmd)
if err != nil {
return err
}
conf, err := config.FromFile(fileHandler, flags.config)
if err != nil {
return err
}
if conf.IsImageDebug() {
cmd.Println("Configured image does not look like a released production image. Double check image before deploying to production.")
}
if err := flags.updateURLs(conf); err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
var fetchedMeasurements config.Measurements
if err := fetchedMeasurements.FetchAndVerify(ctx, client, flags.measurementsURL, flags.signatureURL, []byte(constants.CosignPublicKey)); err != nil {
return err
}
conf.UpdateMeasurements(fetchedMeasurements)
if err := fileHandler.WriteYAML(flags.config, conf, file.OptOverwrite); err != nil {
return err
}
return nil
}
// parseURLFlag checks that flag can be parsed as URL.
// If no value was provided for flag, nil is returned.
func parseURLFlag(cmd *cobra.Command, flag string) (*url.URL, error) {
rawURL, err := cmd.Flags().GetString(flag)
if err != nil {
return nil, fmt.Errorf("parsing config generate flags '%s': %w", flag, err)
}
if rawURL != "" {
return url.Parse(rawURL)
}
return nil, nil
}
func parseFetchMeasurementsFlags(cmd *cobra.Command) (*fetchMeasurementsFlags, error) {
measurementsURL, err := parseURLFlag(cmd, "url")
if err != nil {
return &fetchMeasurementsFlags{}, err
}
measurementsSignatureURL, err := parseURLFlag(cmd, "signature-url")
if err != nil {
return &fetchMeasurementsFlags{}, err
}
config, err := cmd.Flags().GetString("config")
if err != nil {
return &fetchMeasurementsFlags{}, fmt.Errorf("parsing config path argument: %w", err)
}
return &fetchMeasurementsFlags{
measurementsURL: measurementsURL,
signatureURL: measurementsSignatureURL,
config: config,
}, nil
}
func (f *fetchMeasurementsFlags) updateURLs(conf *config.Config) error {
if f.measurementsURL == nil {
parsedURL, err := url.Parse(constants.S3PublicBucket + conf.Image() + "/measurements.yaml")
if err != nil {
return err
}
f.measurementsURL = parsedURL
}
if f.signatureURL == nil {
parsedURL, err := url.Parse(constants.S3PublicBucket + conf.Image() + "/measurements.yaml.sig")
if err != nil {
return err
}
f.signatureURL = parsedURL
}
return nil
}