/
jailer.go
117 lines (101 loc) · 4.18 KB
/
jailer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package configs
import (
"fmt"
"path/filepath"
"strings"
"sync"
profileModel "github.com/combust-labs/firebuild/pkg/profiles/model"
"github.com/combust-labs/firebuild/pkg/utils"
"github.com/spf13/pflag"
)
// ChrootBaseMaxLength is the maximum length of the chroot base setting.
//
// This limitation is dictated but the Kernel socket path maxmimum length set to 107 characters + zero terminator.
//
// The constant jailer path suffix used by firebuild is 76 characters:
//
// - constant /firecracker-v0.22.4-x86_64/ (automatically generated by the jailer)
// - VMM ID is always 20 characters long
// - constant /root/run/firecracker.socket assumed by the jailer
//
// Example: /firecracker-v0.22.4-x86_64/sifuqm4rq2runxparjcx/root/run/firecracker.socket.
//
// Using more than 31 characters for the --chroot-base value, regardless if in the profile setting or using the command --chroot-base flag, will lead to a very obscure error.
const ChrootBaseMaxLength = 31
// JailingFirecrackerConfig represents Jailerspecific configuration options.
type JailingFirecrackerConfig struct {
sync.Mutex
flagBase
ProfileInheriting `json:"-"`
ValidatingConfig `json:"-"`
BinaryFirecracker string `json:"BinaryFirecracker" mapstructure:"BinaryFirecracker"`
BinaryJailer string `json:"BinaryJailer" mapstructure:"BinaryJailer"`
ChrootBase string `json:"ChrootBase" mapstructure:"ChrootBase"`
JailerGID int `json:"JailerGid" mapstructure:"JailerGid"`
JailerNumeNode int `json:"JailerNumaNode" mapstructure:"JailerNumaNode"`
JailerUID int `json:"JailerUid" mapstructure:"JailerUid"`
NetNS string `json:"NetNS" mapstructure:"NetNS"`
vmmID string
}
// NewJailingFirecrackerConfig returns a new instance of the configuration.
func NewJailingFirecrackerConfig() *JailingFirecrackerConfig {
cfg := &JailingFirecrackerConfig{}
return cfg.ensure()
}
// JailerChrootDirectory returns a full path to the jailer configuration directory.
// This method will return empty string until the flag set returned by FlagSet() is parsed.
func (c *JailingFirecrackerConfig) JailerChrootDirectory() string {
return filepath.Join(c.ChrootBase,
filepath.Base(c.BinaryFirecracker), c.VMMID())
}
// VMMID returns a configuration instance unique VMM ID.
func (c *JailingFirecrackerConfig) VMMID() string {
return c.vmmID
}
// FlagSet returns an instance of the flag set for the configuration.
func (c *JailingFirecrackerConfig) FlagSet() *pflag.FlagSet {
if c.initFlagSet() {
c.flagSet.StringVar(&c.BinaryFirecracker, "binary-firecracker", "", "Path to the Firecracker binary to use")
c.flagSet.StringVar(&c.BinaryJailer, "binary-jailer", "", "Path to the Firecracker Jailer binary to use")
c.flagSet.StringVar(&c.ChrootBase, "chroot-base", "/srv/jailer", "chroot base directory; can't be empty or /")
c.flagSet.IntVar(&c.JailerGID, "jailer-gid", 0, "Jailer GID value")
c.flagSet.IntVar(&c.JailerNumeNode, "jailer-numa-node", 0, "Jailer NUMA node")
c.flagSet.IntVar(&c.JailerUID, "jailer-uid", 0, "Jailer UID value")
c.flagSet.StringVar(&c.NetNS, "netns", "/var/lib/netns", "Network namespace")
}
return c.flagSet
}
// UpdateFromProfile updates the configuration from a profile.
func (c *JailingFirecrackerConfig) UpdateFromProfile(input *profileModel.Profile) error {
if input.BinaryFirecracker != "" {
c.BinaryFirecracker = input.BinaryFirecracker
}
if input.BinaryJailer != "" {
c.BinaryJailer = input.BinaryJailer
}
if input.ChrootBase != "" {
c.ChrootBase = input.ChrootBase
}
return nil
}
// Validate validates the correctness of the configuration.
func (c *JailingFirecrackerConfig) Validate() error {
if c.ChrootBase == "" || c.ChrootBase == "/" {
return fmt.Errorf("--chroot-base must be set to value other than empty and /")
}
if len(c.ChrootBase) > ChrootBaseMaxLength {
return fmt.Errorf("--chroot-base must cannot be longer than %d characters", ChrootBaseMaxLength)
}
return nil
}
// WithVMMID allows overriding the VMM ID.
func (c *JailingFirecrackerConfig) WithVMMID(input string) *JailingFirecrackerConfig {
c.vmmID = input
return c
}
func (c *JailingFirecrackerConfig) ensure() *JailingFirecrackerConfig {
if c.vmmID == "" {
c.vmmID = strings.ToLower(utils.RandStringWithDigitsBytes(20))
}
return c
}