From c20f5bae9497193fa45e6175f67e15b0aa2e2c16 Mon Sep 17 00:00:00 2001 From: Markus Rudy Date: Tue, 30 Jan 2024 15:56:28 +0100 Subject: [PATCH] cli: optionally validate coordinator in set and verify --- cli/set.go | 14 +++++++++++++- cli/verify.go | 18 ++++++++++++++++-- justfile | 2 ++ packages/default.nix | 9 +++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/cli/set.go b/cli/set.go index d3f5e07dba..3f59b27d04 100644 --- a/cli/set.go +++ b/cli/set.go @@ -2,6 +2,7 @@ package main import ( "context" + "encoding/hex" "encoding/json" "fmt" "io" @@ -41,6 +42,8 @@ func newSetCmd() *cobra.Command { cmd.Flags().StringP("manifest", "m", manifestFilename, "path to manifest (.json) file") cmd.Flags().StringP("coordinator", "c", "", "endpoint the coordinator can be reached at") must(cobra.MarkFlagRequired(cmd.Flags(), "coordinator")) + // TODO(burgerdev): default --policy should be derived from released artifacts. + cmd.Flags().String("policy", "", "expected policy hash of the coordinator (64 hex-encoded bytes, will not be checked if empty)") return cmd } @@ -84,7 +87,7 @@ func runSet(cmd *cobra.Command, args []string) error { } log.Debug("Using KDS cache dir", "dir", kdsDir) - validateOptsGen := newCoordinatorValidateOptsGen() + validateOptsGen := newCoordinatorValidateOptsGen(flags.policy) kdsCache := fsstore.New(kdsDir, log.WithGroup("kds-cache")) kdsGetter := snp.NewCachedHTTPSGetter(kdsCache, snp.NeverGCTicker, log.WithGroup("kds-getter")) validator := snp.NewValidator(validateOptsGen, kdsGetter, log.WithGroup("snp-validator")) @@ -122,6 +125,7 @@ func runSet(cmd *cobra.Command, args []string) error { type setFlags struct { manifestPath string coordinator string + policy []byte } func parseSetFlags(cmd *cobra.Command) (*setFlags, error) { @@ -136,6 +140,14 @@ func parseSetFlags(cmd *cobra.Command) (*setFlags, error) { if err != nil { return nil, fmt.Errorf("failed to get coordinator flag: %w", err) } + policyString, err := cmd.Flags().GetString("policy") + if err != nil { + return nil, fmt.Errorf("failed to get policy flag: %w", err) + } + flags.policy, err = hex.DecodeString(policyString) + if err != nil { + return nil, fmt.Errorf("hex-decoding policy flag: %w", err) + } return flags, nil } diff --git a/cli/verify.go b/cli/verify.go index 83af8c94df..1365e5c210 100644 --- a/cli/verify.go +++ b/cli/verify.go @@ -2,6 +2,7 @@ package main import ( "crypto/sha256" + "encoding/hex" "fmt" "net" "os" @@ -40,6 +41,8 @@ func newVerifyCmd() *cobra.Command { cmd.Flags().StringP("output", "o", verifyDir, "directory to write files to") cmd.Flags().StringP("coordinator", "c", "", "endpoint the coordinator can be reached at") must(cobra.MarkFlagRequired(cmd.Flags(), "coordinator")) + // TODO(burgerdev): default --policy should be derived from released artifacts. + cmd.Flags().String("policy", "", "expected policy hash of the coordinator (64 hex-encoded bytes, will not be checked if empty)") return cmd } @@ -62,7 +65,7 @@ func runVerify(cmd *cobra.Command, _ []string) error { } log.Debug("Using KDS cache dir", "dir", kdsDir) - validateOptsGen := newCoordinatorValidateOptsGen() + validateOptsGen := newCoordinatorValidateOptsGen(flags.policy) kdsCache := fsstore.New(kdsDir, log.WithGroup("kds-cache")) kdsGetter := snp.NewCachedHTTPSGetter(kdsCache, snp.NeverGCTicker, log.WithGroup("kds-getter")) validator := snp.NewValidator(validateOptsGen, kdsGetter, log.WithGroup("snp-validator")) @@ -107,6 +110,7 @@ func runVerify(cmd *cobra.Command, _ []string) error { type verifyFlags struct { coordinator string outputDir string + policy []byte } func parseVerifyFlags(cmd *cobra.Command) (*verifyFlags, error) { @@ -118,14 +122,23 @@ func parseVerifyFlags(cmd *cobra.Command) (*verifyFlags, error) { if err != nil { return nil, err } + policyString, err := cmd.Flags().GetString("policy") + if err != nil { + return nil, err + } + policy, err := hex.DecodeString(policyString) + if err != nil { + return nil, fmt.Errorf("hex-decoding policy flag: %w", err) + } return &verifyFlags{ coordinator: coordinator, outputDir: outputDir, + policy: policy, }, nil } -func newCoordinatorValidateOptsGen() *snp.StaticValidateOptsGenerator { +func newCoordinatorValidateOptsGen(hostData []byte) *snp.StaticValidateOptsGenerator { defaultManifest := manifest.Default() trustedIDKeyDigests, err := (&defaultManifest.ReferenceValues.SNP.TrustedIDKeyHashes).ByteSlices() if err != nil { @@ -134,6 +147,7 @@ func newCoordinatorValidateOptsGen() *snp.StaticValidateOptsGenerator { return &snp.StaticValidateOptsGenerator{ Opts: &validate.Options{ + HostData: hostData, GuestPolicy: abi.SnpPolicy{ Debug: false, SMT: true, diff --git a/justfile b/justfile index c2be699215..982bbde98b 100644 --- a/justfile +++ b/justfile @@ -76,9 +76,11 @@ set: trap "kill $PID" EXIT nix run .#wait-for-port-listen -- 1313 t=$(date +%s) + policy=$(nix run .#get-coordinator-policy -- ./{{ workspace_dir }}/manifest.json) nix run .#cli -- set \ -m ./{{ workspace_dir }}/manifest.json \ -c localhost:1313 \ + --policy "${policy}" \ ./{{ workspace_dir }}/deployment/*.yml duration=$(( $(date +%s) - $t )) echo "Set manifest in $duration seconds." diff --git a/packages/default.nix b/packages/default.nix index 988b4e305c..4103ec31ec 100644 --- a/packages/default.nix +++ b/packages/default.nix @@ -247,4 +247,13 @@ rec { exit 1 ''; }; + + get-coordinator-policy = writeShellApplication { + name = "get-coordinator-policy"; + runtimeInputs = [ jq ]; + text = '' + set -u + jq -r <"$1" '.Policies | to_entries[] | select(.value[] | startswith("coordinator.")) | .key' + ''; + }; }