// TestNonRootReadInfo tests that non-root users that can do rkt list, rkt image list. func TestNonRootReadInfo(t *testing.T) { if !common.SupportsUserNS() { t.Skip("User namespaces are not supported on this host.") } if err := checkUserNS(); err != nil { t.Skip("User namespaces don't work on this host.") } ctx := testutils.NewRktRunCtx() defer ctx.Cleanup() gid, err := common.LookupGid(common.RktGroup) if err != nil { t.Skipf("Skipping the test because there's no %q group", common.RktGroup) } if err := ctx.SetupDataDir(); err != nil { t.Fatalf("failed to setup data dir: %v", err) } // Launch some pods, this creates the environment for later testing. imgs := []struct { name string msg string exitCode string imgFile string }{ {name: "inspect-1", msg: "foo-1", exitCode: "1"}, {name: "inspect-2", msg: "foo-2", exitCode: "2"}, {name: "inspect-3", msg: "foo-3", exitCode: "3"}, } for i, img := range imgs { imgName := fmt.Sprintf("rkt-%s.aci", img.name) imgs[i].imgFile = patchTestACI(imgName, fmt.Sprintf("--name=%s", img.name), fmt.Sprintf("--exec=/inspect --print-msg=%s --exit-code=%s", img.msg, img.exitCode)) defer os.Remove(imgs[i].imgFile) } runCmds := []string{ // Run with overlay, without private-users. fmt.Sprintf("%s --insecure-options=image run --mds-register=false %s", ctx.Cmd(), imgs[0].imgFile), // Run without overlay, without private-users. fmt.Sprintf("%s --insecure-options=image run --no-overlay --mds-register=false %s", ctx.Cmd(), imgs[1].imgFile), // Run without overlay, with private-users. fmt.Sprintf("%s --insecure-options=image run --no-overlay --private-users --mds-register=false %s", ctx.Cmd(), imgs[2].imgFile), } for i, cmd := range runCmds { t.Logf("#%d: Running %s", i, cmd) runRktAndCheckOutput(t, cmd, imgs[i].msg, false) } imgListCmd := fmt.Sprintf("%s image list", ctx.Cmd()) t.Logf("Running %s", imgListCmd) runRktAsGidAndCheckOutput(t, imgListCmd, "inspect-", false, gid) }
func TestUserns(t *testing.T) { if !common.SupportsUserNS() { t.Skip("User namespaces are not supported on this host.") } if err := checkUserNS(); err != nil { t.Skip("User namespaces don't work on this host.") } // we need CAP_SYS_PTRACE to read /proc/1/root image := patchTestACI("rkt-inspect-stat.aci", "--exec=/inspect --stat-file", "--capability=CAP_SYS_PTRACE") defer os.Remove(image) ctx := testutils.NewRktRunCtx() defer ctx.Cleanup() for i, tt := range usernsTests { for _, userNsOpt := range []string{"", "--private-users"} { runCmd := tt.runCmd runCmd = strings.Replace(runCmd, "^IMAGE^", image, -1) runCmd = strings.Replace(runCmd, "^RKT_BIN^", ctx.Cmd(), -1) runCmd = strings.Replace(runCmd, "^FILE^", tt.file, -1) runCmd = strings.Replace(runCmd, "^USERNS^", userNsOpt, -1) if userNsOpt == "--private-users" { t.Logf("Running 'run' test #%v: %v", i, runCmd) child, err := gexpect.Spawn(runCmd) if err != nil { t.Fatalf("Cannot exec rkt #%v: %v", i, err) } expectedResult := tt.file + `: mode: (\w+.\w+.\w+)` result, _, err := expectRegexWithOutput(child, expectedResult) if err != nil || result[1] != tt.expectMode { t.Fatalf("Expected %q but not found: %v", tt.expectMode, result) } expectedResult = tt.file + `: user: (\d)` result, _, err = expectRegexWithOutput(child, expectedResult) if err != nil || result[0] == tt.expectUid { t.Fatalf("Expected %q but not found: %v", tt.expectUid, result) } expectedResult = tt.file + `: group: (\d)` result, _, err = expectRegexWithOutput(child, expectedResult) if err != nil || result[0] == tt.expectGid { t.Fatalf("Expected %q but not found: %v", tt.expectGid, result) } err = child.Wait() if err != nil { t.Fatalf("rkt didn't terminate correctly: %v", err) } ctx.Reset() } } } }
func TestUserns(t *testing.T) { if !common.SupportsUserNS() { t.Skip("User namespaces are not supported on this host.") } if err := checkUserNS(); err != nil { t.Skip("User namespaces don't work on this host.") } image := patchTestACI("rkt-inspect-stat.aci", "--exec=/inspect --stat-file") defer os.Remove(image) ctx := testutils.NewRktRunCtx() defer ctx.Cleanup() for i, tt := range usernsTests { for _, userNsOpt := range []string{"", "--private-users"} { runCmd := tt.runCmd runCmd = strings.Replace(runCmd, "^IMAGE^", image, -1) runCmd = strings.Replace(runCmd, "^RKT_BIN^", ctx.Cmd(), -1) runCmd = strings.Replace(runCmd, "^FILE^", tt.file, -1) runCmd = strings.Replace(runCmd, "^USERNS^", userNsOpt, -1) t.Logf("Running 'run' test #%v: %v", i, runCmd) child, err := gexpect.Spawn(runCmd) if err != nil { t.Fatalf("Cannot exec rkt #%v: %v", i, err) } err = expectWithOutput(child, tt.file+": mode: "+tt.expectMode) if err != nil { t.Fatalf("Expected %q but not found: %v", tt.expectMode, err) } err = expectWithOutput(child, tt.file+": user: "******"Expected %q but not found: %v", tt.expectUid, err) } err = expectWithOutput(child, tt.file+": group: "+tt.expectGid) if err != nil { t.Fatalf("Expected %q but not found: %v", tt.expectGid, err) } err = child.Wait() if err != nil { t.Fatalf("rkt didn't terminate correctly: %v", err) } ctx.Reset() } } }
func TestExport(t *testing.T) { testCases := []ExportTestCase{noOverlaySimpleTest} // Need to do both checks if common.SupportsUserNS() && checkUserNS() == nil { testCases = append(testCases, userNS) } if common.SupportsOverlay() { testCases = append(testCases, overlaySimpleTest) testCases = append(testCases, overlaySimulateReboot) } NewTestExport(testCases...).Execute(t) }
func TestExport(t *testing.T) { ctx := testutils.NewRktRunCtx() defer ctx.Cleanup() overlay := (common.SupportsOverlay() == nil) userns := (common.SupportsUserNS() && checkUserNS() == nil && !TestedFlavor.Kvm) for name, testCase := range exportTestCases { if testCase.NeedsOverlay && !overlay { t.Logf("TestExport/%v needs overlay, skipping", name) continue } if testCase.NeedsUserNS && !userns { t.Logf("TestExport/%v needs userns, skipping", name) continue } t.Logf("TestExport/%v", name) testCase.Execute(t, ctx) } }
func runRun(cmd *cobra.Command, args []string) (exit int) { privateUsers := uid.NewBlankUidRange() err := parseApps(&rktApps, args, cmd.Flags(), true) if err != nil { stderr("run: error parsing app image arguments: %v", err) return 1 } if flagPrivateUsers { if !common.SupportsUserNS() { stderr("run: --private-users is not supported, kernel compiled without user namespace support") return 1 } privateUsers.SetRandomUidRange(uid.DefaultRangeCount) } if len(flagPorts) > 0 && !flagPrivateNet.Any() { stderr("--port flag requires --private-net") return 1 } if len(flagPodManifest) > 0 && (len(flagVolumes) > 0 || len(flagPorts) > 0 || flagInheritEnv || !flagExplicitEnv.IsEmpty() || rktApps.Count() > 0 || flagLocal) { stderr("conflicting flags set with --pod-manifest (see --help)") return 1 } if globalFlags.Dir == "" { log.Printf("dir unset - using temporary directory") var err error globalFlags.Dir, err = ioutil.TempDir("", "rkt") if err != nil { stderr("error creating temporary directory: %v", err) return 1 } } if flagInteractive && rktApps.Count() > 1 { stderr("run: interactive option only supports one image") return 1 } if rktApps.Count() < 1 && len(flagPodManifest) == 0 { stderr("run: must provide at least one image or specify the pod manifest") return 1 } s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("run: cannot open store: %v", err) return 1 } config, err := getConfig() if err != nil { stderr("run: cannot get configuration: %v", err) return 1 } fn := &finder{ imageActionData: imageActionData{ s: s, headers: config.AuthPerHost, dockerAuth: config.DockerCredentialsPerRegistry, insecureSkipVerify: globalFlags.InsecureSkipVerify, debug: globalFlags.Debug, }, local: flagLocal, withDeps: false, } s1img, err := getStage1Hash(s, flagStage1Image) if err != nil { stderr("%v", err) return 1 } fn.ks = getKeystore() fn.withDeps = true if err := fn.findImages(&rktApps); err != nil { stderr("%v", err) return 1 } p, err := newPod() if err != nil { stderr("Error creating new pod: %v", err) return 1 } // if requested, write out pod UUID early so "rkt rm" can // clean it up even if something goes wrong if flagUUIDFileSave != "" { if err := writeUUIDToFile(p.uuid, flagUUIDFileSave); err != nil { stderr("Error saving pod UUID to file: %v", err) return 1 } } processLabel, mountLabel, err := label.InitLabels(nil) if err != nil { stderr("Error initialising SELinux: %v", err) return 1 } cfg := stage0.CommonConfig{ MountLabel: mountLabel, ProcessLabel: processLabel, Store: s, Stage1Image: *s1img, UUID: p.uuid, Debug: globalFlags.Debug, } pcfg := stage0.PrepareConfig{ CommonConfig: cfg, UseOverlay: !flagNoOverlay && common.SupportsOverlay(), PrivateUsers: privateUsers, } if len(flagPodManifest) > 0 { pcfg.PodManifest = flagPodManifest } else { pcfg.Volumes = []types.Volume(flagVolumes) pcfg.Ports = []types.ExposedPort(flagPorts) pcfg.InheritEnv = flagInheritEnv pcfg.ExplicitEnv = flagExplicitEnv.Strings() pcfg.Apps = &rktApps } err = stage0.Prepare(pcfg, p.path(), p.uuid) if err != nil { stderr("run: error setting up stage0: %v", err) return 1 } // get the lock fd for run lfd, err := p.Fd() if err != nil { stderr("Error getting pod lock fd: %v", err) return 1 } // skip prepared by jumping directly to run, we own this pod if err := p.xToRun(); err != nil { stderr("run: unable to transition to run: %v", err) return 1 } rcfg := stage0.RunConfig{ CommonConfig: cfg, PrivateNet: flagPrivateNet, LockFd: lfd, Interactive: flagInteractive, MDSRegister: flagMDSRegister, LocalConfig: globalFlags.LocalConfigDir, } apps, err := p.getApps() if err != nil { stderr("run: cannot get the appList in the pod manifest: %v", err) return 1 } rcfg.Apps = apps stage0.Run(rcfg, p.path()) // execs, never returns return 1 }
func runPrepare(cmd *cobra.Command, args []string) (exit int) { var err error origStdout := os.Stdout privateUsers := uid.NewBlankUidRange() if flagQuiet { if os.Stdout, err = os.Open("/dev/null"); err != nil { stderr("prepare: unable to open /dev/null") return 1 } } if flagPrivateUsers { if !common.SupportsUserNS() { stderr("prepare: --private-users is not supported, kernel compiled without user namespace support") return 1 } privateUsers.SetRandomUidRange(uid.DefaultRangeCount) } if err = parseApps(&rktApps, args, cmd.Flags(), true); err != nil { stderr("prepare: error parsing app image arguments: %v", err) return 1 } if len(flagPodManifest) > 0 && (len(flagVolumes) > 0 || len(flagPorts) > 0 || flagInheritEnv || !flagExplicitEnv.IsEmpty() || flagLocal) { stderr("prepare: conflicting flags set with --pod-manifest (see --help)") return 1 } if rktApps.Count() < 1 && len(flagPodManifest) == 0 { stderr("prepare: must provide at least one image or specify the pod manifest") return 1 } if globalFlags.Dir == "" { log.Printf("dir unset - using temporary directory") globalFlags.Dir, err = ioutil.TempDir("", "rkt") if err != nil { stderr("prepare: error creating temporary directory: %v", err) return 1 } } s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("prepare: cannot open store: %v", err) return 1 } config, err := getConfig() if err != nil { stderr("prepare: cannot get configuration: %v", err) return 1 } fn := &finder{ imageActionData: imageActionData{ s: s, headers: config.AuthPerHost, dockerAuth: config.DockerCredentialsPerRegistry, insecureSkipVerify: globalFlags.InsecureSkipVerify, debug: globalFlags.Debug, }, local: flagLocal, withDeps: false, } s1img, err := getStage1Hash(s, flagStage1Image) if err != nil { stderr("prepare: %v", err) return 1 } fn.ks = getKeystore() fn.withDeps = true if err := fn.findImages(&rktApps); err != nil { stderr("%v", err) return 1 } p, err := newPod() if err != nil { stderr("prepare: error creating new pod: %v", err) return 1 } cfg := stage0.CommonConfig{ Store: s, Stage1Image: *s1img, UUID: p.uuid, Debug: globalFlags.Debug, } pcfg := stage0.PrepareConfig{ CommonConfig: cfg, UseOverlay: !flagNoOverlay && common.SupportsOverlay(), PrivateUsers: privateUsers, } if len(flagPodManifest) > 0 { pcfg.PodManifest = flagPodManifest } else { pcfg.Volumes = []types.Volume(flagVolumes) pcfg.Ports = []types.ExposedPort(flagPorts) pcfg.InheritEnv = flagInheritEnv pcfg.ExplicitEnv = flagExplicitEnv.Strings() pcfg.Apps = &rktApps } if err = stage0.Prepare(pcfg, p.path(), p.uuid); err != nil { stderr("prepare: error setting up stage0: %v", err) return 1 } if err := p.sync(); err != nil { stderr("prepare: error syncing pod data: %v", err) return 1 } if err := p.xToPrepared(); err != nil { stderr("prepare: error transitioning to prepared: %v", err) return 1 } os.Stdout = origStdout // restore output in case of --quiet stdout("%s", p.uuid.String()) return 0 }
func runRun(cmd *cobra.Command, args []string) (exit int) { privateUsers := user.NewBlankUidRange() err := parseApps(&rktApps, args, cmd.Flags(), true) if err != nil { stderr.PrintE("error parsing app image arguments", err) return 1 } if flagStoreOnly && flagNoStore { stderr.Print("both --store-only and --no-store specified") return 1 } if flagPrivateUsers { if !common.SupportsUserNS() { stderr.Print("--private-users is not supported, kernel compiled without user namespace support") return 1 } privateUsers.SetRandomUidRange(user.DefaultRangeCount) } if len(flagPorts) > 0 && flagNet.None() { stderr.Print("--port flag does not work with 'none' networking") return 1 } if len(flagPorts) > 0 && flagNet.Host() { stderr.Print("--port flag does not work with 'host' networking") return 1 } if flagMDSRegister && flagNet.None() { stderr.Print("--mds-register flag does not work with --net=none. Please use 'host', 'default' or an equivalent network") return 1 } if len(flagPodManifest) > 0 && (len(flagPorts) > 0 || rktApps.Count() > 0 || flagStoreOnly || flagNoStore || flagInheritEnv || !flagExplicitEnv.IsEmpty() || !flagEnvFromFile.IsEmpty() || (*appsVolume)(&rktApps).String() != "" || (*appMount)(&rktApps).String() != "" || (*appExec)(&rktApps).String() != "" || (*appUser)(&rktApps).String() != "" || (*appGroup)(&rktApps).String() != "" || (*appCapsRetain)(&rktApps).String() != "" || (*appCapsRemove)(&rktApps).String() != "") { stderr.Print("conflicting flags set with --pod-manifest (see --help)") return 1 } if flagInteractive && rktApps.Count() > 1 { stderr.Print("interactive option only supports one image") return 1 } if rktApps.Count() < 1 && len(flagPodManifest) == 0 { stderr.Print("must provide at least one image or specify the pod manifest") return 1 } s, err := imagestore.NewStore(storeDir()) if err != nil { stderr.PrintE("cannot open store", err) return 1 } ts, err := treestore.NewStore(treeStoreDir(), s) if err != nil { stderr.PrintE("cannot open treestore", err) return 1 } config, err := getConfig() if err != nil { stderr.PrintE("cannot get configuration", err) return 1 } s1img, err := getStage1Hash(s, ts, config) if err != nil { stderr.Error(err) return 1 } fn := &image.Finder{ S: s, Ts: ts, Ks: getKeystore(), Headers: config.AuthPerHost, DockerAuth: config.DockerCredentialsPerRegistry, InsecureFlags: globalFlags.InsecureFlags, Debug: globalFlags.Debug, TrustKeysFromHTTPS: globalFlags.TrustKeysFromHTTPS, StoreOnly: flagStoreOnly, NoStore: flagNoStore, WithDeps: true, } if err := fn.FindImages(&rktApps); err != nil { stderr.Error(err) return 1 } p, err := newPod() if err != nil { stderr.PrintE("error creating new pod", err) return 1 } // if requested, write out pod UUID early so "rkt rm" can // clean it up even if something goes wrong if flagUUIDFileSave != "" { if err := writeUUIDToFile(p.uuid, flagUUIDFileSave); err != nil { stderr.PrintE("error saving pod UUID to file", err) return 1 } } processLabel, mountLabel, err := label.InitLabels([]string{"mcsdir:/var/run/rkt/mcs"}) if err != nil { stderr.PrintE("error initialising SELinux", err) return 1 } p.mountLabel = mountLabel cfg := stage0.CommonConfig{ MountLabel: mountLabel, ProcessLabel: processLabel, Store: s, TreeStore: ts, Stage1Image: *s1img, UUID: p.uuid, Debug: globalFlags.Debug, } pcfg := stage0.PrepareConfig{ CommonConfig: &cfg, UseOverlay: !flagNoOverlay && common.SupportsOverlay() && common.FSSupportsOverlay(getDataDir()), PrivateUsers: privateUsers, SkipTreeStoreCheck: globalFlags.InsecureFlags.SkipOnDiskCheck(), } if len(flagPodManifest) > 0 { pcfg.PodManifest = flagPodManifest } else { pcfg.Ports = []types.ExposedPort(flagPorts) pcfg.InheritEnv = flagInheritEnv pcfg.ExplicitEnv = flagExplicitEnv.Strings() pcfg.EnvFromFile = flagEnvFromFile.Strings() pcfg.Apps = &rktApps } if globalFlags.Debug { stage0.InitDebug() } keyLock, err := lock.SharedKeyLock(lockDir(), common.PrepareLock) if err != nil { stderr.PrintE("cannot get shared prepare lock", err) return 1 } err = stage0.Prepare(pcfg, p.path(), p.uuid) if err != nil { stderr.PrintE("error setting up stage0", err) keyLock.Close() return 1 } keyLock.Close() // get the lock fd for run lfd, err := p.Fd() if err != nil { stderr.PrintE("error getting pod lock fd", err) return 1 } // skip prepared by jumping directly to run, we own this pod if err := p.xToRun(); err != nil { stderr.PrintE("unable to transition to run", err) return 1 } rktgid, err := common.LookupGid(common.RktGroup) if err != nil { stderr.Printf("group %q not found, will use default gid when rendering images", common.RktGroup) rktgid = -1 } rcfg := stage0.RunConfig{ CommonConfig: &cfg, Net: flagNet, LockFd: lfd, Interactive: flagInteractive, DNS: flagDNS, DNSSearch: flagDNSSearch, DNSOpt: flagDNSOpt, MDSRegister: flagMDSRegister, LocalConfig: globalFlags.LocalConfigDir, RktGid: rktgid, Hostname: flagHostname, } apps, err := p.getApps() if err != nil { stderr.PrintE("cannot get the appList in the pod manifest", err) return 1 } rcfg.Apps = apps stage0.Run(rcfg, p.path(), getDataDir()) // execs, never returns return 1 }
func runRun(cmd *cobra.Command, args []string) (exit int) { privateUsers := uid.NewBlankUidRange() err := parseApps(&rktApps, args, cmd.Flags(), true) if err != nil { stderr("run: error parsing app image arguments: %v", err) return 1 } if flagStoreOnly && flagNoStore { stderr("both --store-only and --no-store specified") return 1 } if flagPrivateUsers { if !common.SupportsUserNS() { stderr("run: --private-users is not supported, kernel compiled without user namespace support") return 1 } privateUsers.SetRandomUidRange(uid.DefaultRangeCount) } if len(flagPorts) > 0 && flagNet.None() { stderr("--port flag does not work with 'none' networking") return 1 } if len(flagPorts) > 0 && flagNet.Host() { stderr("--port flag does not work with 'host' networking") return 1 } if flagMDSRegister && flagNet.None() { stderr("--mds-register flag does not work with --net=none. Please use 'host', 'default' or an equivalent network") return 1 } if len(flagPodManifest) > 0 && (len(flagPorts) > 0 || flagInheritEnv || !flagExplicitEnv.IsEmpty() || rktApps.Count() > 0 || flagStoreOnly || flagNoStore) { stderr("conflicting flags set with --pod-manifest (see --help)") return 1 } if flagInteractive && rktApps.Count() > 1 { stderr("run: interactive option only supports one image") return 1 } if rktApps.Count() < 1 && len(flagPodManifest) == 0 { stderr("run: must provide at least one image or specify the pod manifest") return 1 } s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("run: cannot open store: %v", err) return 1 } config, err := getConfig() if err != nil { stderr("run: cannot get configuration: %v", err) return 1 } fn := &finder{ imageActionData: imageActionData{ s: s, headers: config.AuthPerHost, dockerAuth: config.DockerCredentialsPerRegistry, insecureSkipVerify: globalFlags.InsecureSkipVerify, debug: globalFlags.Debug, }, storeOnly: flagStoreOnly, noStore: flagNoStore, withDeps: false, } s1img, err := getStage1Hash(s, cmd) if err != nil { stderr("%v", err) return 1 } fn.ks = getKeystore() fn.withDeps = true if err := fn.findImages(&rktApps); err != nil { stderr("%v", err) return 1 } p, err := newPod() if err != nil { stderr("Error creating new pod: %v", err) return 1 } // if requested, write out pod UUID early so "rkt rm" can // clean it up even if something goes wrong if flagUUIDFileSave != "" { if err := writeUUIDToFile(p.uuid, flagUUIDFileSave); err != nil { stderr("Error saving pod UUID to file: %v", err) return 1 } } processLabel, mountLabel, err := label.InitLabels(nil) if err != nil { stderr("Error initialising SELinux: %v", err) return 1 } cfg := stage0.CommonConfig{ MountLabel: mountLabel, ProcessLabel: processLabel, Store: s, Stage1Image: *s1img, UUID: p.uuid, Debug: globalFlags.Debug, } pcfg := stage0.PrepareConfig{ CommonConfig: cfg, UseOverlay: !flagNoOverlay && common.SupportsOverlay(), PrivateUsers: privateUsers, } if len(flagPodManifest) > 0 { pcfg.PodManifest = flagPodManifest } else { pcfg.Ports = []types.ExposedPort(flagPorts) pcfg.InheritEnv = flagInheritEnv pcfg.ExplicitEnv = flagExplicitEnv.Strings() pcfg.Apps = &rktApps } if globalFlags.Debug { stage0.InitDebug() } keyLock, err := lock.SharedKeyLock(lockDir(), common.PrepareLock) if err != nil { stderr("rkt: cannot get shared prepare lock: %v", err) return 1 } err = stage0.Prepare(pcfg, p.path(), p.uuid) if err != nil { stderr("run: error setting up stage0: %v", err) keyLock.Close() return 1 } keyLock.Close() // get the lock fd for run lfd, err := p.Fd() if err != nil { stderr("Error getting pod lock fd: %v", err) return 1 } // skip prepared by jumping directly to run, we own this pod if err := p.xToRun(); err != nil { stderr("run: unable to transition to run: %v", err) return 1 } rktgid, err := common.LookupGid(common.RktGroup) if err != nil { stderr("run: group %q not found, will use default gid when rendering images", common.RktGroup) rktgid = -1 } rcfg := stage0.RunConfig{ CommonConfig: cfg, Net: flagNet, LockFd: lfd, Interactive: flagInteractive, MDSRegister: flagMDSRegister, LocalConfig: globalFlags.LocalConfigDir, RktGid: rktgid, } apps, err := p.getApps() if err != nil { stderr("run: cannot get the appList in the pod manifest: %v", err) return 1 } rcfg.Apps = apps stage0.Run(rcfg, p.path(), globalFlags.Dir) // execs, never returns return 1 }
func runPrepare(cmd *cobra.Command, args []string) (exit int) { var err error origStdout := os.Stdout privateUsers := uid.NewBlankUidRange() if flagQuiet { if os.Stdout, err = os.Open("/dev/null"); err != nil { stderr("prepare: unable to open /dev/null: %v", err) return 1 } } if flagStoreOnly && flagNoStore { stderr("both --store-only and --no-store specified") return 1 } if flagPrivateUsers { if !common.SupportsUserNS() { stderr("prepare: --private-users is not supported, kernel compiled without user namespace support") return 1 } privateUsers.SetRandomUidRange(uid.DefaultRangeCount) } if err = parseApps(&rktApps, args, cmd.Flags(), true); err != nil { stderr("prepare: error parsing app image arguments: %v", err) return 1 } if len(flagPodManifest) > 0 && (len(flagPorts) > 0 || flagInheritEnv || !flagExplicitEnv.IsEmpty() || flagStoreOnly || flagNoStore) { stderr("prepare: conflicting flags set with --pod-manifest (see --help)") return 1 } if rktApps.Count() < 1 && len(flagPodManifest) == 0 { stderr("prepare: must provide at least one image or specify the pod manifest") return 1 } s, err := store.NewStore(getDataDir()) if err != nil { stderr("prepare: cannot open store: %v", err) return 1 } config, err := getConfig() if err != nil { stderr("prepare: cannot get configuration: %v", err) return 1 } s1img, err := getStage1Hash(s, cmd) if err != nil { stderr("prepare: %v", err) return 1 } fn := &image.Finder{ S: s, Ks: getKeystore(), Headers: config.AuthPerHost, DockerAuth: config.DockerCredentialsPerRegistry, InsecureFlags: globalFlags.InsecureFlags, Debug: globalFlags.Debug, TrustKeysFromHttps: globalFlags.TrustKeysFromHttps, StoreOnly: flagStoreOnly, NoStore: flagNoStore, WithDeps: true, } if err := fn.FindImages(&rktApps); err != nil { stderr("prepare: %v", err) return 1 } p, err := newPod() if err != nil { stderr("prepare: error creating new pod: %v", err) return 1 } cfg := stage0.CommonConfig{ Store: s, Stage1Image: *s1img, UUID: p.uuid, Debug: globalFlags.Debug, } pcfg := stage0.PrepareConfig{ CommonConfig: &cfg, UseOverlay: !flagNoOverlay && common.SupportsOverlay(), PrivateUsers: privateUsers, } if len(flagPodManifest) > 0 { pcfg.PodManifest = flagPodManifest } else { pcfg.Ports = []types.ExposedPort(flagPorts) pcfg.InheritEnv = flagInheritEnv pcfg.ExplicitEnv = flagExplicitEnv.Strings() pcfg.Apps = &rktApps } if globalFlags.Debug { stage0.InitDebug() } keyLock, err := lock.SharedKeyLock(lockDir(), common.PrepareLock) if err != nil { stderr("rkt: cannot get shared prepare lock: %v", err) return 1 } if err = stage0.Prepare(pcfg, p.path(), p.uuid); err != nil { stderr("prepare: error setting up stage0: %v", err) keyLock.Close() return 1 } keyLock.Close() if err := p.sync(); err != nil { stderr("prepare: error syncing pod data: %v", err) return 1 } if err := p.xToPrepared(); err != nil { stderr("prepare: error transitioning to prepared: %v", err) return 1 } os.Stdout = origStdout // restore output in case of --quiet stdout("%s", p.uuid.String()) return 0 }
func runPrepare(cmd *cobra.Command, args []string) (exit int) { var err error origStdout := os.Stdout privateUsers := user.NewBlankUidRange() if flagQuiet { if os.Stdout, err = os.Open("/dev/null"); err != nil { stderr.PrintE("unable to open /dev/null", err) return 254 } } if flagStoreOnly && flagNoStore { stderr.Print("both --store-only and --no-store specified") return 254 } if flagPrivateUsers { if !common.SupportsUserNS() { stderr.Print("--private-users is not supported, kernel compiled without user namespace support") return 254 } privateUsers.SetRandomUidRange(user.DefaultRangeCount) } if err = parseApps(&rktApps, args, cmd.Flags(), true); err != nil { stderr.PrintE("error parsing app image arguments", err) return 254 } if len(flagPodManifest) > 0 && (rktApps.Count() > 0 || (*appsVolume)(&rktApps).String() != "" || (*appMount)(&rktApps).String() != "" || len(flagPorts) > 0 || flagStoreOnly || flagNoStore || flagInheritEnv || !flagExplicitEnv.IsEmpty() || !flagEnvFromFile.IsEmpty()) { stderr.Print("conflicting flags set with --pod-manifest (see --help)") return 254 } if rktApps.Count() < 1 && len(flagPodManifest) == 0 { stderr.Print("must provide at least one image or specify the pod manifest") return 254 } s, err := imagestore.NewStore(storeDir()) if err != nil { stderr.PrintE("cannot open store", err) return 254 } ts, err := treestore.NewStore(treeStoreDir(), s) if err != nil { stderr.PrintE("cannot open treestore", err) return 254 } config, err := getConfig() if err != nil { stderr.PrintE("cannot get configuration", err) return 254 } s1img, err := getStage1Hash(s, ts, config) if err != nil { stderr.Error(err) return 254 } fn := &image.Finder{ S: s, Ts: ts, Ks: getKeystore(), Headers: config.AuthPerHost, DockerAuth: config.DockerCredentialsPerRegistry, InsecureFlags: globalFlags.InsecureFlags, Debug: globalFlags.Debug, TrustKeysFromHTTPS: globalFlags.TrustKeysFromHTTPS, StoreOnly: flagStoreOnly, NoStore: flagNoStore, WithDeps: true, } if err := fn.FindImages(&rktApps); err != nil { stderr.PrintE("error finding images", err) return 254 } p, err := pkgPod.NewPod(getDataDir()) if err != nil { stderr.PrintE("error creating new pod", err) return 254 } cfg := stage0.CommonConfig{ DataDir: getDataDir(), Store: s, TreeStore: ts, Stage1Image: *s1img, UUID: p.UUID, Debug: globalFlags.Debug, } ovlOk := true if err := common.PathSupportsOverlay(getDataDir()); err != nil { if oerr, ok := err.(common.ErrOverlayUnsupported); ok { stderr.Printf("disabling overlay support: %q", oerr.Error()) ovlOk = false } else { stderr.PrintE("error determining overlay support", err) return 254 } } pcfg := stage0.PrepareConfig{ CommonConfig: &cfg, UseOverlay: !flagNoOverlay && ovlOk, PrivateUsers: privateUsers, SkipTreeStoreCheck: globalFlags.InsecureFlags.SkipOnDiskCheck(), } if len(flagPodManifest) > 0 { pcfg.PodManifest = flagPodManifest } else { pcfg.Ports = []types.ExposedPort(flagPorts) pcfg.InheritEnv = flagInheritEnv pcfg.ExplicitEnv = flagExplicitEnv.Strings() pcfg.EnvFromFile = flagEnvFromFile.Strings() pcfg.Apps = &rktApps } if globalFlags.Debug { stage0.InitDebug() } keyLock, err := lock.SharedKeyLock(lockDir(), common.PrepareLock) if err != nil { stderr.PrintE("cannot get shared prepare lock", err) return 254 } if err = stage0.Prepare(pcfg, p.Path(), p.UUID); err != nil { stderr.PrintE("error setting up stage0", err) keyLock.Close() return 254 } keyLock.Close() if err := p.Sync(); err != nil { stderr.PrintE("error syncing pod data", err) return 254 } if err := p.ToPrepared(); err != nil { stderr.PrintE("error transitioning to prepared", err) return 254 } os.Stdout = origStdout // restore output in case of --quiet stdout.Printf("%s", p.UUID.String()) return 0 }
func TestAppUserGroup(t *testing.T) { imageDummy := patchTestACI("rkt-inspect-dummy.aci", "--name=dummy") defer os.Remove(imageDummy) supportsUserNS := common.SupportsUserNS() && checkUserNS() == nil for _, tt := range []struct { imageParams []string rktParams string expected string }{ { expected: "User: uid=0 euid=0 gid=0 egid=0", }, { rktParams: "--user=200", expected: "User: uid=200 euid=200 gid=0 egid=0", }, { rktParams: "--group=300", expected: "User: uid=0 euid=0 gid=300 egid=300", }, { rktParams: "--user=200 --group=300", expected: "User: uid=200 euid=200 gid=300 egid=300", }, { rktParams: "--user=user1 --group=300", expected: "User: uid=1000 euid=1000 gid=300 egid=300", }, { rktParams: "--user=200 --group=group1", expected: "User: uid=200 euid=200 gid=100 egid=100", }, { imageParams: []string{"--user=400", "--group=500"}, expected: "User: uid=400 euid=400 gid=500 egid=500", }, { imageParams: []string{"--user=400", "--group=500"}, rktParams: "--user=200", expected: "User: uid=200 euid=200 gid=500 egid=500", }, { imageParams: []string{"--user=400", "--group=500"}, rktParams: "--group=300", expected: "User: uid=400 euid=400 gid=300 egid=300", }, { imageParams: []string{"--user=400", "--group=500"}, rktParams: "--user=200 --group=300", expected: "User: uid=200 euid=200 gid=300 egid=300", }, { imageParams: []string{"--user=400", "--group=500"}, rktParams: "--user=user1 --group=group1", expected: "User: uid=1000 euid=1000 gid=100 egid=100", }, { imageParams: []string{"--user=root", "--group=root"}, expected: "User: uid=0 euid=0 gid=0 egid=0", }, { rktParams: "--user=root --group=root", expected: "User: uid=0 euid=0 gid=0 egid=0", }, { rktParams: "--user=/inspect --group=/inspect", expected: "User: uid=0 euid=0 gid=0 egid=0", }, } { func() { ctx := testutils.NewRktRunCtx() defer ctx.Cleanup() tt.imageParams = append(tt.imageParams, "--exec=/inspect --print-user") image := patchTestACI("rkt-inspect-user-group.aci", tt.imageParams...) defer os.Remove(image) userNSOpts := []string{""} if supportsUserNS { userNSOpts = append(userNSOpts, "--private-users --no-overlay") } for _, userNSOpt := range userNSOpts { // run the user/group overriden app first rktCmd := fmt.Sprintf( "%s --debug --insecure-options=image run %s %s %s %s", ctx.Cmd(), userNSOpt, image, tt.rktParams, imageDummy, ) runRktAndCheckOutput(t, rktCmd, tt.expected, false) // run the user/group overriden app last rktCmd = fmt.Sprintf( "%s --debug --insecure-options=image run %s %s %s %s", ctx.Cmd(), userNSOpt, imageDummy, image, tt.rktParams, ) runRktAndCheckOutput(t, rktCmd, tt.expected, false) } }() } }