You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
subgraph-oz/profile.go

208 lines
4.5 KiB

package oz
import (
"encoding/json"
"fmt"
"io/ioutil"
"path"
"strings"
"github.com/subgraph/oz/network"
)
type Profile struct {
// Name of this profile
Name string
// Path to binary to launch
Path string
// List of path to binaries matching this sandbox
Paths []string
// Path of the config file
ProfilePath string `json:"-"`
// Optional path of binary to watch for watchdog purposes if different than Path
Watchdog string
// Optional wrapper binary to use when launching command (ex: tsocks)
Wrapper string
// If true launch one sandbox per instance, otherwise run all instances in same sandbox
Multi bool
// Disable mounting of sys and proc inside the sandbox
NoSysProc bool
// Disable bind mounting of default directories (etc,usr,bin,lib,lib64)
// Also disables default blacklist items (/sbin, /usr/sbin, /usr/bin/sudo)
// Normally not used
NoDefaults bool
// Allow bind mounting of files passed as arguments inside the sandbox
AllowFiles bool `json:"allow_files"`
// List of paths to bind mount inside jail
Whitelist []WhitelistItem
// List of paths to blacklist inside jail
Blacklist []BlacklistItem
// Optional XServer config
XServer XServerConf
// List of environment variables
Environment []EnvVar
// Networking
Networking NetworkProfile
// Seccomp
Seccomp SeccompConf
}
type AudioMode string
const (
PROFILE_AUDIO_NONE AudioMode = "none"
PROFILE_AUDIO_SPEAKER AudioMode = "speaker"
PROFILE_AUDIO_FULL AudioMode = "full"
)
type XServerConf struct {
Enabled bool
TrayIcon string `json:"tray_icon"`
WindowIcon string `json:"window_icon"`
EnableTray bool `json:"enable_tray"`
EnableNotifications bool `json:"enable_notifications"`
UsePulseAudio bool `json:"use_pulse_audio"`
DisableClipboard bool `json:"disable_clipboard"`
AudioMode AudioMode `json:"audio_mode"`
}
type SeccompMode string
const (
PROFILE_SECCOMP_WHITELIST SeccompMode = "whitelist"
PROFILE_SECCOMP_BLACKLIST SeccompMode = "blacklist"
PROFILE_SECCOMP_DISABLED SeccompMode = "disabled"
)
type SeccompConf struct {
Mode SeccompMode
Enforce bool
Seccomp_Whitelist string
Seccomp_Blacklist string
}
type WhitelistItem struct {
Path string
ReadOnly bool `json:"read_only"`
}
type BlacklistItem struct {
Path string
}
type EnvVar struct {
Name string
Value string
}
// Sandbox network definition
type NetworkProfile struct {
// One of empty, host, bridge
Nettype network.NetType `json:"type"`
// Name of the bridge to attach to
//Bridge string
// List of Sockets we want to attach to the jail
// Applies to Nettype: bridge and empty only
Sockets []network.ProxyConfig
}
const defaultProfileDirectory = "/var/lib/oz/cells.d"
var loadedProfiles []*Profile
type Profiles []*Profile
func NewDefaultProfile() *Profile {
return &Profile{
Multi: false,
AllowFiles: false,
XServer: XServerConf{
Enabled: true,
EnableTray: false,
EnableNotifications: false,
UsePulseAudio: false,
AudioMode: PROFILE_AUDIO_NONE,
},
}
}
func (ps Profiles) GetProfileByName(name string) (*Profile, error) {
if loadedProfiles == nil {
ps, err := LoadProfiles(defaultProfileDirectory)
if err != nil {
return nil, err
}
loadedProfiles = ps
}
for _, p := range loadedProfiles {
if p.Name == name {
return p, nil
}
}
return nil, nil
}
func (ps Profiles) GetProfileByPath(bpath string) (*Profile, error) {
if loadedProfiles == nil {
ps, err := LoadProfiles(defaultProfileDirectory)
if err != nil {
return nil, err
}
loadedProfiles = ps
}
for _, p := range loadedProfiles {
if p.Path == bpath {
return p, nil
}
for _, pp := range p.Paths {
if pp == bpath {
return p, nil
}
}
}
return nil, nil
}
func LoadProfiles(dir string) (Profiles, error) {
fs, err := ioutil.ReadDir(dir)
if err != nil {
return nil, err
}
ps := []*Profile{}
for _, f := range fs {
if !f.IsDir() {
name := path.Join(dir, f.Name())
if strings.HasSuffix(f.Name(), ".json") {
p, err := loadProfileFile(name)
if err != nil {
return nil, fmt.Errorf("error loading '%s': %v", f.Name(), err)
}
ps = append(ps, p)
}
}
}
loadedProfiles = ps
return ps, nil
}
func loadProfileFile(file string) (*Profile, error) {
bs, err := ioutil.ReadFile(file)
if err != nil {
return nil, err
}
p := new(Profile)
if err := json.Unmarshal(bs, p); err != nil {
return nil, err
}
if p.Name == "" {
p.Name = path.Base(p.Path)
}
p.ProfilePath = file
return p, nil
}