diff --git a/website/docs/developer-guide/temporal-python/configuration.md b/website/docs/developer-guide/temporal-python/configuration.md index 2735ca5..f3149fb 100644 --- a/website/docs/developer-guide/temporal-python/configuration.md +++ b/website/docs/developer-guide/temporal-python/configuration.md @@ -12,25 +12,37 @@ tags: The sole OpenBox integration surface is the native Temporal `Worker(..., plugins=[OpenBoxPlugin(...)])` shape. The plugin initializer owns all OpenBox Worker, Workflow, and Activity setup. -The plugin can be configured via environment variables or constructor parameters. +The plugin is configured with constructor parameters. It does not read +environment variables: the package reads the process environment in exactly one +place, and that place is unrelated to plugin configuration. -## Environment Variables +## Credentials -| Variable | Required | Default | Description | -| ----------------------------------- | -------- | ----------- | --------------------------------------------------------- | -| `OPENBOX_URL` | Yes | - | OpenBox Core API URL (HTTPS required for non-localhost) | -| `OPENBOX_API_KEY` | Yes | - | API key for authentication (`obx_live_*` or `obx_test_*`) | -| `OPENBOX_ENABLED` | No | `true` | Enable/disable governance | -| `OPENBOX_GOVERNANCE_TIMEOUT` | No | `30.0` | Seconds to wait for governance evaluation | -| `OPENBOX_GOVERNANCE_POLICY` | No | `fail_open` | Behavior when API unreachable | -| `OPENBOX_SEND_START_EVENT` | No | `true` | Send WorkflowStarted events | -| `OPENBOX_SEND_ACTIVITY_START_EVENT` | No | `true` | Send ActivityStarted events | +`OPENBOX_URL` and `OPENBOX_API_KEY` are the conventional names for the two +values every deployment needs. Your own code reads them and passes them in, so +the key never appears in source: -## Plugin Parameters +```python +OpenBoxPlugin( + openbox_url=os.environ["OPENBOX_URL"], + openbox_api_key=os.environ["OPENBOX_API_KEY"], +) +``` + +Everything else is a parameter with a default. To drive any of them from the +environment, read the variable yourself and pass the value in: -Parameters passed to `OpenBoxPlugin()` override environment variables: +```python +OpenBoxPlugin( + openbox_url=os.environ["OPENBOX_URL"], + openbox_api_key=os.environ["OPENBOX_API_KEY"], + governance_timeout=float(os.getenv("OPENBOX_GOVERNANCE_TIMEOUT", "30.0")), + governance_policy=os.getenv("OPENBOX_GOVERNANCE_POLICY", "fail_open"), +) +``` -See **[Example: Full Configuration](#example-full-configuration)** for a complete example. +Setting those variables without reading them changes nothing, because the +plugin never looks at them. ## Configuration Options @@ -206,7 +218,7 @@ plugin = OpenBoxPlugin( For a registered command, `CONSTRAIN` selects sandbox execution and aborts the corresponding host action before its side effect. Policy routing uses `constraints: ["run_in_sandbox"]`; a behavioral `CONSTRAIN` can select a registered replacement profile. Ordinary Temporal operations that cannot enforce `CONSTRAIN` fail closed. Keep all OpenBox setup in the same plugin initializer; there is no separate Worker path for sandboxed commands. -The sandbox runtime defaults to the `native` provider. Provision it with `obs provision` (`native` is the default), then load `~/.config/openbox-sandbox/agent.env`. +The sandbox runtime defaults to the `native` provider. Provision it with `obs provision` (`native` is the default), then load `~/.config/openbox-sandbox/agent.env`. For a guest-kernel boundary, provision the optional [OpenShell Provider (VM)](/developer-guide/temporal-python/openshell-provider) explicitly. See [Governed Sandbox Commands](/developer-guide/temporal-python/concept) for registry construction, native Worker composition, result bounds, and the zero-host deployment requirement. diff --git a/website/docs/developer-guide/temporal-python/integration-walkthrough.mdx b/website/docs/developer-guide/temporal-python/integration-walkthrough.mdx index a36f45d..354a644 100644 --- a/website/docs/developer-guide/temporal-python/integration-walkthrough.mdx +++ b/website/docs/developer-guide/temporal-python/integration-walkthrough.mdx @@ -87,10 +87,6 @@ TEMPORAL_ADDRESS=localhost:7233 # OpenBox (use the API key from Part 2) OPENBOX_URL=https://core.openbox.ai OPENBOX_API_KEY=your-openbox-api-key -OPENBOX_GOVERNANCE_ENABLED=true -OPENBOX_GOVERNANCE_TIMEOUT=30.0 -OPENBOX_GOVERNANCE_MAX_RETRIES=1 -OPENBOX_GOVERNANCE_POLICY=fail_open ``` ## Part 4: Run the Demo diff --git a/website/docs/developer-guide/temporal-python/native-provider.md b/website/docs/developer-guide/temporal-python/native-provider.md index 1ea5c1c..1a94956 100644 --- a/website/docs/developer-guide/temporal-python/native-provider.md +++ b/website/docs/developer-guide/temporal-python/native-provider.md @@ -22,6 +22,8 @@ The native provider uses these platform controls: - **macOS:** Seatbelt through `/usr/bin/sandbox-exec`. - **Linux:** bubblewrap (`bwrap`). +Use the optional [OpenShell provider (VM)](./openshell-provider) when you require a guest-kernel boundary. + ## Requirements | Host | Requirements | @@ -91,7 +93,7 @@ Bubblewrap cannot filter destination addresses in a shared network namespace. Th Without another kernel network control, the allowlist cannot stop clients that bypass the proxy. -Use the deny-network template for bypass-resistant native Linux isolation. +Use the deny-network template for bypass-resistant native Linux isolation. Use the [OpenShell provider (VM)](./openshell-provider) if you require a network allowlist and a stronger Linux network boundary. ### Linux violation telemetry @@ -116,5 +118,6 @@ A clean rerun removes the runtime state that the launcher owns and recompiles th ## Related pages - [Governed Sandbox Commands](./concept): Registration of Temporal profiles and behavioral interception. +- [OpenShell Provider (VM)](./openshell-provider): The optional OpenShell provider with microVM isolation. - [Sandbox Execution](/trust-lifecycle/authorize/sandbox-execution): The lifecycle and evidence model. - [Error Handling](./error-handling): Fail-closed command outcomes. diff --git a/website/docs/developer-guide/temporal-python/openshell-provider.md b/website/docs/developer-guide/temporal-python/openshell-provider.md new file mode 100644 index 0000000..1d0c1ed --- /dev/null +++ b/website/docs/developer-guide/temporal-python/openshell-provider.md @@ -0,0 +1,262 @@ +--- +title: OpenShell Provider (VM) +sidebar_label: OpenShell Provider (VM) +sidebar_position: 2 +description: "Provision the optional OpenShell microVM provider on macOS or Linux." +llms_description: OpenShell microVM provisioning, prepared caches, zot registry, CA trust, and platforms +slug: openshell-provider +tags: + - sdk + - temporal + - governance +--- + +# OpenShell Provider (VM) + +The optional OpenShell provider (`openshell`) runs admitted commands in a libkrun microVM with a guest kernel. + +## Isolation boundary + +The OpenShell provider uses these platform controls: + +- **macOS:** Hypervisor.framework. +- **Linux:** KVM. + +Select this provider with `--provider openshell` or `OPENBOX_PROVIDER=openshell`. The launcher never selects the OpenShell provider as a fallback from the default [native provider (`native`)](./native-provider). + +After a failure of the OpenShell provider, OpenBox does not retry the command under the native provider (`native`) or on the host. + +## Selection guidance + +Use the OpenShell provider when one of these requirements applies: + +- The command requires a VM boundary instead of a host operating system sandbox. +- A Linux network allowlist must stop clients that bypass `HTTP_PROXY` and `HTTPS_PROXY`. +- The command requires a prepared Linux guest image. +- Your deployment requires VM-backed isolation. + +Use the native provider (`native`) when you require a shorter local setup and lower startup cost. The native provider does not require an image cache. It also provides native filtering for each domain on macOS. + +The OpenShell provider adds a gateway, VM driver, guest image, cache lifecycle, and platform requirements. + +## Supported platforms + +| Host | VM boundary | Release support | Prepared cache | OCI and zot assets for development | +|---|---|---|---|---| +| macOS on Apple Silicon | Hypervisor.framework | Supported | `prepared-vm-cache-darwin-arm64.tar.gz` | `openbox-sandbox-dev-darwin-arm64-oci.tar.gz` and `zot-darwin-arm64` | +| Linux x86_64 with glibc 2.28 or later | KVM (`/dev/kvm`) | Supported | `prepared-vm-cache-linux-x86_64.tar.gz` | `openbox-sandbox-dev-linux-x86_64-oci.tar.gz` and `zot-linux-x86_64` | +| Linux arm64 | KVM | Incomplete. OpenShell can fetch aarch64 dependencies, but OpenBox does not publish the matching cache and pinned zot assets. | Not published | Not published | +| Intel macOS | Not available | OpenBox does not publish a VM bundle or cache. | Not published | Not published | +| Windows | Not available | Not supported directly. WSL2 requires readable nested `/dev/kvm`. | Not published | Not published | + +A launcher binary does not prove that a complete VM asset set exists. OpenBox publishes complete provider assets for Apple Silicon macOS and x86_64 glibc Linux. + +## Requirements + +### macOS + +The macOS host requires: + +- Apple Silicon. +- A `1` response from `sysctl -n kern.hv_support`. +- Xcode Command Line Tools, including `codesign`. +- Developer mode enabled with `sudo DevToolsSecurity -enable`. +- OpenSSL and `curl`. +- `e2fsprogs`, including `mkfs.ext4` or `mke2fs`, and `debugfs`. + +The launcher applies an ad hoc signature to the VM driver. The signature includes the `com.apple.security.hypervisor` entitlement. + +Provisioning installs `e2fsprogs` when Homebrew is available. Otherwise, install it before you retry: + +```bash +brew install e2fsprogs +``` + +### Linux + +The Linux host requires: + +- x86_64 with glibc 2.28 or later. +- Read access to `/dev/kvm`. +- OpenSSL, `curl`, and `e2fsprogs`. + +The released VM binaries do not support musl or Alpine Linux. + +If `/dev/kvm` exists but is not readable, add the operator to the `kvm` group according to your host policy. Then log out and log in again. + +Provisioning stops before the VM starts when `/dev/kvm` is inaccessible. + +## Install and provision + +Download the release assets as described in [Provisioning](./provisioning), plus two that only this provider needs: the OpenShell bundle and the prepared VM cache. + +OpenShell is a pinned external runtime. The hosted bundle locks OpenShell `0.0.88`. Alternatively, it accepts the corresponding approved source marker. The launcher verifies the OpenShell release assets. + +Provision this provider explicitly: + +```bash +obs provision --provider openshell +``` + +Provisioning never prompts, and it does not bypass these checks: + +- KVM access +- VM driver signing +- `e2fsprogs` availability +- Asset verification +- Required CA trust + +Provisioning performs these actions: + +1. Starts the OpenShell gateway and VM driver. +2. Starts the loopback service with mTLS. +3. Verifies the selected policy and image identity. +4. Prepares or warms the image cache. +5. Runs a create, ready, and delete warm lifecycle. +6. Writes the same provider-neutral `agent.env` that the native provider writes. + +An application needs no code change when a registered command switches providers. + +## Prepared VM caches + +A cold image pull and ext4 conversion can take minutes. The release provides these caches for the supported platforms: + +- `prepared-vm-cache-darwin-arm64.tar.gz` +- `prepared-vm-cache-linux-x86_64.tar.gz` + +`obs provision` uses the matching cache by default. It verifies the cache with the checksum data that the release locks. It extracts the cache into VM driver state for each user. + +Then it runs a warm sandbox lifecycle. This lifecycle verifies that the driver accepts the cache. + +The cache uses these identity controls: + +- The state directory belongs to the current user and gateway. +- The `cache-image` file contains the expected sandbox image identity. +- The VM driver keys prepared content by immutable image identity, not by a mutable tag. + +Do not use a cache from another platform, architecture, user, gateway state layout, or image identity. + +A normal `--clean-rerun` preserves prepared images. Use `--purge-cache` for a full reset: + +```bash +obs provision --provider openshell --clean-rerun --purge-cache +``` + +Skip cache use only during diagnosis: + +```bash +obs provision --provider openshell --no-vm-cache +obs provision --provider openshell --skip-warm-cache +``` + +If the prepared cache is missing, invalid, or rejected, provisioning can build it through the documented runtime fallback. Provisioning does not switch sandbox providers. + +## OCI registry mode for development + +The development release can serve the sandbox image without Docker or Podman. `obs update --dev --all` downloads these assets: + +- The platform-specific OpenBox OCI layout. +- The platform-specific service and policy assets. +- The prepared VM cache, when published. +- The pinned official zot `v2.1.20` binary for the platform. + +The launcher downloads zot from `project-zot/zot`. It verifies the binary against its platform pin. + +Download the assets, then provision the development release: + +```bash +obs update --dev --all +obs provision --provider openshell --dev +``` + +When the OCI layout and zot are present, provisioning performs these actions: + +1. Extracts the OCI layout into runtime state that the launcher owns. +2. Generates a local TLS certificate for `127.0.0.1` and `localhost`. +3. Starts zot with HTTPS on loopback. The default port is `15000`. +4. Reads the registry manifest digest. +5. Configures a digest-pinned image reference in this form: `127.0.0.1:/openbox-sandboxes-dev@sha256:...`. + +Docker and Podman are optional. A container engine provides a fallback when the cache and registry assets cannot provide the development image. + +The container engine loads the development image locally. + +## Registry CA trust + +The OpenShell VM driver verifies registry HTTPS certificates. The host must trust the local zot certificate. + +The registry CA is separate from the mTLS identities for the SDK, the service, and the OpenShell gateway. + +### macOS trust + +Provisioning first tries to add the certificate to the login keychain. If that keychain is locked or rejects the certificate, the launcher requests `sudo` access. + +The launcher then tries the system keychain. + +If both operations fail, provisioning stops. It prints this one-time command: + +```bash +sudo security add-trusted-cert -d -r trustRoot \ + -k /Library/Keychains/System.keychain \ + "$HOME/.local/state/openbox-sandbox/zot/tls/cert.pem" +``` + +Confirm that the path contains the certificate that the launcher owns. Then provision the provider again. + +Alternatively, unlock the login keychain instead of changing system trust. + +### Linux trust + +Provisioning writes a CA copy to: + +```text +~/.local/state/openbox-sandbox/certs/openbox-registry-ca.crt +``` + +When passwordless authorization is available, provisioning copies the CA under `/usr/local/share/ca-certificates/`. It then runs `update-ca-certificates`. + +If you cannot update the system trust, install the CA that the launcher owns according to your distribution policy. Then provision the provider again. + +The VM driver can reject the registry until the host trusts the CA. + +## Security properties + +The OpenShell provider retains the provider-neutral lifecycle and admission controls: + +- It executes an exact registered argument vector without a shell. +- It verifies immutable policy and image identities. +- It bounds command output and execution time. +- It uses mTLS between the service for the SDK and the runtime boundary. +- It performs create, ready, execute, delete, and terminal-absence checks that the request owns. +- It never uses host execution after a `CONSTRAIN` dispatch. + +The VM supplies a guest-kernel and hardware isolation boundary. Enforcement of the policy inside the guest depends on the pinned OpenShell image, supervisor, and policy. + +A prepared cache reduces startup time. It does not replace identity verification. + +## Limitations + +- The OpenShell provider has higher startup and resource costs than the native provider (`native`). +- Cache warming requires `e2fsprogs`, even without a container engine. +- Registry mode requires host CA trust. Provisioning does not bypass this requirement. +- Linux requires readable KVM and compatible glibc. +- A cache miss can slow the first request or require the container engine fallback. +- OpenBox does not publish a complete VM path for Windows or Intel macOS. + +## Operations + +Use these commands to inspect, verify, provision again, or remove the provider: + +```bash +obs status +obs provision --provider openshell --clean-rerun +obs uninstall +``` + +`obs --verify-runtime` checks local artifact and version compatibility only. It does not connect to the gateway or create a VM. + +## Related pages + +- [Governed Sandbox Commands](./concept): Shared profiles, interception, results, and evidence. +- [Native Provider](./native-provider): The default native provider and its platform limits. +- [Sandbox Execution](/trust-lifecycle/authorize/sandbox-execution): The governance model that is independent of the provider. diff --git a/website/docs/developer-guide/temporal-python/provisioning.md b/website/docs/developer-guide/temporal-python/provisioning.md index a4566b2..1dfa2ed 100644 --- a/website/docs/developer-guide/temporal-python/provisioning.md +++ b/website/docs/developer-guide/temporal-python/provisioning.md @@ -156,3 +156,4 @@ Load the generated provider-neutral values into the Worker process, as shown in ## Provider guides - [Native Provider](./native-provider): Requirements, network behavior, and limitations for Seatbelt and bubblewrap. +- [OpenShell Provider (VM)](./openshell-provider): Requirements for microVMs, prepared caches, registry mode, and CA trust. diff --git a/website/docs/developer-guide/temporal-python/sdk-reference.md b/website/docs/developer-guide/temporal-python/sdk-reference.md index 20f1961..9034a29 100644 --- a/website/docs/developer-guide/temporal-python/sdk-reference.md +++ b/website/docs/developer-guide/temporal-python/sdk-reference.md @@ -54,7 +54,7 @@ See: ## Plugin Usage -```python +```text from openbox import OpenBoxPlugin from openbox.sandbox import SandboxConfig diff --git a/website/docs/trust-lifecycle/authorize/sandbox-execution.md b/website/docs/trust-lifecycle/authorize/sandbox-execution.md index 2a8915d..6332f11 100644 --- a/website/docs/trust-lifecycle/authorize/sandbox-execution.md +++ b/website/docs/trust-lifecycle/authorize/sandbox-execution.md @@ -81,7 +81,7 @@ The sandbox service and its mTLS credentials run in infrastructure that you cont The local service owns scope creation, execution, cleanup, and restart reconciliation for each request. -Provider selection is explicit. A provider startup or execution failure does not cause fallback. +The optional [OpenShell Provider (VM)](/developer-guide/temporal-python/openshell-provider) uses Hypervisor.framework or KVM to provide a guest-kernel boundary. Provider selection is explicit. A provider startup or execution failure does not cause fallback. ## Configuration @@ -119,3 +119,4 @@ Treat a command as indeterminate when cleanup or terminal absence is uncertain. - [Authorize Phase](/trust-lifecycle/authorize): Location of `CONSTRAIN` in the authorization pipeline. - [Governed Sandbox Commands](/developer-guide/temporal-python/concept): Temporal interception, profiles, and results. - [Native Provider](/developer-guide/temporal-python/native-provider): Native installation, verification, and limitations. +- [OpenShell Provider (VM)](/developer-guide/temporal-python/openshell-provider): Optional microVM provider. diff --git a/website/sidebars.js b/website/sidebars.js index 078abc4..58caadf 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -475,6 +475,11 @@ const sidebars = { id: 'developer-guide/temporal-python/native-provider', className: 'sidebar-item--diff', }, + { + type: 'doc', + id: 'developer-guide/temporal-python/openshell-provider', + className: 'sidebar-item--diff', + }, ], }, {