mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
chore: Cleanup sandbox
This commit is contained in:
@@ -10,7 +10,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NewSandbox creates a platform-specific sandbox instance for Windows.
|
// NewSandbox creates a platform-specific sandbox instance for Windows.
|
||||||
// TODO: Implement AppContainer or Job Objects based sandbox.
|
|
||||||
func NewSandbox() (sandbox.Sandbox, error) {
|
func NewSandbox() (sandbox.Sandbox, error) {
|
||||||
return nil, errors.New("sandbox not yet implemented for Windows")
|
return nil, errors.New("sandbox not yet implemented for Windows")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,17 +13,15 @@ import (
|
|||||||
"github.com/safedep/pmg/sandbox"
|
"github.com/safedep/pmg/sandbox"
|
||||||
)
|
)
|
||||||
|
|
||||||
// seatbeltSandbox implements the Sandbox interface using macOS Seatbelt (sandbox-exec).
|
|
||||||
type seatbeltSandbox struct {
|
type seatbeltSandbox struct {
|
||||||
translator *policyTranslator
|
translator *seatbeltPolicyTranslator
|
||||||
tempProfilePath string // Path to temporary .sb file, cleaned up in Close()
|
tempProfilePath string
|
||||||
cleanupCompleted bool // Track if cleanup already happened (idempotent Close)
|
cleanupCompleted bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// newSeatbeltSandbox creates a new Seatbelt sandbox instance.
|
|
||||||
func newSeatbeltSandbox() (*seatbeltSandbox, error) {
|
func newSeatbeltSandbox() (*seatbeltSandbox, error) {
|
||||||
return &seatbeltSandbox{
|
return &seatbeltSandbox{
|
||||||
translator: newPolicyTranslator(),
|
translator: newSeatbeltPolicyTranslator(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,30 +32,33 @@ func newSeatbeltSandbox() (*seatbeltSandbox, error) {
|
|||||||
// This implementation modifies the cmd in place and does NOT execute it.
|
// This implementation modifies the cmd in place and does NOT execute it.
|
||||||
// Returns ExecutionResult with executed=false, indicating the caller must run cmd.Run().
|
// Returns ExecutionResult with executed=false, indicating the caller must run cmd.Run().
|
||||||
func (s *seatbeltSandbox) Execute(ctx context.Context, cmd *exec.Cmd, policy *sandbox.SandboxPolicy) (*sandbox.ExecutionResult, error) {
|
func (s *seatbeltSandbox) Execute(ctx context.Context, cmd *exec.Cmd, policy *sandbox.SandboxPolicy) (*sandbox.ExecutionResult, error) {
|
||||||
// Translate PMG policy to Seatbelt profile
|
|
||||||
sbProfile, err := s.translator.translate(policy)
|
sbProfile, err := s.translator.translate(policy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to translate sandbox policy: %w", err)
|
return nil, fmt.Errorf("failed to translate sandbox policy: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write Seatbelt profile to temporary file
|
|
||||||
// The file will be cleaned up when Close() is called
|
|
||||||
tmpFile, err := os.CreateTemp("", "pmg-sandbox-*.sb")
|
tmpFile, err := os.CreateTemp("", "pmg-sandbox-*.sb")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create temporary sandbox profile: %w", err)
|
return nil, fmt.Errorf("failed to create temporary sandbox profile: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the path for cleanup in Close()
|
defer func() {
|
||||||
|
if err := tmpFile.Close(); err != nil {
|
||||||
|
log.Warnf("failed to close temporary sandbox profile: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Storing the path is required for cleanup in Close()
|
||||||
s.tempProfilePath = tmpFile.Name()
|
s.tempProfilePath = tmpFile.Name()
|
||||||
|
|
||||||
if _, err := tmpFile.WriteString(sbProfile); err != nil {
|
if _, err := tmpFile.WriteString(sbProfile); err != nil {
|
||||||
tmpFile.Close()
|
if err := os.Remove(s.tempProfilePath); err != nil {
|
||||||
// Clean up on error
|
log.Warnf("failed to remove temporary sandbox profile: %v", err)
|
||||||
os.Remove(s.tempProfilePath)
|
}
|
||||||
|
|
||||||
s.tempProfilePath = ""
|
s.tempProfilePath = ""
|
||||||
return nil, fmt.Errorf("failed to write sandbox profile: %w", err)
|
return nil, fmt.Errorf("failed to write sandbox profile: %w", err)
|
||||||
}
|
}
|
||||||
tmpFile.Close()
|
|
||||||
|
|
||||||
log.Debugf("Seatbelt profile written to %s", s.tempProfilePath)
|
log.Debugf("Seatbelt profile written to %s", s.tempProfilePath)
|
||||||
log.Debugf("Seatbelt profile content:\n%s", sbProfile)
|
log.Debugf("Seatbelt profile content:\n%s", sbProfile)
|
||||||
|
|||||||
+7
-10
@@ -12,16 +12,13 @@ import (
|
|||||||
"github.com/safedep/pmg/sandbox/util"
|
"github.com/safedep/pmg/sandbox/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// policyTranslator translates PMG sandbox policies to Seatbelt Profile Language (.sb).
|
type seatbeltPolicyTranslator struct{}
|
||||||
type policyTranslator struct{}
|
|
||||||
|
|
||||||
// newPolicyTranslator creates a new policy translator.
|
func newSeatbeltPolicyTranslator() *seatbeltPolicyTranslator {
|
||||||
func newPolicyTranslator() *policyTranslator {
|
return &seatbeltPolicyTranslator{}
|
||||||
return &policyTranslator{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// translate converts a PMG SandboxPolicy to Seatbelt Profile Language.
|
func (t *seatbeltPolicyTranslator) translate(policy *sandbox.SandboxPolicy) (string, error) {
|
||||||
func (t *policyTranslator) translate(policy *sandbox.SandboxPolicy) (string, error) {
|
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
@@ -62,7 +59,7 @@ func (t *policyTranslator) translate(policy *sandbox.SandboxPolicy) (string, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
// translateFilesystem translates filesystem access rules.
|
// translateFilesystem translates filesystem access rules.
|
||||||
func (t *policyTranslator) translateFilesystem(policy *sandbox.SandboxPolicy, sb *strings.Builder) error {
|
func (t *seatbeltPolicyTranslator) translateFilesystem(policy *sandbox.SandboxPolicy, sb *strings.Builder) error {
|
||||||
sb.WriteString(";; Filesystem access\n")
|
sb.WriteString(";; Filesystem access\n")
|
||||||
|
|
||||||
// Expand and add allow read rules
|
// Expand and add allow read rules
|
||||||
@@ -137,7 +134,7 @@ func (t *policyTranslator) translateFilesystem(policy *sandbox.SandboxPolicy, sb
|
|||||||
}
|
}
|
||||||
|
|
||||||
// translateNetwork translates network access rules.
|
// translateNetwork translates network access rules.
|
||||||
func (t *policyTranslator) translateNetwork(policy *sandbox.SandboxPolicy, sb *strings.Builder) error {
|
func (t *seatbeltPolicyTranslator) translateNetwork(policy *sandbox.SandboxPolicy, sb *strings.Builder) error {
|
||||||
sb.WriteString(";; Network access\n")
|
sb.WriteString(";; Network access\n")
|
||||||
|
|
||||||
// If there are allow outbound rules, allow network-outbound generally
|
// If there are allow outbound rules, allow network-outbound generally
|
||||||
@@ -165,7 +162,7 @@ func (t *policyTranslator) translateNetwork(policy *sandbox.SandboxPolicy, sb *s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// translateProcess translates process execution rules.
|
// translateProcess translates process execution rules.
|
||||||
func (t *policyTranslator) translateProcess(policy *sandbox.SandboxPolicy, sb *strings.Builder) error {
|
func (t *seatbeltPolicyTranslator) translateProcess(policy *sandbox.SandboxPolicy, sb *strings.Builder) error {
|
||||||
sb.WriteString(";; Process execution\n")
|
sb.WriteString(";; Process execution\n")
|
||||||
|
|
||||||
// Add allow exec rules
|
// Add allow exec rules
|
||||||
Reference in New Issue
Block a user