WIP on start: Build parameter file

This commit is contained in:
yo 2022-06-19 14:48:55 +02:00
parent fcf7d68d06
commit d9e1e20afc

View File

@ -5,7 +5,6 @@ import (
"fmt"
"github.com/c-robinson/iplib"
log "github.com/sirupsen/logrus"
"io/ioutil"
"net"
"os"
"regexp"
@ -13,21 +12,18 @@ import (
"strings"
)
// FIXME : Do not work?!
func setJailConfigUpdated(jail *Jail) error {
if len(jail.ConfigPath) == 0 {
return errors.New(fmt.Sprintf("No config path for jail %s", jail.Name))
}
for i, j := range gJails {
if jail.Name == j.Name {
fmt.Printf("Tag %s as configUpdated\n", jail.Name)
gJails[i].ConfigUpdated = true
return nil
}
j, err := getJailFromArray(jail.Name, gJails)
if err != nil {
return err
}
return errors.New("Jail not found")
j.ConfigUpdated = true
return nil
}
func mountProcFs(jail *Jail) error {
@ -194,12 +190,18 @@ func mountAllJailFsFromHost(jail *Jail) error {
func prepareJailedZfsDatasets(jail *Jail) error {
if jail.Config.Jail_zfs > 0 {
// For jail to mount filesystem, enforce_statfs should be 1 or lower (2 is the default)
// TODO : Write these changes in jail config file
jail.Config.Allow_mount = 1
jail.Config.Allow_mount_zfs = 1
if jail.Config.Allow_mount != 1 {
jail.Config.Allow_mount = 1
setJailConfigUpdated(jail)
}
if jail.Config.Allow_mount_zfs != 1 {
jail.Config.Allow_mount_zfs = 1
setJailConfigUpdated(jail)
}
// TODO : Overload Json Unmarshalling to fix bad typed values, keeping iocage compatibility
if jail.Config.Enforce_statfs > "1" {
jail.Config.Enforce_statfs = "1"
setJailConfigUpdated(jail)
}
for _, d := range strings.Split(jail.Config.Jail_zfs_dataset, " ") {
// Check if dataset exist, create if necessary
@ -450,14 +452,7 @@ func genNatIpv4(jail *Jail) ([]string, error) {
func buildDevfsRuleSet(jail *Jail) (error, int) {
rulesets := []int{}
// TODO : Could be replaced by "add include $devfsrules_unhide_login" (see /etc/devfs.rules)
/*default_devs := [47]string {"hide", "null", "zero", "crypto", "random", "urandom", "ptyp*",
"ptyq*", "ptyr*", "ptys*", "ptyP*", "ptyQ*", "ptyR*", "ptyS*", "ptyl*",
"ptym*", "ptyn*", "ptyo*", "ptyL*", "ptyM*", "ptyN*", "pty0*", "ttyp*",
"ttyq*", "ttyr*", "ttys*", "ttyP*", "ttyQ*", "ttyR*", "ttyS*", "ttyl*",
"ttym*", "ttyn*", "ttyo*", "ttyL*", "ttyM*", "ttyN*", "tty0*", "ptmx",
"pts", "pts/*", "fd", "fd/*", "stdin", "stdout", "stderr", "zfs"}
*/
// Get known rulesets
out, err := executeCommand("devfs rule showsets")
if err != nil {
@ -480,22 +475,25 @@ func buildDevfsRuleSet(jail *Jail) (error, int) {
}
}
log.Debug("buildDevfsRuleSet: Build ruleset %d\n", ruleset)
// Get default devfs_ruleset for the datastore
ds, err := getDatastoreFromArray(jail.Datastore, gDatastores)
// UPDATE: We don't need this as every jail have a default Devfs_ruleset value
/*ds, err := getDatastoreFromArray(jail.Datastore, gDatastores)
if err != nil {
return errors.New(fmt.Sprintf("Error getting datastore %s for jail %s", jail.Datastore, jail.Name)), 0
}
defaultrs, err := strconv.ParseInt(ds.DefaultJailConfig.Devfs_ruleset, 10, 64)
if err != nil {
return errors.New(fmt.Sprintf("Error parsing default devfs_ruleset for datastore %s", jail.Datastore)), 0
}
}*/
// Clone configured devfs_rulesetto a dynamic ruleset
// Clone configured devfs_ruleset to a dynamic ruleset
if false == isStringInArray(srs, jail.Config.Devfs_ruleset) {
return errors.New(fmt.Sprintf("Unknown ruleset: %s", jail.Config.Devfs_ruleset)), 0
}
rs, _ := strconv.Atoi(jail.Config.Devfs_ruleset)
err := copyDevfsRuleset(ruleset, rs)
err = copyDevfsRuleset(ruleset, rs)
if err != nil {
return err, 0
}
@ -523,6 +521,204 @@ func buildDevfsRuleSet(jail *Jail) (error, int) {
return nil, ruleset
}
/*****************************************************************************
* Build the file containing jail start parameters, in
* /var/run/jail.${jail_internal_name}.conf
****************************************************************************/
func buildJailParameters(jail *Jail, dynruleset int) error {
parameterFilePath := fmt.Sprintf("/var/run/jail.%s.conf", jail.InternalName)
pfile, err := os.Create(parameterFilePath)
if err != nil {
return errors.New(fmt.Sprintf("Unable to create file /var/run/jail.%d.conf", jail.InternalName))
}
defer pfile.Close()
if _, err = pfile.WriteString(fmt.Sprintf("%s {\n", jail.InternalName)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if jail.Config.Vnet > 0 {
if _, err = pfile.WriteString(" vnet;\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
// FreeBSD 9.3 and under do not support these 2 options
if gJailHost.version.major > 9 || (gJailHost.version.major == 9 && gJailHost.version.minor > 3) {
if _, err = pfile.WriteString(" mount.fdescfs = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if jail.Config.Allow_mount_tmpfs > 0 {
if _, err = pfile.WriteString(" allow.mount.tmpfs = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
}
if gJailHost.version.major >= 12 {
if jail.Config.Allow_mlock > 0 {
if _, err = pfile.WriteString(" allow.mlock = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if jail.Config.Allow_mount_fusefs > 0 {
if _, err = pfile.WriteString(" allow.mount.fusefs = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if jail.Config.Allow_vmm > 0 {
if _, err = pfile.WriteString(" allow.vmm = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
}
if jail.Config.Allow_set_hostname > 0 {
if _, err = pfile.WriteString(" allow.set_hostname = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if jail.Config.Mount_devfs > 0 {
if _, err = pfile.WriteString(" mount.devfs = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if jail.Config.Allow_raw_sockets > 0 {
if _, err = pfile.WriteString(" allow.raw_sockets = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if jail.Config.Allow_sysvipc > 0 {
if _, err = pfile.WriteString(" allow.sysvipc = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if jail.Config.Allow_quotas > 0 {
if _, err = pfile.WriteString(" allow.quotas = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if jail.Config.Allow_socket_af > 0 {
if _, err = pfile.WriteString(" allow.socket_af = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if jail.Config.Allow_chflags > 0 {
if _, err = pfile.WriteString(" allow.chflags = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if jail.Config.Allow_mount > 0 {
if _, err = pfile.WriteString(" allow.mount = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if jail.Config.Allow_mount_devfs > 0 {
if _, err = pfile.WriteString(" allow.mount.devfs = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if jail.Config.Allow_mount_nullfs > 0 {
if _, err = pfile.WriteString(" allow.mount.nullfs = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if jail.Config.Allow_mount_procfs > 0 {
if _, err = pfile.WriteString(" allow.mount.procfs = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if jail.Config.Allow_mount_zfs > 0 {
if _, err = pfile.WriteString(" allow.mount.zfs = \"1\";\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if gJailHost.version.major > 10 || (gJailHost.version.major == 10 && gJailHost.version.minor > 3) {
if _, err = pfile.WriteString(fmt.Sprintf(" sysvmsg = \"%s\";\n", jail.Config.Sysvmsg)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if _, err = pfile.WriteString(fmt.Sprintf(" sysvsem = \"%s\";\n", jail.Config.Sysvsem)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if _, err = pfile.WriteString(fmt.Sprintf(" sysvshm = \"%s\";\n", jail.Config.Sysvshm)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if gJailHost.version.major >= 12 {
if _, err = pfile.WriteString(fmt.Sprintf(" exec.created = \"%s\";\n", jail.Config.Exec_created)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if _, err = pfile.WriteString(fmt.Sprintf(" host.domainname = \"%s\";\n", jail.Config.Host_domainname)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if _, err = pfile.WriteString(fmt.Sprintf(" host.hostname = \"%s\";\n", jail.Config.Host_hostname)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if _, err = pfile.WriteString(fmt.Sprintf(" path = \"%s\";\n", jail.RootPath)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if _, err = pfile.WriteString(fmt.Sprintf(" securelevel = \"%s\";\n", jail.Config.Securelevel)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
// FIXME : Handle the same name jail on different datastores
if _, err = pfile.WriteString(fmt.Sprintf(" host.hostuuid = \"%s\";\n", jail.Config.Host_hostuuid)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if _, err = pfile.WriteString(fmt.Sprintf(" devfs_ruleset = \"%d\";\n", dynruleset)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if _, err = pfile.WriteString(fmt.Sprintf(" enforce_statfs = \"%s\";\n", jail.Config.Enforce_statfs)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if _, err = pfile.WriteString(fmt.Sprintf(" children.max = \"%s\";\n", jail.Config.Children_max)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if _, err = pfile.WriteString(fmt.Sprintf(" exec.clean = \"%d\";\n", jail.Config.Exec_clean)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if _, err = pfile.WriteString(fmt.Sprintf(" exec.timeout = \"%s\";\n", jail.Config.Exec_timeout)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if _, err = pfile.WriteString(fmt.Sprintf(" stop.timeout = \"%s\";\n", jail.Config.Stop_timeout)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
splits := strings.Split(jail.RootPath, "/")
fstabPath := strings.Join(append(splits[:len(splits)-1],
strings.Replace(splits[len(splits)-1], "root", "fstab", 1)), "/")
if _, err = pfile.WriteString(fmt.Sprintf(" mount.fstab = \"%s\";\n", fstabPath)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if _, err = pfile.WriteString(" allow.dying;\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
// get current datastore to get mountpoint
ds, err := getDatastoreFromArray(jail.Datastore, gDatastores)
if err != nil {
return errors.New(fmt.Sprintf("Unable to get datastore %s for jail %s", jail.Datastore, jail.Name))
}
consolelog := fmt.Sprintf("%s/log/%s-console.log", ds.Mountpoint, jail.InternalName)
if _, err = pfile.WriteString(fmt.Sprintf(" exec.consolelog = \"%s\";\n", consolelog)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if jail.Config.Ip_hostname > 0 {
if _, err = pfile.WriteString(fmt.Sprintf(" ip_hostname = \"%s\";\n", jail.Config.Ip_hostname)); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
}
if _, err = pfile.WriteString(" persist;\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
if _, err = pfile.WriteString("}\n"); err != nil {
return errors.New(fmt.Sprintf("Unable to write to file /var/run/jail.%d.conf: %v", jail.InternalName, err))
}
return nil
}
/*
Start jail:
Check jail fstab?
@ -574,13 +770,7 @@ func StartJail(args []string) {
}
if len(cj.Config.Hostid) > 0 && cj.Config.Hostid_strict_check > 0 {
hostid, err := ioutil.ReadFile("/etc/hostid")
if err != nil {
fmt.Printf(err.Error())
return
}
hostid = []byte(strings.Replace(string(hostid), "\n", "", -1))
if strings.EqualFold(string(hostid), cj.Config.Hostid) == false {
if strings.EqualFold(gJailHost.hostid, cj.Config.Hostid) == false {
fmt.Printf("hostid is not matching and hostid_strict_check is on. Not starting jail.\n")
return
}
@ -721,24 +911,24 @@ func StartJail(args []string) {
}
if cj.Config.Vnet == 0 {
log.Debug("Generate NAT IPv4 without VNet")
log.Debug("Generate NAT IPv4 without VNet\n")
ip4, err := genNatIpv4(cj)
if err != nil {
fmt.Printf("%s\n", err.Error())
return
}
log.Debug("Configuring NAT : Set ip4_addr to %s", ip4[0])
log.Debug("Configuring NAT : Set ip4_addr to %s\n", ip4[0])
// This IP should not be saved into json
cj.Config.Ip4_addr = fmt.Sprintf("%s|%s", cj.Config.Nat_interface, ip4[0])
} else {
log.Debug("Generate NAT IPv4 with VNet")
log.Debug("Generate NAT IPv4 with VNet\n")
ip4, err := genNatIpv4(cj)
if err != nil {
fmt.Printf("%s\n", err.Error())
return
}
log.Debug("Configuring NAT : Set ip4_addr to %s, defaultrouter to %s", ip4[1], ip4[0])
log.Debug("Configuring NAT : Set ip4_addr to %s, defaultrouter to %s\n", ip4[1], ip4[0])
// This IP should not be saved into json
cj.Config.Ip4_addr = fmt.Sprintf("vnet0|%s", ip4[1])
cj.Config.Defaultrouter = ip4[0]
@ -757,14 +947,21 @@ func StartJail(args []string) {
net = append(net, strings.Split(cj.Config.Vnet_interfaces, " ")...)
}
err, rs := buildDevfsRuleSet(cj)
err, dynrs := buildDevfsRuleSet(cj)
if err != nil {
fmt.Printf("%s\n", err.Error())
return
}
// CONTINUE HERE, around https://github.com/iocage/iocage/blob/master/iocage_lib/ioc_start.py:516
fmt.Printf("Built ruleset: %d\n", rs)
// CONTINUE HERE, around https://github.com/iocage/iocage/blob/master/iocage_lib/ioc_start.py:516
err = buildJailParameters(cj, dynrs)
if err != nil {
fmt.Printf("%s\n", err.Error())
return
}
// Synchronize jail config to disk
WriteConfigToDisk(false)
/*
out, err := executeCommand(fmt.Sprintf("rctl jail:%s", cj.InternalName))