diff --git a/build/rofl/artifacts.go b/build/rofl/artifacts.go new file mode 100644 index 0000000..64cb26a --- /dev/null +++ b/build/rofl/artifacts.go @@ -0,0 +1,19 @@ +package rofl + +// LatestBasicArtifacts are the latest TDX ROFL basic app artifacts. +var LatestBasicArtifacts = ArtifactsConfig{ + Firmware: "https://github.com/oasisprotocol/oasis-boot/releases/download/v0.3.3/ovmf.tdx.fd#db47100a7d6a0c1f6983be224137c3f8d7cb09b63bb1c7a5ee7829d8e994a42f", + Kernel: "https://github.com/oasisprotocol/oasis-boot/releases/download/v0.3.3/stage1.bin#539f25c66a27b2ca3c6b4d3333b88c64e531fcc96776c37a12c9ce06dd7fbac9", + Stage2: "https://github.com/oasisprotocol/oasis-boot/releases/download/v0.3.3/stage2-basic.tar.bz2#72c84d2566959799fdd98fae08c143a8572a5a09ee426be376f9a8bbd1675f2b", +} + +// LatestContainerArtifacts are the latest TDX container app artifacts. +var LatestContainerArtifacts = ArtifactsConfig{ + Firmware: "https://github.com/oasisprotocol/oasis-boot/releases/download/v0.3.3/ovmf.tdx.fd#db47100a7d6a0c1f6983be224137c3f8d7cb09b63bb1c7a5ee7829d8e994a42f", + Kernel: "https://github.com/oasisprotocol/oasis-boot/releases/download/v0.3.3/stage1.bin#539f25c66a27b2ca3c6b4d3333b88c64e531fcc96776c37a12c9ce06dd7fbac9", + Stage2: "https://github.com/oasisprotocol/oasis-boot/releases/download/v0.3.3/stage2-podman.tar.bz2#827531546f3db6b0945ece7ddab4e10d648eaa3ba1c146b7889d7cb9cbf0b507", + Container: ContainerArtifactsConfig{ + Runtime: "https://github.com/oasisprotocol/oasis-sdk/releases/download/rofl-containers%2Fv0.3.4/rofl-containers#d6a055b2e88e1f321e3ab1f73046444e24df9d8925d13cc6b8230de9a81e5c41", + Compose: "compose.yaml", + }, +} diff --git a/cmd/rofl/build/container.go b/cmd/rofl/build/container.go index 2747e34..5eda634 100644 --- a/cmd/rofl/build/container.go +++ b/cmd/rofl/build/container.go @@ -12,17 +12,6 @@ import ( "github.com/oasisprotocol/cli/cmd/common" ) -const ( - artifactContainerRuntime = "rofl-container runtime" - artifactContainerCompose = "compose.yaml" - - defaultContainerStage2TemplateURI = "https://github.com/oasisprotocol/oasis-boot/releases/download/v0.3.3/stage2-podman.tar.bz2#827531546f3db6b0945ece7ddab4e10d648eaa3ba1c146b7889d7cb9cbf0b507" - - defaultContainerRuntimeURI = "https://github.com/oasisprotocol/oasis-sdk/releases/download/rofl-containers%2Fv0.3.3/rofl-containers#b7f025e3bb844a4ce044fa3a2503f6854e5e2d2d5ec22be919c582e57cf5d6ab" - - defaultContainerComposeURI = "compose.yaml" -) - // tdxBuildContainer builds a TDX-based container ROFL app. func tdxBuildContainer( tmpDir string, @@ -33,20 +22,7 @@ func tdxBuildContainer( ) error { fmt.Println("Building a container-based TDX ROFL application...") - tdxStage2TemplateURI = defaultContainerStage2TemplateURI - - wantedArtifacts := tdxGetDefaultArtifacts() - wantedArtifacts = append(wantedArtifacts, - &artifact{ - kind: artifactContainerRuntime, - uri: defaultContainerRuntimeURI, - }, - &artifact{ - kind: artifactContainerCompose, - uri: defaultContainerComposeURI, - }, - ) - tdxOverrideArtifacts(manifest, wantedArtifacts) + wantedArtifacts := tdxWantedArtifacts(manifest, buildRofl.LatestContainerArtifacts) artifacts := tdxFetchArtifacts(wantedArtifacts) // Validate compose file. diff --git a/cmd/rofl/build/tdx.go b/cmd/rofl/build/tdx.go index 5a4db56..f06b386 100644 --- a/cmd/rofl/build/tdx.go +++ b/cmd/rofl/build/tdx.go @@ -16,21 +16,13 @@ import ( "github.com/oasisprotocol/cli/cmd/common" ) -// TODO: Replace these URIs with a better mechanism for managing releases. +// Artifact kinds. const ( - artifactFirmware = "firmware" - artifactKernel = "kernel" - artifactStage2 = "stage 2 template" - - defaultFirmwareURI = "https://github.com/oasisprotocol/oasis-boot/releases/download/v0.3.3/ovmf.tdx.fd#db47100a7d6a0c1f6983be224137c3f8d7cb09b63bb1c7a5ee7829d8e994a42f" - defaultKernelURI = "https://github.com/oasisprotocol/oasis-boot/releases/download/v0.3.3/stage1.bin#539f25c66a27b2ca3c6b4d3333b88c64e531fcc96776c37a12c9ce06dd7fbac9" - defaultStage2TemplateURI = "https://github.com/oasisprotocol/oasis-boot/releases/download/v0.3.3/stage2-basic.tar.bz2#72c84d2566959799fdd98fae08c143a8572a5a09ee426be376f9a8bbd1675f2b" -) - -var ( - tdxFirmwareURI = defaultFirmwareURI - tdxKernelURI = defaultKernelURI - tdxStage2TemplateURI = defaultStage2TemplateURI + artifactFirmware = "firmware" + artifactKernel = "kernel" + artifactStage2 = "stage 2 template" + artifactContainerRuntime = "rofl-container runtime" + artifactContainerCompose = "compose.yaml" ) // tdxBuildRaw builds a TDX-based "raw" ROFL app. @@ -41,8 +33,7 @@ func tdxBuildRaw( deployment *buildRofl.Deployment, bnd *bundle.Bundle, ) error { - wantedArtifacts := tdxGetDefaultArtifacts() - tdxOverrideArtifacts(manifest, wantedArtifacts) + wantedArtifacts := tdxWantedArtifacts(manifest, buildRofl.LatestBasicArtifacts) artifacts := tdxFetchArtifacts(wantedArtifacts) fmt.Println("Building a TDX-based Rust ROFL application...") @@ -87,13 +78,32 @@ type artifact struct { uri string } -// tdxGetDefaultArtifacts returns the list of default TDX artifacts. -func tdxGetDefaultArtifacts() []*artifact { - return []*artifact{ - {artifactFirmware, tdxFirmwareURI}, - {artifactKernel, tdxKernelURI}, - {artifactStage2, tdxStage2TemplateURI}, +// tdxWantedArtifacts returns the list of wanted artifacts based on the passed manifest and a set of +// defaults. In case an artifact is not defined in the manifest, it is taken from defaults. +func tdxWantedArtifacts(manifest *buildRofl.Manifest, defaults buildRofl.ArtifactsConfig) []*artifact { + var artifacts []*artifact + for _, a := range []struct { + kind string + getter func(*buildRofl.ArtifactsConfig) string + }{ + {artifactFirmware, func(ac *buildRofl.ArtifactsConfig) string { return ac.Firmware }}, + {artifactKernel, func(ac *buildRofl.ArtifactsConfig) string { return ac.Kernel }}, + {artifactStage2, func(ac *buildRofl.ArtifactsConfig) string { return ac.Stage2 }}, + {artifactContainerRuntime, func(ac *buildRofl.ArtifactsConfig) string { return ac.Container.Runtime }}, + {artifactContainerCompose, func(ac *buildRofl.ArtifactsConfig) string { return ac.Container.Compose }}, + } { + var uri string + if manifest.Artifacts != nil { + uri = a.getter(manifest.Artifacts) + } + if uri == "" { + uri = a.getter(&defaults) + } + if uri != "" { + artifacts = append(artifacts, &artifact{a.kind, uri}) + } } + return artifacts } // tdxFetchArtifacts obtains all of the required artifacts for a TDX image. @@ -105,36 +115,6 @@ func tdxFetchArtifacts(artifacts []*artifact) map[string]string { return result } -// tdxOverrideArtifacts overrides artifacts based on the manifest. -func tdxOverrideArtifacts(manifest *buildRofl.Manifest, artifacts []*artifact) { - if manifest == nil || manifest.Artifacts == nil { - return - } - overrides := manifest.Artifacts - - for _, artifact := range artifacts { - var overrideURI string - switch artifact.kind { - case artifactFirmware: - overrideURI = overrides.Firmware - case artifactKernel: - overrideURI = overrides.Kernel - case artifactStage2: - overrideURI = overrides.Stage2 - case artifactContainerRuntime: - overrideURI = overrides.Container.Runtime - case artifactContainerCompose: - overrideURI = overrides.Container.Compose - default: - } - - if overrideURI == "" { - continue - } - artifact.uri = overrideURI - } -} - type tdxStage2 struct { fn string rootHash string diff --git a/cmd/rofl/mgmt.go b/cmd/rofl/mgmt.go index 66dbf19..18c37cc 100644 --- a/cmd/rofl/mgmt.go +++ b/cmd/rofl/mgmt.go @@ -87,6 +87,9 @@ var ( height, err := common.GetActualHeight(ctx, conn.Consensus()) cobra.CheckErr(err) + blk, err := conn.Consensus().GetBlock(ctx, height) + cobra.CheckErr(err) + // Determine debug mode. var debugMode bool params, err := conn.Consensus().Registry().ConsensusParameters(ctx, height) @@ -116,6 +119,7 @@ var ( }, TrustRoot: &buildRofl.TrustRootConfig{ Height: uint64(height), + Hash: blk.Hash.Hex(), }, } manifest := buildRofl.Manifest{ @@ -149,13 +153,25 @@ var ( fmt.Printf(" Debug: %v\n", deployment.Debug) fmt.Printf(" Admin: %s\n", deployment.Admin) - // For container app kind also create an en empty compose.yaml file if it doesn't exist. - if appKind == buildRofl.AppKindContainer { - var f *os.File - f, err = os.OpenFile("compose.yaml", os.O_RDONLY|os.O_CREATE, 0o644) - if err == nil { - f.Close() + switch manifest.TEE { + case buildRofl.TEETypeTDX: + switch appKind { + case buildRofl.AppKindRaw: + artifacts := buildRofl.LatestBasicArtifacts // Copy. + manifest.Artifacts = &artifacts + case buildRofl.AppKindContainer: + // For container app kind also create an en empty compose.yaml file if it doesn't exist. + var f *os.File + f, err = os.OpenFile("compose.yaml", os.O_RDONLY|os.O_CREATE, 0o644) + if err == nil { + f.Close() + } + + artifacts := buildRofl.LatestContainerArtifacts // Copy. + manifest.Artifacts = &artifacts + default: } + default: } // Serialize manifest and write it to file. @@ -463,6 +479,37 @@ var ( }, } + upgradeCmd = &cobra.Command{ + Use: "upgrade", + Short: "Upgrade all artifacts to their latest default versions", + Args: cobra.NoArgs, + Run: func(_ *cobra.Command, _ []string) { + cfg := cliConfig.Global() + npa := common.GetNPASelection(cfg) + + manifest, _ := roflCommon.LoadManifestAndSetNPA(cfg, npa, deploymentName, false) + + switch manifest.TEE { + case buildRofl.TEETypeTDX: + switch manifest.Kind { + case buildRofl.AppKindRaw: + artifacts := buildRofl.LatestBasicArtifacts // Copy. + manifest.Artifacts = &artifacts + case buildRofl.AppKindContainer: + artifacts := buildRofl.LatestContainerArtifacts // Copy. + manifest.Artifacts = &artifacts + default: + } + default: + } + + // Update manifest. + if err := manifest.Save(); err != nil { + cobra.CheckErr(fmt.Errorf("failed to update manifest: %w", err)) + } + }, + } + secretCmd = &cobra.Command{ Use: "secret", Short: "Encrypted secret management commands", diff --git a/cmd/rofl/rofl.go b/cmd/rofl/rofl.go index 36fb9a6..19898aa 100644 --- a/cmd/rofl/rofl.go +++ b/cmd/rofl/rofl.go @@ -22,4 +22,5 @@ func init() { Cmd.AddCommand(build.Cmd) Cmd.AddCommand(identityCmd) Cmd.AddCommand(secretCmd) + Cmd.AddCommand(upgradeCmd) }