Exemple #1
0
Fichier : pod.go Projet : nhlfr/rkt
// generateDeviceAllows generates a DeviceAllow= line for an app.
// To make it work, the path needs to start with "/dev" but the device won't
// exist inside the container. So for a given mount, if the volume is a device
// node, we create a symlink to its target in "/rkt/volumes". Later,
// prepare-app will copy those to "/dev/.rkt/" so that's what we use in the
// DeviceAllow= line.
func generateDeviceAllows(root string, appName types.ACName, mountPoints []types.MountPoint, mounts []mountWrapper, vols map[types.ACName]types.Volume, uidRange *user.UidRange) ([]string, error) {
	var devAllow []string

	rktVolumeLinksPath := filepath.Join(root, "rkt", "volumes")
	if err := os.MkdirAll(rktVolumeLinksPath, 0600); err != nil {
		return nil, err
	}
	if err := user.ShiftFiles([]string{rktVolumeLinksPath}, uidRange); err != nil {
		return nil, err
	}

	for _, m := range mounts {
		v := vols[m.Volume]
		if v.Kind != "host" {
			continue
		}
		if fileutil.IsDeviceNode(v.Source) {
			mode := "r"
			if !IsMountReadOnly(v, mountPoints) {
				mode += "w"
			}

			tgt := filepath.Join(common.RelAppRootfsPath(appName), m.Path)
			// the DeviceAllow= line needs the link path in /dev/.rkt/
			linkRel := filepath.Join("/dev/.rkt", v.Name.String())
			// the real link should be in /rkt/volumes for now
			link := filepath.Join(rktVolumeLinksPath, v.Name.String())

			err := os.Symlink(tgt, link)
			// if the link already exists, we don't need to do anything
			if err != nil && !os.IsExist(err) {
				return nil, err
			}

			devAllow = append(devAllow, linkRel+" "+mode)
		}
	}

	return devAllow, nil
}
Exemple #2
0
// WriteEnvFile creates an environment file for given app name, the minimum
// required environment variables by the appc spec will be set to sensible
// defaults here if they're not provided by env.
func WriteEnvFile(env types.Environment, uidRange *user.UidRange, envFilePath string) error {
	ef := bytes.Buffer{}

	for dk, dv := range defaultEnv {
		if _, exists := env.Get(dk); !exists {
			fmt.Fprintf(&ef, "%s=%s\n", dk, dv)
		}
	}

	for _, e := range env {
		fmt.Fprintf(&ef, "%s=%s\n", e.Name, e.Value)
	}

	if err := ioutil.WriteFile(envFilePath, ef.Bytes(), 0644); err != nil {
		return err
	}

	if err := user.ShiftFiles([]string{envFilePath}, uidRange); err != nil {
		return err
	}

	return nil
}
Exemple #3
0
// generateSysusers generates systemd sysusers files for a given app so that
// corresponding entries in /etc/passwd and /etc/group are created in stage1.
// This is needed to use the "User="******"Group=" options in the systemd
// service files of apps.
// If there're several apps defining the same UIDs/GIDs, systemd will take care
// of only generating one /etc/{passwd,group} entry
func generateSysusers(p *stage1commontypes.Pod, ra *schema.RuntimeApp, uid_ int, gid_ int, uidRange *user.UidRange) error {
	var toShift []string

	app := ra.App
	appName := ra.Name

	sysusersDir := path.Join(common.Stage1RootfsPath(p.Root), "usr/lib/sysusers.d")
	toShift = append(toShift, sysusersDir)
	if err := os.MkdirAll(sysusersDir, 0755); err != nil {
		return err
	}

	gids := append(app.SupplementaryGIDs, gid_)

	// Create the Unix user and group
	var sysusersConf []string

	for _, g := range gids {
		groupname := "gen" + strconv.Itoa(g)
		sysusersConf = append(sysusersConf, fmt.Sprintf("g %s %d\n", groupname, g))
	}

	username := "******" + strconv.Itoa(uid_)
	sysusersConf = append(sysusersConf, fmt.Sprintf("u %s %d \"%s\"\n", username, uid_, username))

	sysusersFile := path.Join(common.Stage1RootfsPath(p.Root), "usr/lib/sysusers.d", ServiceUnitName(appName)+".conf")
	toShift = append(toShift, sysusersFile)
	if err := ioutil.WriteFile(sysusersFile, []byte(strings.Join(sysusersConf, "\n")), 0640); err != nil {
		return err
	}

	if err := user.ShiftFiles(toShift, uidRange); err != nil {
		return err
	}

	return nil
}