Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cmd/rofl): Add --verify to build to verify enclave identities #353

Merged
merged 1 commit into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 81 additions & 1 deletion cmd/rofl/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/base64"
"fmt"
"maps"
"os"

"github.com/spf13/cobra"
Expand All @@ -14,7 +15,9 @@ import (
"github.com/oasisprotocol/oasis-core/go/common/sgx"
"github.com/oasisprotocol/oasis-core/go/common/version"
"github.com/oasisprotocol/oasis-core/go/runtime/bundle"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/client"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/connection"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/rofl"

buildRofl "github.com/oasisprotocol/cli/build/rofl"
"github.com/oasisprotocol/cli/cmd/common"
Expand All @@ -33,6 +36,7 @@ var (
buildMode string
offline bool
doUpdate bool
doVerify bool
deploymentName string

Cmd = &cobra.Command{
Expand All @@ -44,6 +48,10 @@ var (
npa := common.GetNPASelection(cfg)
manifest, deployment := roflCommon.LoadManifestAndSetNPA(cfg, npa, deploymentName, true)

if doVerify && doUpdate {
cobra.CheckErr("only one of --verify and --update-manifest may be passed")
}

fmt.Println("Building a ROFL application...")
fmt.Printf("Deployment: %s\n", deploymentName)
fmt.Printf("Network: %s\n", deployment.Network)
Expand Down Expand Up @@ -147,14 +155,83 @@ var (

runScript(manifest, buildRofl.ScriptBundlePost)

buildEnclaves := make(map[sgx.EnclaveIdentity]struct{})
for _, eid := range eids {
buildEnclaves[*eid] = struct{}{}
}

manifestEnclaves := make(map[sgx.EnclaveIdentity]struct{})
for _, eid := range deployment.Policy.Enclaves {
manifestEnclaves[eid] = struct{}{}
}

// Perform verification when requested.
if doVerify {
showIdentityDiff := func(build, other map[sgx.EnclaveIdentity]struct{}, otherName string) {
fmt.Println("Built enclave identities:")
for enclaveID := range build {
data, _ := enclaveID.MarshalText()
fmt.Printf(" - %s\n", string(data))
}

fmt.Printf("%s enclave identities:\n", otherName)
for enclaveID := range other {
data, _ := enclaveID.MarshalText()
fmt.Printf(" - %s\n", string(data))
}
}

if !maps.Equal(buildEnclaves, manifestEnclaves) {
fmt.Println("Built enclave identities DIFFER from manifest enclave identities!")
kostko marked this conversation as resolved.
Show resolved Hide resolved
showIdentityDiff(buildEnclaves, manifestEnclaves, "Manifest")
cobra.CheckErr(fmt.Errorf("enclave identity verification failed"))
}

fmt.Println("Built enclave identities MATCH manifest enclave identities.")

// When not in offline mode, also verify on-chain enclave identities.
if !offline {
var conn connection.Connection
ctx := context.Background()
conn, err = connection.Connect(ctx, npa.Network)
cobra.CheckErr(err)

var appID rofl.AppID
_ = appID.UnmarshalText([]byte(deployment.AppID)) // Already verified.

var appCfg *rofl.AppConfig
appCfg, err = conn.Runtime(npa.ParaTime).ROFL.App(ctx, client.RoundLatest, appID)
cobra.CheckErr(err)

cfgEnclaves := make(map[sgx.EnclaveIdentity]struct{})
for _, eid := range appCfg.Policy.Enclaves {
cfgEnclaves[eid] = struct{}{}
}

if !maps.Equal(manifestEnclaves, cfgEnclaves) {
fmt.Println("Built enclave identities DIFFER from on-chain enclave identities!")
showIdentityDiff(buildEnclaves, cfgEnclaves, "On-chain")
cobra.CheckErr(fmt.Errorf("enclave identity verification failed"))
}

fmt.Println("Built enclave identities MATCH on-chain enclave identities.")
}
return
}

// Override the update manifest flag in case the policy does not exist.
if deployment.Policy == nil {
doUpdate = false
}

switch doUpdate {
case false:
// Ask the user to update the manifest manually.
// Ask the user to update the manifest manually (if the manifest has changed).
if maps.Equal(buildEnclaves, manifestEnclaves) {
fmt.Println("Built enclave identities already match manifest enclave identities.")
break
}

fmt.Println("Update the manifest with the following identities to use the new app:")
fmt.Println()
fmt.Printf("deployments:\n")
Expand All @@ -177,6 +254,8 @@ var (
if err = manifest.Save(); err != nil {
cobra.CheckErr(fmt.Errorf("failed to update manifest: %w", err))
}

fmt.Printf("Run `oasis rofl update` to update your ROFL app's on-chain configuration.\n")
}
},
}
Expand Down Expand Up @@ -258,6 +337,7 @@ func init() {
buildFlags.BoolVar(&offline, "offline", false, "do not perform any operations requiring network access")
buildFlags.StringVar(&outputFn, "output", "", "output bundle filename")
buildFlags.BoolVar(&doUpdate, "update-manifest", false, "automatically update the manifest")
buildFlags.BoolVar(&doVerify, "verify", false, "verify build against manifest and on-chain state")
buildFlags.StringVar(&deploymentName, "deployment", buildRofl.DefaultDeploymentName, "deployment name")

Cmd.Flags().AddFlagSet(buildFlags)
Expand Down
4 changes: 4 additions & 0 deletions cmd/rofl/mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,8 @@ var (
}
}
}

fmt.Printf("Run `oasis rofl build --update-manifest` to build your ROFL app.\n")
},
}

Expand Down Expand Up @@ -577,6 +579,8 @@ var (
if err = manifest.Save(); err != nil {
cobra.CheckErr(fmt.Errorf("failed to update manifest: %w", err))
}

fmt.Printf("Run `oasis rofl update` to update your ROFL app's on-chain configuration.\n")
},
}

Expand Down
Loading