mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
feat: Add Sandbox Inspection and Debugging Commands (#261)
* feat: add sandbox DX commands * fix: Linter errors * fix: Sandbox deny log parsing * fix: Sandbox docs * refactor: Maintain SSOT across pkg dependencies * fix: Linter errors
This commit is contained in:
+91
-8
@@ -5,6 +5,16 @@ import (
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// DriverName identifies a sandbox driver implementation. Returned by
|
||||
// Sandbox.Name() and used wherever code needs to refer to a specific driver.
|
||||
type DriverName string
|
||||
|
||||
const (
|
||||
DriverSeatbelt DriverName = "seatbelt"
|
||||
DriverBubblewrap DriverName = "bubblewrap"
|
||||
DriverLandlock DriverName = "landlock"
|
||||
)
|
||||
|
||||
// ViolationKind is PMG's normalized taxonomy for sandbox denials.
|
||||
type ViolationKind string
|
||||
|
||||
@@ -21,7 +31,7 @@ const (
|
||||
// ViolationReport is a best-effort sandbox violation summary collected from a
|
||||
// sandbox implementation after command execution fails.
|
||||
type ViolationReport struct {
|
||||
SandboxName string
|
||||
SandboxName DriverName
|
||||
PolicyName string
|
||||
CorrelationID string
|
||||
Violations []Violation
|
||||
@@ -128,8 +138,8 @@ type Sandbox interface {
|
||||
// Callers must check result.ShouldRun() and only call cmd.Run() if true.
|
||||
Execute(ctx context.Context, cmd *exec.Cmd, policy *SandboxPolicy) (*ExecutionResult, error)
|
||||
|
||||
// Name returns the sandbox implementation name (e.g., "seatbelt", "bubblewrap").
|
||||
Name() string
|
||||
// Name returns the sandbox driver identifier.
|
||||
Name() DriverName
|
||||
|
||||
// IsAvailable returns true if the sandbox is available and functional on this platform.
|
||||
IsAvailable() bool
|
||||
@@ -139,20 +149,93 @@ type Sandbox interface {
|
||||
Close() error
|
||||
}
|
||||
|
||||
// ProfileInfo describes a user profile discovered on disk.
|
||||
type ProfileInfo struct {
|
||||
// Name is the profile name, derived from the file name without extension.
|
||||
Name string
|
||||
|
||||
// Path is the absolute path to the profile file.
|
||||
Path string
|
||||
|
||||
// Shadowed is true when a built-in profile of the same name exists and
|
||||
// will win during name-based resolution.
|
||||
Shadowed bool
|
||||
}
|
||||
|
||||
// ProfileSource identifies where a profile came from.
|
||||
type ProfileSource string
|
||||
|
||||
const (
|
||||
ProfileSourceBuiltin ProfileSource = "builtin"
|
||||
ProfileSourceUser ProfileSource = "user"
|
||||
)
|
||||
|
||||
// ProfileSummary describes a discoverable profile for listing purposes.
|
||||
type ProfileSummary struct {
|
||||
Name string
|
||||
Source ProfileSource
|
||||
Path string // "" for builtins; absolute path for user profiles
|
||||
Inherits string
|
||||
PackageManagers []string
|
||||
Description string
|
||||
Shadowed bool // true when a user file is masked by a same-named builtin
|
||||
}
|
||||
|
||||
// ResolveOptions tunes variable expansion when resolving a policy for display
|
||||
// or diffing. Zero values mean "use the current process environment".
|
||||
type ResolveOptions struct {
|
||||
CWD string
|
||||
Home string
|
||||
TmpDir string
|
||||
}
|
||||
|
||||
// ProfileRegistry manages built-in and custom sandbox policies.
|
||||
type ProfileRegistry interface {
|
||||
// GetProfile retrieves a policy by name.
|
||||
// Name can be a built-in profile (e.g., "npm-restrictive") or a path to a custom YAML file.
|
||||
// Name can be a built-in profile (e.g., "npm-restrictive"), the bare name of a
|
||||
// user profile under UserProfileDir(), or a path to a custom YAML file.
|
||||
// Resolution order: built-ins first, then the user profile directory.
|
||||
GetProfile(name string) (*SandboxPolicy, error)
|
||||
|
||||
// LoadCustomProfile loads a policy from a custom YAML file path.
|
||||
LoadCustomProfile(path string) (*SandboxPolicy, error)
|
||||
|
||||
// ListProfiles returns the names of all built-in profiles.
|
||||
ListProfiles() []string
|
||||
// ListProfiles returns all discoverable profiles: built-ins first, then
|
||||
// user profiles (including shadowed entries).
|
||||
ListProfiles() ([]ProfileSummary, error)
|
||||
|
||||
// ResolveProfile loads name and returns a policy with all path-bearing
|
||||
// fields expanded against opts (or the process environment).
|
||||
ResolveProfile(name string, opts ResolveOptions) (*SandboxPolicy, error)
|
||||
|
||||
// UserProfileDir returns the directory scanned for user profiles.
|
||||
UserProfileDir() string
|
||||
|
||||
// ListUserProfiles enumerates *.yml / *.yaml files under UserProfileDir().
|
||||
// A missing directory returns an empty slice with no error.
|
||||
ListUserProfiles() ([]ProfileInfo, error)
|
||||
|
||||
// BuiltinProfileYAML returns the embedded YAML bytes for a built-in
|
||||
// profile. Returns false if name is not a built-in.
|
||||
BuiltinProfileYAML(name string) ([]byte, bool)
|
||||
}
|
||||
|
||||
// RegistryOption configures a ProfileRegistry.
|
||||
type RegistryOption func(*registryOptions)
|
||||
|
||||
type registryOptions struct {
|
||||
userProfileDir string
|
||||
}
|
||||
|
||||
// WithUserProfileDir sets the directory the registry uses to discover user
|
||||
// profiles. The directory does not need to exist at construction time.
|
||||
func WithUserProfileDir(dir string) RegistryOption {
|
||||
return func(o *registryOptions) {
|
||||
o.userProfileDir = dir
|
||||
}
|
||||
}
|
||||
|
||||
// NewProfileRegistry creates a new profile registry with built-in policies.
|
||||
func NewProfileRegistry() (ProfileRegistry, error) {
|
||||
return newDefaultProfileRegistry()
|
||||
func NewProfileRegistry(opts ...RegistryOption) (ProfileRegistry, error) {
|
||||
return newDefaultProfileRegistry(opts...)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user