Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions cmd/oci-runtime-tool/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"fmt"
"os"
"runtime"
"strconv"
"strings"
"unicode"
Expand Down Expand Up @@ -90,6 +91,7 @@ var generateFlags = []cli.Flag{
cli.StringSliceFlag{Name: "mounts-add", Usage: "configures additional mounts inside container"},
cli.StringSliceFlag{Name: "mounts-remove", Usage: "remove destination mountpoints from inside container"},
cli.BoolFlag{Name: "mounts-remove-all", Usage: "remove all mounts inside container"},
cli.StringFlag{Name: "os", Value: runtime.GOOS, Usage: "operating system the container is created for"},
cli.StringFlag{Name: "output", Usage: "output file (defaults to stdout)"},
cli.BoolFlag{Name: "privileged", Usage: "enable privileged container settings"},
cli.StringSliceFlag{Name: "process-cap-add-ambient", Usage: "add Linux ambient capabilities"},
Expand Down Expand Up @@ -141,21 +143,23 @@ var generateCommand = cli.Command{
Before: before,
Action: func(context *cli.Context) error {
// Start from the default template.
specgen := generate.New()
specgen, err := generate.New(context.String("os"))
if err != nil {
return err
}

var template string
if context.IsSet("template") {
template = context.String("template")
}
if template != "" {
var err error
specgen, err = generate.NewFromFile(template)
if err != nil {
return err
}
}

err := setupSpec(&specgen, context)
err = setupSpec(&specgen, context)
if err != nil {
return err
}
Expand Down
221 changes: 115 additions & 106 deletions generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,117 +36,128 @@ type ExportOptions struct {
Seccomp bool // seccomp toggles if only seccomp should be exported
}

// New creates a spec Generator with the default spec.
func New() Generator {
spec := rspec.Spec{
// New creates a spec Generator with the default spec for the target
// OS.
func New(os string) (generator Generator, err error) {
if os != "linux" && os != "solaris" {
return generator, fmt.Errorf("no defaults configured for %s", os)
}

config := rspec.Spec{
Version: rspec.Version,
Root: &rspec.Root{
Path: "rootfs",
Readonly: false,
},
Process: &rspec.Process{
Terminal: false,
User: rspec.User{},
Args: []string{
"sh",
},
Env: []string{
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM=xterm",
},
Hostname: "mrsdalloway",
}

if os == "linux" || os == "solaris" {
config.Process.User = rspec.User{}
config.Process.Env = []string{
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM=xterm",
}
config.Process.Cwd = "/"
config.Process.Rlimits = []rspec.POSIXRlimit{
{
Type: "RLIMIT_NOFILE",
Hard: uint64(1024),
Soft: uint64(1024),
},
Cwd: "/",
Capabilities: &rspec.LinuxCapabilities{
Bounding: []string{
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID",
"CAP_FOWNER",
"CAP_MKNOD",
"CAP_NET_RAW",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETFCAP",
"CAP_SETPCAP",
"CAP_NET_BIND_SERVICE",
"CAP_SYS_CHROOT",
"CAP_KILL",
"CAP_AUDIT_WRITE",
},
Permitted: []string{
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID",
"CAP_FOWNER",
"CAP_MKNOD",
"CAP_NET_RAW",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETFCAP",
"CAP_SETPCAP",
"CAP_NET_BIND_SERVICE",
"CAP_SYS_CHROOT",
"CAP_KILL",
"CAP_AUDIT_WRITE",
},
Inheritable: []string{
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID",
"CAP_FOWNER",
"CAP_MKNOD",
"CAP_NET_RAW",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETFCAP",
"CAP_SETPCAP",
"CAP_NET_BIND_SERVICE",
"CAP_SYS_CHROOT",
"CAP_KILL",
"CAP_AUDIT_WRITE",
},
Effective: []string{
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID",
"CAP_FOWNER",
"CAP_MKNOD",
"CAP_NET_RAW",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETFCAP",
"CAP_SETPCAP",
"CAP_NET_BIND_SERVICE",
"CAP_SYS_CHROOT",
"CAP_KILL",
"CAP_AUDIT_WRITE",
},
Ambient: []string{
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID",
"CAP_FOWNER",
"CAP_MKNOD",
"CAP_NET_RAW",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETFCAP",
"CAP_SETPCAP",
"CAP_NET_BIND_SERVICE",
"CAP_SYS_CHROOT",
"CAP_KILL",
"CAP_AUDIT_WRITE",
},
}
}

if os == "linux" {
config.Process.Capabilities = &rspec.LinuxCapabilities{
Bounding: []string{
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID",
"CAP_FOWNER",
"CAP_MKNOD",
"CAP_NET_RAW",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETFCAP",
"CAP_SETPCAP",
"CAP_NET_BIND_SERVICE",
"CAP_SYS_CHROOT",
"CAP_KILL",
"CAP_AUDIT_WRITE",
},
Rlimits: []rspec.POSIXRlimit{
{
Type: "RLIMIT_NOFILE",
Hard: uint64(1024),
Soft: uint64(1024),
},
Permitted: []string{
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID",
"CAP_FOWNER",
"CAP_MKNOD",
"CAP_NET_RAW",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETFCAP",
"CAP_SETPCAP",
"CAP_NET_BIND_SERVICE",
"CAP_SYS_CHROOT",
"CAP_KILL",
"CAP_AUDIT_WRITE",
},
},
Hostname: "mrsdalloway",
Mounts: []rspec.Mount{
Inheritable: []string{
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID",
"CAP_FOWNER",
"CAP_MKNOD",
"CAP_NET_RAW",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETFCAP",
"CAP_SETPCAP",
"CAP_NET_BIND_SERVICE",
"CAP_SYS_CHROOT",
"CAP_KILL",
"CAP_AUDIT_WRITE",
},
Effective: []string{
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID",
"CAP_FOWNER",
"CAP_MKNOD",
"CAP_NET_RAW",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETFCAP",
"CAP_SETPCAP",
"CAP_NET_BIND_SERVICE",
"CAP_SYS_CHROOT",
"CAP_KILL",
"CAP_AUDIT_WRITE",
},
Ambient: []string{
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID",
"CAP_FOWNER",
"CAP_MKNOD",
"CAP_NET_RAW",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETFCAP",
"CAP_SETPCAP",
"CAP_NET_BIND_SERVICE",
"CAP_SYS_CHROOT",
"CAP_KILL",
"CAP_AUDIT_WRITE",
},
}
config.Mounts = []rspec.Mount{
{
Destination: "/proc",
Type: "proc",
Expand Down Expand Up @@ -183,8 +194,8 @@ func New() Generator {
Source: "sysfs",
Options: []string{"nosuid", "noexec", "nodev", "ro"},
},
},
Linux: &rspec.Linux{
}
config.Linux = &rspec.Linux{
Resources: &rspec.LinuxResources{
Devices: []rspec.LinuxDeviceCgroup{
{
Expand All @@ -210,13 +221,11 @@ func New() Generator {
Type: "mount",
},
},
Devices: []rspec.LinuxDevice{},
},
}
spec.Linux.Seccomp = seccomp.DefaultProfile(&spec)
return Generator{
spec: &spec,
Seccomp: seccomp.DefaultProfile(&config),
}
}

return Generator{spec: &config}, nil
}

// NewFromSpec creates a spec Generator from a given spec.
Expand Down
3 changes: 3 additions & 0 deletions man/oci-runtime-tool-generate.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,9 @@ read the configuration from `config.json`.
Remove all mounts inside the container. The default is *false*.
When specified with --mount-add, this option will be parsed first.

**--os**=OS
Operating system used within the container.

**--output**=PATH
Instead of writing the configuration JSON to stdout, write it to a
file at *PATH* (overwriting the existing content if a file already
Expand Down
5 changes: 5 additions & 0 deletions validate/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,11 @@ func (v *Validator) CheckPlatform() (errs error) {
return
}

if v.HostSpecific && v.platform != runtime.GOOS {
errs = multierror.Append(errs, fmt.Errorf("platform %q differs from the host %q, skipping host-specific checks", v.platform, runtime.GOOS))
v.HostSpecific = false
}

if v.platform == "windows" {
if v.spec.Windows == nil {
errs = multierror.Append(errs,
Expand Down
8 changes: 6 additions & 2 deletions validation/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"fmt"
"os/exec"
"runtime"

"github.com/mndrix/tap-go"
rspecs "github.com/opencontainers/runtime-spec/specs-go"
Expand All @@ -16,7 +17,10 @@ func main() {
t := tap.New()
t.Header(0)

g := generate.New()
g, err := generate.New(runtime.GOOS)
if err != nil {
util.Fatal(err)
}
g.SetRootPath(".")
g.SetProcessArgs([]string{"ls"})

Expand Down Expand Up @@ -49,7 +53,7 @@ func main() {

for _, c := range cases {
r.SetID(c.id)
err := r.Create()
err = r.Create()
t.Ok((err == nil) == c.errExpected, c.err.(*specerror.Error).Err.Err.Error())
diagnostic := map[string]string{
"reference": c.err.(*specerror.Error).Err.Reference,
Expand Down
7 changes: 5 additions & 2 deletions validation/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import (
)

func main() {
g := util.GetDefaultGenerator()
err := util.RuntimeInsideValidate(g, nil)
g, err := util.GetDefaultGenerator()
if err != nil {
util.Fatal(err)
}
err = util.RuntimeInsideValidate(g, nil)
if err != nil {
util.Fatal(err)
}
Expand Down
12 changes: 9 additions & 3 deletions validation/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,15 @@ func main() {
}
defer os.RemoveAll(bundleDir)

stoppedConfig := util.GetDefaultGenerator()
stoppedConfig, err := util.GetDefaultGenerator()
if err != nil {
util.Fatal(err)
}
stoppedConfig.SetProcessArgs([]string{"true"})
runningConfig := util.GetDefaultGenerator()
runningConfig, err := util.GetDefaultGenerator()
if err != nil {
util.Fatal(err)
}
runningConfig.SetProcessArgs([]string{"sleep", "30"})
containerID := uuid.NewV4().String()
testRuntime, _ := util.NewRuntime(util.RuntimeCommand, bundleDir)
Expand Down Expand Up @@ -67,7 +73,7 @@ func main() {
if c.effectCheck {
// waiting for the error of State, just in case the delete operation takes time
util.WaitingForStatus(testRuntime, util.LifecycleActionNone, time.Second*10, time.Second*1)
_, err := testRuntime.State()
_, err = testRuntime.State()
// err == nil means the 'delete' operation does NOT take effect
util.SpecErrorOK(t, err == nil, specerror.NewError(specerror.DeleteNonStopHaveNoEffect, fmt.Errorf("attempting to `delete` a container that is not `stopped` MUST have no effect on the container"), rspecs.Version), err)
}
Expand Down
Loading