mirror of
https://github.com/hanzoai/runtime.git
synced 2026-10-30 18:23:13 +00:00
Every sandbox was created privileged under the daemon's default runtime, and the setting that would have changed it defaulted to an empty string that silently meant runc. For a service whose whole premise is running code somebody else wrote, that is not a boundary. An org sets its isolation and the create request carries it, so a sandbox records what it was made with: changing the policy moves new sandboxes and leaves running ones alone. gvisor is the default. firecracker is delivered through kata's shim, which is why it is one name rather than two. runc is refused unless the runner names that org, and an empty list names nobody. Absent means the default, unknown is a refusal, and a runtime the daemon does not have is a refusal. Nothing substitutes quietly. The runner took an organization in a field called UserId with a note beside it saying so. Deciding who may have runc through a field named after something else is not reviewable. Privileged is replaced by dropping everything and granting the eight the daemon uses. Nothing the sandbox does broke; what stopped working is mount, mknod, raw sockets, chroot, writing to proc, and seeing the host's disks. AUDIT_WRITE is among them because without it sudo works and complains every time. The creation histogram's lowest bucket was a tenth of a second, so the metric could not observe the claim the product makes about its own speed. It can now, and it carries the isolation, so comparing them is a query. Co-authored-by: Hanzo Dev <[email protected]>
52 lines
2.3 KiB
Go
52 lines
2.3 KiB
Go
// Copyright 2025 Hanzo Industries Inc.
|
|
// SPDX-License-Identifier: AGPL-3.0
|
|
|
|
package dto
|
|
|
|
// Isolation names the boundary a sandbox runs behind. It is chosen per
|
|
// organization and travels with the create request, so the runner never has to
|
|
// ask anyone which boundary a sandbox gets.
|
|
//
|
|
// The empty value is not a selection. Anything that resolves it treats absent
|
|
// as IsolationDefault, so a caller that says nothing is isolated.
|
|
type Isolation string
|
|
|
|
const (
|
|
// IsolationGvisor runs the sandbox under gVisor, which serves the guest's
|
|
// syscalls from a userspace kernel rather than passing them to the host.
|
|
IsolationGvisor Isolation = "gvisor"
|
|
// IsolationFirecracker runs the sandbox in a microVM behind a hardware
|
|
// boundary. It requires KVM on the node.
|
|
IsolationFirecracker Isolation = "firecracker"
|
|
// IsolationRunc runs the sandbox in namespaces and cgroups only, with no
|
|
// boundary against code that attacks the kernel. Only organizations named
|
|
// in the runner's RUNC_ORGS may select it.
|
|
IsolationRunc Isolation = "runc"
|
|
)
|
|
|
|
// IsolationDefault is what an organization gets when it has configured nothing.
|
|
const IsolationDefault = IsolationGvisor
|
|
|
|
type CreateSandboxDTO struct {
|
|
Id string `json:"id" validate:"required"`
|
|
FromVolumeId string `json:"fromVolumeId,omitempty"`
|
|
OrgId string `json:"orgId" validate:"required"`
|
|
Isolation Isolation `json:"isolation,omitempty"`
|
|
Snapshot string `json:"snapshot" validate:"required"`
|
|
OsUser string `json:"osUser" validate:"required"`
|
|
CpuQuota int64 `json:"cpuQuota" validate:"min=1"`
|
|
GpuQuota int64 `json:"gpuQuota" validate:"min=0"`
|
|
MemoryQuota int64 `json:"memoryQuota" validate:"min=1"`
|
|
StorageQuota int64 `json:"storageQuota" validate:"min=1"`
|
|
Env map[string]string `json:"env,omitempty"`
|
|
Registry *RegistryDTO `json:"registry,omitempty"`
|
|
Entrypoint []string `json:"entrypoint,omitempty"`
|
|
Volumes []VolumeDTO `json:"volumes,omitempty"`
|
|
} // @name CreateSandboxDTO
|
|
|
|
type ResizeSandboxDTO struct {
|
|
Cpu int64 `json:"cpu" validate:"min=1"`
|
|
Gpu int64 `json:"gpu" validate:"min=0"`
|
|
Memory int64 `json:"memory" validate:"min=1"`
|
|
} // @name ResizeSandboxDTO
|