Example #1
0
File: manifest.go Project: nak3/rkt
// parseSeccompArgs parses seccomp mode and set CLI flags, preparing an
// appropriate seccomp isolator.
func parseSeccompArgs(patchSeccompMode string, patchSeccompSet string) (*types.Isolator, error) {
	// Parse mode flag and additional keyed arguments.
	var errno, mode string
	args := strings.Split(patchSeccompMode, ",")
	for _, a := range args {
		kv := strings.Split(a, "=")
		switch len(kv) {
		case 1:
			// mode, either "remove" or "retain"
			mode = kv[0]
		case 2:
			// k=v argument, only "errno" allowed for now
			if kv[0] == "errno" {
				errno = kv[1]
			} else {
				return nil, fmt.Errorf("invalid seccomp-mode optional argument: %s", a)
			}
		default:
			return nil, fmt.Errorf("cannot parse seccomp-mode argument: %s", a)
		}
	}

	// Instantiate an Isolator with the content specified by the --seccomp-set parameter.
	var err error
	var seccomp types.AsIsolator
	switch mode {
	case "remove":
		seccomp, err = types.NewLinuxSeccompRemoveSet(errno, strings.Split(patchSeccompSet, ",")...)
	case "retain":
		seccomp, err = types.NewLinuxSeccompRetainSet(errno, strings.Split(patchSeccompSet, ",")...)
	default:
		err = fmt.Errorf("unknown seccomp mode %s", mode)
	}
	if err != nil {
		return nil, fmt.Errorf("cannot parse seccomp isolator: %s", err)
	}
	seccompIsolator, err := seccomp.AsIsolator()
	if err != nil {
		return nil, err
	}
	return seccompIsolator, nil
}
Example #2
0
File: run.go Project: nak3/rkt
// generatePodManifest creates the pod manifest from the command line input.
// It returns the pod manifest as []byte on success.
// This is invoked if no pod manifest is specified at the command line.
func generatePodManifest(cfg PrepareConfig, dir string) ([]byte, error) {
	pm := schema.PodManifest{
		ACKind: "PodManifest",
		Apps:   make(schema.AppList, 0),
	}

	v, err := types.NewSemVer(version.Version)
	if err != nil {
		return nil, errwrap.Wrap(errors.New("error creating version"), err)
	}
	pm.ACVersion = *v

	if err := cfg.Apps.Walk(func(app *apps.App) error {
		img := app.ImageID

		am, err := cfg.Store.GetImageManifest(img.String())
		if err != nil {
			return errwrap.Wrap(errors.New("error getting the manifest"), err)
		}
		appName, err := imageNameToAppName(am.Name)
		if err != nil {
			return errwrap.Wrap(errors.New("error converting image name to app name"), err)
		}

		if err := prepareAppImage(cfg, *appName, img, dir, cfg.UseOverlay); err != nil {
			return errwrap.Wrap(fmt.Errorf("error setting up image %s", img), err)
		}
		if pm.Apps.Get(*appName) != nil {
			return fmt.Errorf("error: multiple apps with name %s", am.Name)
		}
		if am.App == nil && app.Exec == "" {
			return fmt.Errorf("error: image %s has no app section and --exec argument is not provided", img)
		}
		ra := schema.RuntimeApp{
			// TODO(vc): leverage RuntimeApp.Name for disambiguating the apps
			Name: *appName,
			App:  am.App,
			Image: schema.RuntimeImage{
				Name:   &am.Name,
				ID:     img,
				Labels: am.Labels,
			},
			Annotations: am.Annotations,
			Mounts:      MergeMounts(cfg.Apps.Mounts, app.Mounts),
		}

		if execOverride := app.Exec; execOverride != "" {
			// Create a minimal App section if not present
			if am.App == nil {
				ra.App = &types.App{
					User:  strconv.Itoa(os.Getuid()),
					Group: strconv.Itoa(os.Getgid()),
				}
			}
			ra.App.Exec = []string{execOverride}
		}

		if execAppends := app.Args; execAppends != nil {
			ra.App.Exec = append(ra.App.Exec, execAppends...)
		}

		if memoryOverride := app.MemoryLimit; memoryOverride != nil {
			isolator := memoryOverride.AsIsolator()
			ra.App.Isolators = append(ra.App.Isolators, isolator)
		}

		if cpuOverride := app.CPULimit; cpuOverride != nil {
			isolator := cpuOverride.AsIsolator()
			ra.App.Isolators = append(ra.App.Isolators, isolator)
		}

		if app.CapsRetain != nil && app.CapsRemove != nil {
			return fmt.Errorf("error: cannot use both --caps-retain and --caps-remove on the same image")
		}

		// Delete existing caps isolators if the user wants to override
		// them with either --caps-retain or --caps-remove
		if app.CapsRetain != nil || app.CapsRemove != nil {
			for i := len(ra.App.Isolators) - 1; i >= 0; i-- {
				isolator := ra.App.Isolators[i]
				if _, ok := isolator.Value().(types.LinuxCapabilitiesSet); ok {
					ra.App.Isolators = append(ra.App.Isolators[:i],
						ra.App.Isolators[i+1:]...)
				}
			}
		}

		if capsRetain := app.CapsRetain; capsRetain != nil {
			isolator, err := capsRetain.AsIsolator()
			if err != nil {
				return err
			}
			ra.App.Isolators = append(ra.App.Isolators, *isolator)
		} else if capsRemove := app.CapsRemove; capsRemove != nil {
			isolator, err := capsRemove.AsIsolator()
			if err != nil {
				return err
			}
			ra.App.Isolators = append(ra.App.Isolators, *isolator)
		}

		// Override seccomp isolators via --seccomp CLI switch
		if app.SeccompFilter != "" {
			var is *types.Isolator
			mode, errno, set, err := app.SeccompOverride()
			if err != nil {
				return err
			}
			switch mode {
			case "retain":
				lss, err := types.NewLinuxSeccompRetainSet(errno, set...)
				if err != nil {
					return err
				}
				if is, err = lss.AsIsolator(); err != nil {
					return err
				}
			case "remove":
				lss, err := types.NewLinuxSeccompRemoveSet(errno, set...)
				if err != nil {
					return err
				}
				if is, err = lss.AsIsolator(); err != nil {
					return err
				}
			default:
				return apps.ErrInvalidSeccompMode
			}
			ra.App.Isolators.ReplaceIsolatorsByName(*is, []types.ACIdentifier{types.LinuxSeccompRemoveSetName, types.LinuxSeccompRetainSetName})
		}

		if user := app.User; user != "" {
			ra.App.User = user
		}

		if group := app.Group; group != "" {
			ra.App.Group = group
		}

		// loading the environment from the lowest priority to highest
		if cfg.InheritEnv {
			// Inherit environment does not override app image environment
			mergeEnvs(&ra.App.Environment, os.Environ(), false)
		}

		mergeEnvs(&ra.App.Environment, cfg.EnvFromFile, true)
		mergeEnvs(&ra.App.Environment, cfg.ExplicitEnv, true)
		pm.Apps = append(pm.Apps, ra)
		return nil
	}); err != nil {
		return nil, err
	}

	// TODO(jonboulle): check that app mountpoint expectations are
	// satisfied here, rather than waiting for stage1
	pm.Volumes = cfg.Apps.Volumes
	pm.Ports = cfg.Ports

	pmb, err := json.Marshal(pm)
	if err != nil {
		return nil, errwrap.Wrap(errors.New("error marshalling pod manifest"), err)
	}
	return pmb, nil
}
Example #3
0
// prepareIsolators merges the CLI app parameters with the manifest's app
func prepareIsolators(setup *apps.App, app *types.App) error {
	if memoryOverride := setup.MemoryLimit; memoryOverride != nil {
		isolator := memoryOverride.AsIsolator()
		app.Isolators = append(app.Isolators, isolator)
	}

	if cpuOverride := setup.CPULimit; cpuOverride != nil {
		isolator := cpuOverride.AsIsolator()
		app.Isolators = append(app.Isolators, isolator)
	}

	if cpuSharesOverride := setup.CPUShares; cpuSharesOverride != nil {
		isolator := cpuSharesOverride.AsIsolator()
		app.Isolators.ReplaceIsolatorsByName(isolator, []types.ACIdentifier{types.LinuxCPUSharesName})
	}

	if oomAdjOverride := setup.OOMScoreAdj; oomAdjOverride != nil {
		app.Isolators.ReplaceIsolatorsByName(oomAdjOverride.AsIsolator(), []types.ACIdentifier{types.LinuxOOMScoreAdjName})
	}

	if setup.CapsRetain != nil && setup.CapsRemove != nil {
		return fmt.Errorf("error: cannot use both --caps-retain and --caps-remove on the same image")
	}

	// Delete existing caps isolators if the user wants to override
	// them with either --caps-retain or --caps-remove
	if setup.CapsRetain != nil || setup.CapsRemove != nil {
		for i := len(app.Isolators) - 1; i >= 0; i-- {
			isolator := app.Isolators[i]
			if _, ok := isolator.Value().(types.LinuxCapabilitiesSet); ok {
				app.Isolators = append(app.Isolators[:i],
					app.Isolators[i+1:]...)
			}
		}
	}

	if capsRetain := setup.CapsRetain; capsRetain != nil {
		isolator, err := capsRetain.AsIsolator()
		if err != nil {
			return err
		}
		app.Isolators = append(app.Isolators, *isolator)
	} else if capsRemove := setup.CapsRemove; capsRemove != nil {
		isolator, err := capsRemove.AsIsolator()
		if err != nil {
			return err
		}
		app.Isolators = append(app.Isolators, *isolator)
	}

	// Override seccomp isolators via --seccomp CLI switch
	if setup.SeccompFilter != "" {
		var is *types.Isolator
		mode, errno, set, err := setup.SeccompOverride()
		if err != nil {
			return err
		}
		switch mode {
		case "retain":
			lss, err := types.NewLinuxSeccompRetainSet(errno, set...)
			if err != nil {
				return err
			}
			if is, err = lss.AsIsolator(); err != nil {
				return err
			}
		case "remove":
			lss, err := types.NewLinuxSeccompRemoveSet(errno, set...)
			if err != nil {
				return err
			}
			if is, err = lss.AsIsolator(); err != nil {
				return err
			}
		default:
			return apps.ErrInvalidSeccompMode
		}
		app.Isolators.ReplaceIsolatorsByName(*is, []types.ACIdentifier{types.LinuxSeccompRemoveSetName, types.LinuxSeccompRetainSetName})
	}
	return nil
}