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 } tmpDir, err := os.MkdirTemp("", "oasis-build") if err != nil { return fmt.Errorf("failed to create temporary build directory: %w", err) } defer os.RemoveAll(tmpDir) setUmask(0o002) var buildEnv env.ExecEnv switch { case manifest.Artifacts == nil || manifest.Artifacts.Builder == "" || noContainer: buildEnv = env.NewNativeEnv() default: var baseDir string baseDir, err = env.GetBasedir() if err != nil { return fmt.Errorf("failed to determine base directory: %w", err) } containerEnv := env.NewContainerEnv( manifest.Artifacts.Builder, baseDir, "/src", ) containerEnv.AddDirectory(tmpDir) buildEnv = containerEnv if buildEnv.IsAvailable() { fmt.Printf("Initializing build environment...\n") cmd := exec.Command("true") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err = buildEnv.WrapCommand(cmd); err != nil { return fmt.Errorf("unable to wrap command: %w", err) } if err = cmd.Run(); err != nil { return fmt.Errorf("failed to initialize build environment: %w", err) } } } 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) 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) 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) 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.