Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var ( Cmd = &cobra.Command{ Use: "build", Short: "Build a ROFL application", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { cmd.SilenceUsage = true manifest, deployment, npa := roflCommon.LoadManifestAndSetNPA(&roflCommon.ManifestOptions{ NeedAppID: true, NeedAdmin: false, }) if onlyValidate { fmt.Println("Validating app...") _, err := ValidateApp(manifest, ValidationOpts{}) if err == nil { fmt.Println("App validation passed.") return nil } return err } fmt.Println("Building a ROFL application...") fmt.Printf("Deployment: %s\n", roflCommon.DeploymentName) fmt.Printf("Network: %s\n", deployment.Network) fmt.Printf("ParaTime: %s\n", deployment.ParaTime) fmt.Printf("Debug: %v\n", deployment.Debug) fmt.Printf("App ID: %s\n", deployment.AppID) fmt.Printf("Name: %s\n", manifest.Name) fmt.Printf("Version: %s\n", manifest.Version) fmt.Printf("TEE: %s\n", manifest.TEE) fmt.Printf("Kind: %s\n", manifest.Kind) fmt.Println() switch deployment.Debug { case true: buildMode = buildModeUnsafe case false: buildMode = buildModeProduction } setUmask(0o002) builderImage := "" if manifest.Artifacts != nil { builderImage = strings.TrimSpace(manifest.Artifacts.Builder) if manifest.Artifacts.Builder != "" && builderImage == "" { return fmt.Errorf("builder image is empty after trimming whitespace") } } nativeBuildSupported := runtime.GOOS == "linux" && runtime.GOARCH == "amd64" var ( buildEnv env.ExecEnv usingContainer bool err error tmpDir string ) switch { case noContainer: if !nativeBuildSupported { return fmt.Errorf("native ROFL builds are only supported on linux/amd64; remove --no-container to use containerized builds on %s/%s", runtime.GOOS, runtime.GOARCH) } buildEnv = env.NewNativeEnv() case builderImage == "": if nativeBuildSupported { buildEnv = env.NewNativeEnv() } else { return fmt.Errorf("no builder image specified in manifest; run `oasis rofl upgrade` to add the default builder or set artifacts.builder") } default: if !env.IsContainerRuntimeAvailable() { return fmt.Errorf("builder specified in manifest but no container runtime (docker or podman) is available") } fmt.Printf("Using container build environment (image: %s)\n", builderImage) buildEnv, err = setupContainerEnv(builderImage) if err != nil { return err } usingContainer = true } tmpBase := "" if usingContainer { var baseDir string baseDir, err = env.GetBasedir() if err != nil { return fmt.Errorf("failed to determine base directory: %w", err) } tmpBase = filepath.Join(baseDir, ".oasis-tmp") _ = os.RemoveAll(tmpBase) if err = os.MkdirAll(tmpBase, 0o755); err != nil { return fmt.Errorf("failed to create temporary build directory: %w", err) } } tmpDir, err = os.MkdirTemp(tmpBase, "oasis-build") if err != nil { return fmt.Errorf("failed to create temporary build directory: %w", err) } if usingContainer { defer os.RemoveAll(tmpBase) } else { defer os.RemoveAll(tmpDir) } if !buildEnv.IsAvailable() { return fmt.Errorf("build environment '%s' is not available", buildEnv) } bnd := &bundle.Bundle{ Manifest: &bundle.Manifest{ Name: deployment.AppID, ID: npa.ParaTime.Namespace(), }, } os.Setenv("ROFL_MANIFEST", manifest.SourceFileName()) os.Setenv("ROFL_DEPLOYMENT_NAME", roflCommon.DeploymentName) os.Setenv("ROFL_DEPLOYMENT_NETWORK", deployment.Network) os.Setenv("ROFL_DEPLOYMENT_PARATIME", deployment.ParaTime) os.Setenv("ROFL_TMPDIR", tmpDir) runScript(manifest, buildRofl.ScriptBuildPre, buildEnv, usingContainer) switch manifest.TEE { case buildRofl.TEETypeSGX: if manifest.Kind != buildRofl.AppKindRaw { return fmt.Errorf("unsupported app kind for SGX TEE: %s", manifest.Kind) } sgxBuild(buildEnv, npa, manifest, deployment, bnd, doVerify) case buildRofl.TEETypeTDX: switch manifest.Kind { case buildRofl.AppKindRaw: err = tdxBuildRaw(buildEnv, tmpDir, npa, manifest, deployment, bnd, doVerify) case buildRofl.AppKindContainer: err = tdxBuildContainer(buildEnv, tmpDir, npa, manifest, deployment, bnd) } default: return fmt.Errorf("unsupported TEE kind: %s", manifest.TEE) } if err != nil { return err } runScript(manifest, buildRofl.ScriptBuildPost, buildEnv, usingContainer) outFn := roflCommon.GetOrcFilename(manifest, roflCommon.DeploymentName) if outputFn != "" { outFn = outputFn } if err = bnd.Write(outFn); err != nil { return fmt.Errorf("failed to write output bundle: %s", err) } fmt.Printf("ROFL app built and bundle written to '%s'.\n", outFn) fmt.Println("Computing enclave identity...") ids, err := roflCommon.ComputeEnclaveIdentity(bnd, "") if err != nil { return err } os.Setenv("ROFL_BUNDLE", outFn) for idx, id := range ids { data, _ := id.Enclave.MarshalText() os.Setenv(fmt.Sprintf("ROFL_ENCLAVE_ID_%d", idx), string(data)) } runScript(manifest, buildRofl.ScriptBundlePost, buildEnv, usingContainer) buildEnclaves := make(map[sgx.EnclaveIdentity]struct{}) for _, id := range ids { buildEnclaves[id.Enclave] = struct{}{} } allManifestEnclaves := make(map[sgx.EnclaveIdentity]struct{}) latestManifestEnclaves := make(map[sgx.EnclaveIdentity]struct{}) for _, eid := range deployment.Policy.Enclaves { if eid.IsLatest() { latestManifestEnclaves[eid.ID] = struct{}{} } allManifestEnclaves[eid.ID] = struct{}{} } if doVerify { showIdentityDiff := func(this, other map[sgx.EnclaveIdentity]struct{}, thisName, otherName string) { fmt.Printf("%s enclave identities:\n", thisName) for enclaveID := range this { 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, latestManifestEnclaves) { fmt.Println("Built enclave identities DIFFER from latest manifest enclave identities!") showIdentityDiff(buildEnclaves, latestManifestEnclaves, "Built", "Manifest") return fmt.Errorf("enclave identity verification failed") } fmt.Println("Built enclave identities MATCH latest manifest enclave identities.") if len(latestManifestEnclaves) != len(allManifestEnclaves) { fmt.Println("NOTE: Non-latest enclave identities present in manifest!") } if !offline { ctx := context.Background() var cfgEnclaves map[sgx.EnclaveIdentity]struct{} cfgEnclaves, err = roflCommon.GetRegisteredEnclaves(ctx, deployment.AppID, npa) if err != nil { return err } if !maps.Equal(allManifestEnclaves, cfgEnclaves) { fmt.Println("Manifest enclave identities DIFFER from on-chain enclave identities!") showIdentityDiff(allManifestEnclaves, cfgEnclaves, "Manifest", "On-chain") return fmt.Errorf("enclave identity verification failed") } fmt.Println("Manifest enclave identities MATCH on-chain enclave identities.") } return nil } if deployment.Policy == nil { roflCommon.NoUpdate = true } switch roflCommon.NoUpdate { case true: if maps.Equal(buildEnclaves, latestManifestEnclaves) { 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") fmt.Printf(" %s:\n", roflCommon.DeploymentName) fmt.Printf(" policy:\n") fmt.Printf(" enclaves:\n") for _, id := range ids { data, _ := id.Enclave.MarshalText() fmt.Printf(" - \"%s\"\n", string(data)) } case false: deployment.Policy.Enclaves = slices.DeleteFunc(deployment.Policy.Enclaves, func(ei *buildRofl.EnclaveIdentity) bool { return ei.IsLatest() }) for _, id := range ids { deployment.Policy.Enclaves = append(deployment.Policy.Enclaves, &buildRofl.EnclaveIdentity{ ID: id.Enclave, }) } if err = manifest.Save(); err != nil { return fmt.Errorf("failed to update manifest: %w", err) } fmt.Printf("Run `oasis rofl update` to update your ROFL app's on-chain configuration.\n") } return nil }, } )
Functions ¶
This section is empty.
Types ¶
type AppExtraConfig ¶ added in v0.16.0
type AppExtraConfig struct {
// Ports are the port mappings exposed by the app.
Ports []*PortMapping
}
AppExtraConfig represents extra configuration for the ROFL app.
func ValidateApp ¶ added in v0.16.0
func ValidateApp(manifest *buildRofl.Manifest, opts ValidationOpts) (*AppExtraConfig, error)
ValidateApp validates the ROFL app manifest.
type PortMapping ¶ added in v0.16.0
type PortMapping struct {
// ServiceName is the name of the service.
ServiceName string
// Port is the port number.
Port string
// ProxyMode is the proxy mode for the port.
ProxyMode string
// GenericDomain is the generic domain name.
GenericDomain string
// CustomDomain is the custom domain name (if any).
CustomDomain string
}
PortMapping represents a port mapping.
type ValidationOpts ¶ added in v0.16.0
type ValidationOpts struct {
// Offline indicates whether the validation should be performed without network access.
Offline bool
}
ValidationOpts represents options for the validation process.
Click to show internal directories.
Click to hide internal directories.