Skip to content
Merged
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
71 changes: 49 additions & 22 deletions validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path"
"reflect"
"regexp"
"strings"
"unicode"
"unicode/utf8"

"github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
Expand Down Expand Up @@ -53,23 +56,24 @@ var bundleValidateCommand = cli.Command{
logrus.Fatal(err)
}

sf, err := os.Open(path.Join(inputPath, "config.json"))
configPath := path.Join(inputPath, "config.json")
content, err := ioutil.ReadFile(configPath)
if err != nil {
logrus.Fatal(err)
}

defer sf.Close()

if !utf8.Valid(content) {
logrus.Fatalf("%q is not encoded in UTF-8", configPath)
}
var spec rspec.Spec
if err = json.NewDecoder(sf).Decode(&spec); err != nil {
if err = json.Unmarshal(content, &spec); err != nil {
logrus.Fatal(err)
}

rootfsPath := path.Join(inputPath, spec.Root.Path)
if fi, err := os.Stat(rootfsPath); err != nil {
logrus.Fatalf("Cannot find the rootfs: %v", rootfsPath)
logrus.Fatalf("Cannot find the root path %q", rootfsPath)
} else if !fi.IsDir() {
logrus.Fatalf("Rootfs: %v is not a directory.", spec.Root.Path)
logrus.Fatalf("root path %q is not a directory.", spec.Root.Path)
}

bundleValidate(spec, rootfsPath)
Expand All @@ -89,17 +93,17 @@ func bundleValidate(spec rspec.Spec, rootfs string) {
func checkSemVer(version string) {
re, _ := regexp.Compile("^(\\d+)?\\.(\\d+)?\\.(\\d+)?$")
if ok := re.Match([]byte(version)); !ok {
logrus.Fatalf("%s is not a valid version format, please read 'SemVer v2.0.0'", version)
logrus.Fatalf("%q is not a valid version format, please read 'SemVer v2.0.0'", version)
}
}

func checkMounts(mounts []rspec.Mount, rootfs string) {
for _, mount := range mounts {
rootfsPath := path.Join(rootfs, mount.Destination)
if fi, err := os.Stat(rootfsPath); err != nil {
logrus.Fatalf("Cannot find the mount point: %v", rootfsPath)
destPath := path.Join(rootfs, mount.Destination)
if fi, err := os.Stat(destPath); err != nil {
logrus.Fatalf("Cannot find the mount destination %q", destPath)
} else if !fi.IsDir() {
logrus.Fatalf("Mount point: %v is not a directory.", rootfsPath)
logrus.Fatalf("Mount destination %q is not a directory.", destPath)
}
}
}
Expand All @@ -122,23 +126,33 @@ func checkPlatform(platform rspec.Platform) {
return
}
}
logrus.Fatalf("Combination of '%s' and '%s' is invalid.", platform.OS, platform.Arch)
logrus.Fatalf("Combination of %q and %q is invalid.", platform.OS, platform.Arch)
}
}
logrus.Fatalf("Operation system '%s' of the bundle is not supported yet.", platform.OS)
logrus.Fatalf("Operation system %q of the bundle is not supported yet.", platform.OS)
}

func checkProcess(process rspec.Process, rootfs string) {
if !path.IsAbs(process.Cwd) {
logrus.Fatalf("cwd %q is not an absolute path", process.Cwd)
}

for _, env := range process.Env {
if !envValid(env) {
logrus.Fatalf("env %q should be in the form of 'key=value'. The left hand side must consist solely of letters, digits, and underscores '_'.", env)
}
}

for index := 0; index < len(process.Capabilities); index++ {
capability := process.Capabilities[index]
if !capValid(capability) {
logrus.Fatalf("%s is not valid, man capabilities(7)", process.Capabilities[index])
logrus.Fatalf("capability %q is not valid, man capabilities(7)", process.Capabilities[index])
}
}

for index := 0; index < len(process.Rlimits); index++ {
if !rlimitValid(process.Rlimits[index].Type) {
logrus.Fatalf("Rlimit %v is invalid.", process.Rlimits[index])
logrus.Fatalf("rlimit type %q is invalid.", process.Rlimits[index].Type)
}
}

Expand All @@ -162,13 +176,13 @@ func checkLinux(spec rspec.Linux, rootfs string) {

for index := 0; index < len(spec.Namespaces); index++ {
if !namespaceValid(spec.Namespaces[index]) {
logrus.Fatalf("Namespace %s is invalid.", spec.Namespaces[index])
logrus.Fatalf("namespace %v is invalid.", spec.Namespaces[index])
}
}

for index := 0; index < len(spec.Devices); index++ {
if !deviceValid(spec.Devices[index]) {
logrus.Fatalf("Device %s is invalid.", spec.Devices[index].Path)
logrus.Fatalf("device %v is invalid.", spec.Devices[index])
}
}

Expand All @@ -185,17 +199,17 @@ func checkLinux(spec rspec.Linux, rootfs string) {
case "shared":
case "rshared":
default:
logrus.Fatalf("rootfs-propagation must be empty or one of private|rprivate|slave|rslave|shared|rshared")
logrus.Fatalf("rootfsPropagation must be empty or one of \"private|rprivate|slave|rslave|shared|rshared\"")
}
}

func checkSeccomp(s rspec.Seccomp) {
if !seccompActionValid(s.DefaultAction) {
logrus.Fatalf("Seccomp.DefaultAction is invalid.")
logrus.Fatalf("seccomp defaultAction %q is invalid.", s.DefaultAction)
}
for index := 0; index < len(s.Syscalls); index++ {
if !syscallValid(s.Syscalls[index]) {
logrus.Fatalf("Syscall action is invalid.")
logrus.Fatalf("syscall %v is invalid.", s.Syscalls[index])
}
}
for index := 0; index < len(s.Architectures); index++ {
Expand All @@ -212,11 +226,24 @@ func checkSeccomp(s rspec.Seccomp) {
case rspec.ArchMIPSEL64:
case rspec.ArchMIPSEL64N32:
default:
logrus.Fatalf("Seccomp.Architecture [%s] is invalid", s.Architectures[index])
logrus.Fatalf("seccomp architecture %q is invalid", s.Architectures[index])
}
}
}

func envValid(env string) bool {
items := strings.Split(env, "=")
if len(items) < 2 {
return false
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple equals are valid (e.g. LS_COLORS=rs=0:di=01;34:…).

for _, ch := range strings.TrimSpace(items[0]) {
if !unicode.IsDigit(ch) && !unicode.IsLetter(ch) && ch != '_' {
return false
}
}
return true
}

func capValid(capability string) bool {
for _, val := range defaultCaps {
if val == capability {
Expand Down