func Test0Dot3Migration(t *testing.T) {
	// make a temporary directory and copy the fixture into it, since updating
	// and publishing will modify the files
	tmpDir, err := ioutil.TempDir("", "notary-backwards-compat-test")
	defer os.RemoveAll(tmpDir)
	require.NoError(t, err)
	require.NoError(t, recursiveCopy("../fixtures/compatibility/notary0.3", tmpDir))

	gun := "docker.com/notary0.3/samplerepo"
	passwd := "randompass"

	ts := fullTestServer(t)
	defer ts.Close()

	_, err = NewFileCachedNotaryRepository(tmpDir, gun, ts.URL, http.DefaultTransport,
		passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
	require.NoError(t, err, "error creating repo: %s", err)

	// check that root_keys and tuf_keys are gone and that all corect keys are present and have the correct headers
	files, _ := ioutil.ReadDir(filepath.Join(tmpDir, notary.PrivDir))
	require.Equal(t, files[0].Name(), "041b64dab281324ef2b62fd2d04f4758269e120ff063b7bc78709272821a0a02.key")
	targKey, err := os.OpenFile(filepath.Join(tmpDir, notary.PrivDir, "041b64dab281324ef2b62fd2d04f4758269e120ff063b7bc78709272821a0a02.key"), os.O_RDONLY, notary.PrivExecPerms)
	require.NoError(t, err)
	defer targKey.Close()
	targBytes, _ := ioutil.ReadAll(targKey)
	targString := string(targBytes)
	require.Contains(t, targString, "gun: docker.com/notary0.3/tst")
	require.Contains(t, targString, "role: targets")
	require.Equal(t, files[1].Name(), "85559599cf3cf681ff193f432a7ca6d128182bd1cfa8ede2c70761deac8bc2dc.key")
	snapKey, err := os.OpenFile(filepath.Join(tmpDir, notary.PrivDir, "85559599cf3cf681ff193f432a7ca6d128182bd1cfa8ede2c70761deac8bc2dc.key"), os.O_RDONLY, notary.PrivExecPerms)
	require.NoError(t, err)
	defer snapKey.Close()
	snapBytes, _ := ioutil.ReadAll(snapKey)
	snapString := string(snapBytes)
	require.Contains(t, snapString, "gun: docker.com/notary0.3/tst")
	require.Contains(t, snapString, "role: snapshot")
	require.Equal(t, files[2].Name(), "f4eaf871a74aa3b3a0ff95cef2455a1e4d461639f5625418e76756fc5c948690.key")
	rootKey, err := os.OpenFile(filepath.Join(tmpDir, notary.PrivDir, "f4eaf871a74aa3b3a0ff95cef2455a1e4d461639f5625418e76756fc5c948690.key"), os.O_RDONLY, notary.PrivExecPerms)
	require.NoError(t, err)
	defer rootKey.Close()
	rootBytes, _ := ioutil.ReadAll(rootKey)
	rootString := string(rootBytes)
	require.Contains(t, rootString, "role: root")
	require.NotContains(t, rootString, "gun")
	require.Equal(t, files[3].Name(), "fa842f66cac2dc898677a8660789dcff0e3b0b93b73f8952491f6493199936d3.key")
	delKey, err := os.OpenFile(filepath.Join(tmpDir, notary.PrivDir, "fa842f66cac2dc898677a8660789dcff0e3b0b93b73f8952491f6493199936d3.key"), os.O_RDONLY, notary.PrivExecPerms)
	require.NoError(t, err)
	defer delKey.Close()
	delBytes, _ := ioutil.ReadAll(delKey)
	delString := string(delBytes)
	require.Contains(t, delString, "role: targets/releases")
	require.NotContains(t, delString, "gun")
	require.Len(t, files, 4)
}
Example #2
0
// insufficient arguments produce an error before any parsing of configs happens
func TestInsufficientArgumentsReturnsErrorAndPrintsUsage(t *testing.T) {
	tempdir, err := ioutil.TempDir("", "empty-dir")
	require.NoError(t, err)
	defer os.RemoveAll(tempdir)

	for _, args := range exampleValidCommands {
		b := new(bytes.Buffer)
		cmd := NewNotaryCommand()
		cmd.SetOutput(b)

		arglist := strings.Fields(args)
		if args == "key list" || args == "key generate rsa" {
			// in these case, "key" or "key generate" are valid commands, so add an arg to them instead
			arglist = append(arglist, "extraArg")
		} else {
			arglist = arglist[:len(arglist)-1]
		}

		invalid := strings.Join(arglist, " ")

		cmd.SetArgs(append(
			[]string{"-c", filepath.Join(tempdir, "idonotexist.json"), "-d", tempdir}, arglist...))
		err = cmd.Execute()

		require.NotContains(t, err.Error(), "error opening config file", "running `notary %s`", invalid)
		// it's a usage error, so the usage is printed
		require.Contains(t, b.String(), "Usage:", "expected usage when running `notary %s`", invalid)
	}
}
Example #3
0
func TestStatusUnstageAndReset(t *testing.T) {
	setUp(t)
	tempBaseDir := tempDirWithConfig(t, "{}")
	defer os.RemoveAll(tempBaseDir)

	tc := &tufCommander{
		configGetter: func() (*viper.Viper, error) {
			v := viper.New()
			v.SetDefault("trust_dir", tempBaseDir)
			return v, nil
		},
	}

	// run a reset with an empty changelist and make sure it succeeds
	tc.resetAll = true
	err := tc.tufReset(&cobra.Command{}, []string{"gun"})
	require.NoError(t, err)

	// add some targets
	tc.sha256 = "88b76b34ab83a9e4d5abe3697950fb73f940aab1aa5b534f80cf9de9708942be"
	err = tc.tufAddByHash(&cobra.Command{}, []string{"gun", "test1", "100"})
	require.NoError(t, err)
	tc.sha256 = "4a7c203ce63b036a1999ea74eebd307c338368eb2b32218b722de6c5fdc7f016"
	err = tc.tufAddByHash(&cobra.Command{}, []string{"gun", "test2", "100"})
	require.NoError(t, err)
	tc.sha256 = "64bd0565907a6a55fc66fd828a71dbadd976fa875d0a3869f53d02eb8710ecb4"
	err = tc.tufAddByHash(&cobra.Command{}, []string{"gun", "test3", "100"})
	require.NoError(t, err)
	tc.sha256 = "9d9e890af64dd0f44b8a1538ff5fa0511cc31bf1ab89f3a3522a9a581a70fad8"
	err = tc.tufAddByHash(&cobra.Command{}, []string{"gun", "test4", "100"})
	require.NoError(t, err)

	out, err := runCommand(t, tempBaseDir, "status", "gun")
	require.NoError(t, err)
	require.Contains(t, out, "test1")
	require.Contains(t, out, "test2")
	require.Contains(t, out, "test3")
	require.Contains(t, out, "test4")

	_, err = runCommand(t, tempBaseDir, "reset", "gun", "-n", "-1,1,3,10")
	require.NoError(t, err)

	out, err = runCommand(t, tempBaseDir, "status", "gun")
	require.NoError(t, err)
	require.Contains(t, out, "test1")
	require.NotContains(t, out, "test2")
	require.Contains(t, out, "test3")
	require.NotContains(t, out, "test4")

	_, err = runCommand(t, tempBaseDir, "reset", "gun", "--all")
	require.NoError(t, err)

	out, err = runCommand(t, tempBaseDir, "status", "gun")
	require.NoError(t, err)
	require.NotContains(t, out, "test1")
	require.NotContains(t, out, "test2")
	require.NotContains(t, out, "test3")
	require.NotContains(t, out, "test4")

}
Example #4
0
// the config can provide all the TLS information necessary - the root ca file,
// the tls client files - they are all relative to the directory of the config
// file, and not the cwd, or absolute paths
func TestConfigFileTLSCanBeRelativeToConfigOrAbsolute(t *testing.T) {
	// Set up server that with a self signed cert
	var err error
	// add a handler for getting the root
	m := &recordingMetaStore{MemStorage: *storage.NewMemStorage()}
	s := httptest.NewUnstartedServer(setupServerHandler(m))
	s.TLS, err = tlsconfig.Server(tlsconfig.Options{
		CertFile:   "../../fixtures/notary-server.crt",
		KeyFile:    "../../fixtures/notary-server.key",
		CAFile:     "../../fixtures/root-ca.crt",
		ClientAuth: tls.RequireAndVerifyClientCert,
	})
	require.NoError(t, err)
	s.StartTLS()
	defer s.Close()

	tempDir, err := ioutil.TempDir("", "config-test")
	require.NoError(t, err)
	defer os.RemoveAll(tempDir)
	configFile, err := os.Create(filepath.Join(tempDir, "config.json"))
	require.NoError(t, err)
	fmt.Fprintf(configFile, `{
		"remote_server": {
			"url": "%s",
			"root_ca": "root-ca.crt",
			"tls_client_cert": "%s",
			"tls_client_key": "notary-server.key"
		}
	}`, s.URL, filepath.Join(tempDir, "notary-server.crt"))
	configFile.Close()

	// copy the certs to be relative to the config directory
	for _, fname := range []string{"notary-server.crt", "notary-server.key", "root-ca.crt"} {
		content, err := ioutil.ReadFile(filepath.Join("../../fixtures", fname))
		require.NoError(t, err)
		require.NoError(t, ioutil.WriteFile(filepath.Join(tempDir, fname), content, 0766))
	}

	// set a config file, so it doesn't check ~/.notary/config.json by default,
	// and execute a random command so that the flags are parsed
	cmd := NewNotaryCommand()
	cmd.SetArgs([]string{"-c", configFile.Name(), "-d", tempDir, "list", "repo"})
	cmd.SetOutput(new(bytes.Buffer)) // eat the output
	err = cmd.Execute()
	require.Error(t, err, "there was no repository, so list should have failed")
	require.NotContains(t, err.Error(), "TLS", "there was no TLS error though!")

	// validate that we actually managed to connect and attempted to download the root though
	require.Len(t, m.gotten, 1)
	require.Equal(t, m.gotten[0], "repo.root")
}
Example #5
0
func TestAllNotNearExpiry(t *testing.T) {
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	require.NoError(t, err)
	notnearexpdate := time.Now().AddDate(0, 10, 0)
	repo.Root.Signed.SignedCommon.Expires = notnearexpdate
	repo.Snapshot.Signed.SignedCommon.Expires = notnearexpdate
	repo.Targets["targets"].Signed.Expires = notnearexpdate
	_, err1 := repo.InitTargets("targets/noexp")
	require.NoError(t, err1)
	repo.Targets["targets/noexp"].Signed.Expires = notnearexpdate
	//Reset levels to display warnings through logrus
	orgLevel := log.GetLevel()
	log.SetLevel(log.WarnLevel)
	defer log.SetLevel(orgLevel)
	a := bytes.NewBuffer(nil)
	log.SetOutput(a)
	warnRolesNearExpiry(repo)
	require.NotContains(t, a.String(), "targets metadata is nearing expiry, you should re-sign the role metadata", "targets should not show near expiry")
	require.NotContains(t, a.String(), "targets/noexp metadata is nearing expiry, you should re-sign the role metadata", "targets/noexp should not show near expiry")
	require.NotContains(t, a.String(), "root is nearing expiry, you should re-sign the role metadata", "Root should not show near expiry")
	require.NotContains(t, a.String(), "snapshot is nearing expiry, you should re-sign the role metadata", "Snapshot should not show near expiry")
	require.NotContains(t, a.String(), "timestamp", "there should be no logrus warnings pertaining to timestamp")
}
Example #6
0
// Whatever TLS config is in the config file can be overridden by the command line
// TLS flags, which are relative to the CWD (not the config) or absolute
func TestConfigFileOverridenByCmdLineFlags(t *testing.T) {
	// Set up server that with a self signed cert
	var err error
	// add a handler for getting the root
	m := &recordingMetaStore{MemStorage: *storage.NewMemStorage()}
	s := httptest.NewUnstartedServer(setupServerHandler(m))
	s.TLS, err = tlsconfig.Server(tlsconfig.Options{
		CertFile:   "../../fixtures/notary-server.crt",
		KeyFile:    "../../fixtures/notary-server.key",
		CAFile:     "../../fixtures/root-ca.crt",
		ClientAuth: tls.RequireAndVerifyClientCert,
	})
	require.NoError(t, err)
	s.StartTLS()
	defer s.Close()

	tempDir := tempDirWithConfig(t, fmt.Sprintf(`{
		"remote_server": {
			"url": "%s",
			"root_ca": "nope",
			"tls_client_cert": "nope",
			"tls_client_key": "nope"
		}
	}`, s.URL))
	defer os.RemoveAll(tempDir)
	configFile := filepath.Join(tempDir, "config.json")

	// set a config file, so it doesn't check ~/.notary/config.json by default,
	// and execute a random command so that the flags are parsed
	cwd, err := os.Getwd()
	require.NoError(t, err)

	cmd := NewNotaryCommand()
	cmd.SetArgs([]string{
		"-c", configFile, "-d", tempDir, "list", "repo",
		"--tlscacert", "../../fixtures/root-ca.crt",
		"--tlscert", filepath.Clean(filepath.Join(cwd, "../../fixtures/notary-server.crt")),
		"--tlskey", "../../fixtures/notary-server.key"})
	cmd.SetOutput(new(bytes.Buffer)) // eat the output
	err = cmd.Execute()
	require.Error(t, err, "there was no repository, so list should have failed")
	require.NotContains(t, err.Error(), "TLS", "there was no TLS error though!")

	// validate that we actually managed to connect and attempted to download the root though
	require.Len(t, m.gotten, 1)
	require.Equal(t, m.gotten[0], "repo.root")
}
func Test0Dot1Migration(t *testing.T) {
	// make a temporary directory and copy the fixture into it, since updating
	// and publishing will modify the files
	tmpDir, err := ioutil.TempDir("", "notary-backwards-compat-test")
	defer os.RemoveAll(tmpDir)
	require.NoError(t, err)
	require.NoError(t, recursiveCopy("../fixtures/compatibility/notary0.1", tmpDir))

	gun := "docker.com/notary0.1/samplerepo"
	passwd := "randompass"

	ts := fullTestServer(t)
	defer ts.Close()

	_, err = NewFileCachedNotaryRepository(tmpDir, gun, ts.URL, http.DefaultTransport,
		passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
	require.NoError(t, err, "error creating repo: %s", err)

	// check that root_keys and tuf_keys are gone and that all corect keys are present and have the correct headers
	files, _ := ioutil.ReadDir(filepath.Join(tmpDir, notary.PrivDir))
	require.Equal(t, files[0].Name(), "7fc757801b9bab4ec9e35bfe7a6b61668ff6f4c81b5632af19e6c728ab799599.key")
	targKey, err := os.OpenFile(filepath.Join(tmpDir, notary.PrivDir, "7fc757801b9bab4ec9e35bfe7a6b61668ff6f4c81b5632af19e6c728ab799599.key"), os.O_RDONLY, notary.PrivExecPerms)
	require.NoError(t, err)
	defer targKey.Close()
	targBytes, _ := ioutil.ReadAll(targKey)
	targString := string(targBytes)
	require.Contains(t, targString, "gun: docker.com/notary0.1/samplerepo")
	require.Contains(t, targString, "role: targets")
	require.Equal(t, files[1].Name(), "a55ccf652b0be4b6c4d356cbb02d9ea432bb84a2571665be3df7c7396af8e8b8.key")
	snapKey, err := os.OpenFile(filepath.Join(tmpDir, notary.PrivDir, "a55ccf652b0be4b6c4d356cbb02d9ea432bb84a2571665be3df7c7396af8e8b8.key"), os.O_RDONLY, notary.PrivExecPerms)
	require.NoError(t, err)
	defer snapKey.Close()
	snapBytes, _ := ioutil.ReadAll(snapKey)
	snapString := string(snapBytes)
	require.Contains(t, snapString, "gun: docker.com/notary0.1/samplerepo")
	require.Contains(t, snapString, "role: snapshot")
	require.Equal(t, files[2].Name(), "d0c623c8e70c70d42a8a8125c44a8598588b3f6e31d5c21a83cbc338dfde8a68.key")
	rootKey, err := os.OpenFile(filepath.Join(tmpDir, notary.PrivDir, "d0c623c8e70c70d42a8a8125c44a8598588b3f6e31d5c21a83cbc338dfde8a68.key"), os.O_RDONLY, notary.PrivExecPerms)
	require.NoError(t, err)
	defer rootKey.Close()
	rootBytes, _ := ioutil.ReadAll(rootKey)
	rootString := string(rootBytes)
	require.Contains(t, rootString, "role: root")
	require.NotContains(t, rootString, "gun")
	require.Len(t, files, 3)
}
Example #8
0
func TestBuilderBridgeSAM(t *testing.T) {
	DownloadCoresAndToolsAndLibraries(t)

	ctx := &types.Context{
		HardwareFolders:         []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"},
		ToolsFolders:            []string{"downloaded_tools"},
		BuiltInLibrariesFolders: []string{"downloaded_libraries"},
		OtherLibrariesFolders:   []string{"libraries"},
		SketchLocation:          filepath.Join("downloaded_libraries", "Bridge", "examples", "Bridge", "Bridge.ino"),
		FQBN:                    "arduino:sam:arduino_due_x_dbg",
		ArduinoAPIVersion:       "10600",
	}

	buildPath := SetupBuildPath(t, ctx)
	defer os.RemoveAll(buildPath)

	ctx.WarningsLevel = "all"

	command := builder.Builder{}
	err := command.Run(ctx)
	NoError(t, err)

	_, err = os.Stat(filepath.Join(buildPath, constants.FOLDER_CORE, "syscalls_sam3.c.o"))
	NoError(t, err)
	_, err = os.Stat(filepath.Join(buildPath, constants.FOLDER_CORE, "USB", "PluggableUSB.cpp.o"))
	NoError(t, err)
	_, err = os.Stat(filepath.Join(buildPath, constants.FOLDER_CORE, "avr", "dtostrf.c.d"))
	NoError(t, err)
	_, err = os.Stat(filepath.Join(buildPath, constants.FOLDER_PREPROC, constants.FILE_CTAGS_TARGET_FOR_GCC_MINUS_E))
	NoError(t, err)
	_, err = os.Stat(filepath.Join(buildPath, constants.FOLDER_SKETCH, "Bridge.ino.cpp.o"))
	NoError(t, err)
	_, err = os.Stat(filepath.Join(buildPath, "Bridge.ino.elf"))
	NoError(t, err)
	_, err = os.Stat(filepath.Join(buildPath, "Bridge.ino.bin"))
	NoError(t, err)
	_, err = os.Stat(filepath.Join(buildPath, constants.FOLDER_LIBRARIES, "Bridge", "Mailbox.cpp.o"))
	NoError(t, err)

	cmd := exec.Command(filepath.Join("downloaded_tools", "arm-none-eabi-gcc", "4.8.3-2014q1", "bin", "arm-none-eabi-objdump"), "-f", filepath.Join(buildPath, constants.FOLDER_CORE, "core.a"))
	bytes, err := cmd.CombinedOutput()
	NoError(t, err)
	require.NotContains(t, string(bytes), "variant.cpp.o")
}
Example #9
0
func TestBuilderBridgeSAM(t *testing.T) {
	DownloadCoresAndToolsAndLibraries(t)

	context := make(map[string]interface{})

	buildPath := SetupBuildPath(t, context)
	defer os.RemoveAll(buildPath)

	context[constants.CTX_HARDWARE_FOLDERS] = []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"}
	context[constants.CTX_TOOLS_FOLDERS] = []string{"downloaded_tools"}
	context[constants.CTX_FQBN] = "arduino:sam:arduino_due_x_dbg"
	context[constants.CTX_SKETCH_LOCATION] = filepath.Join("downloaded_libraries", "Bridge", "examples", "Bridge", "Bridge.ino")
	context[constants.CTX_BUILT_IN_LIBRARIES_FOLDERS] = []string{"downloaded_libraries"}
	context[constants.CTX_OTHER_LIBRARIES_FOLDERS] = []string{"libraries"}
	context[constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION] = "10600"
	context[constants.CTX_WARNINGS_LEVEL] = "all"

	command := builder.Builder{}
	err := command.Run(context)
	NoError(t, err)

	_, err = os.Stat(filepath.Join(buildPath, constants.FOLDER_CORE, "syscalls_sam3.c.o"))
	NoError(t, err)
	_, err = os.Stat(filepath.Join(buildPath, constants.FOLDER_CORE, "USB", "PluggableUSB.cpp.o"))
	NoError(t, err)
	_, err = os.Stat(filepath.Join(buildPath, constants.FOLDER_CORE, "avr", "dtostrf.c.d"))
	NoError(t, err)
	_, err = os.Stat(filepath.Join(buildPath, constants.FOLDER_PREPROC, constants.FILE_CTAGS_TARGET_FOR_GCC_MINUS_E))
	NoError(t, err)
	_, err = os.Stat(filepath.Join(buildPath, constants.FOLDER_SKETCH, "Bridge.ino.cpp.o"))
	NoError(t, err)
	_, err = os.Stat(filepath.Join(buildPath, "Bridge.ino.elf"))
	NoError(t, err)
	_, err = os.Stat(filepath.Join(buildPath, "Bridge.ino.bin"))
	NoError(t, err)
	_, err = os.Stat(filepath.Join(buildPath, constants.FOLDER_LIBRARIES, "Bridge", "Mailbox.cpp.o"))
	NoError(t, err)

	cmd := exec.Command(filepath.Join("downloaded_tools", "arm-none-eabi-gcc", "4.8.3-2014q1", "bin", "arm-none-eabi-objdump"), "-f", filepath.Join(buildPath, constants.FOLDER_CORE, "core.a"))
	bytes, err := cmd.CombinedOutput()
	NoError(t, err)
	require.NotContains(t, string(bytes), "variant.cpp.o")
}
Example #10
0
// config parsing bugs are propagated in all commands
func TestConfigParsingErrorsPropagatedByCommands(t *testing.T) {
	tempdir, err := ioutil.TempDir("", "empty-dir")
	require.NoError(t, err)
	defer os.RemoveAll(tempdir)

	for _, args := range exampleValidCommands {
		b := new(bytes.Buffer)
		cmd := NewNotaryCommand()
		cmd.SetOutput(b)

		cmd.SetArgs(append(
			[]string{"-c", filepath.Join(tempdir, "idonotexist.json"), "-d", tempdir},
			strings.Fields(args)...))
		err = cmd.Execute()

		require.Error(t, err, "expected error when running `notary %s`", args)
		require.Contains(t, err.Error(), "error opening config file", "running `notary %s`", args)
		require.NotContains(t, b.String(), "Usage:")
	}
}
Example #11
0
// NewRaftDEKManager creates a key if one doesn't exist
func TestNewRaftDEKManager(t *testing.T) {
	tempDir, err := ioutil.TempDir("", "manager-new-dek-manager-")
	require.NoError(t, err)
	defer os.RemoveAll(tempDir)

	paths := ca.NewConfigPaths(tempDir)
	cert, key, err := cautils.CreateRootCertAndKey("cn")
	require.NoError(t, err)

	krw := ca.NewKeyReadWriter(paths.Node, nil, nil)
	require.NoError(t, krw.Write(cert, key, nil))

	keyBytes, err := ioutil.ReadFile(paths.Node.Key)
	require.NoError(t, err)
	require.NotContains(t, string(keyBytes), pemHeaderRaftDEK) // headers are not written

	dekManager, err := NewRaftDEKManager(krw) // this should create a new DEK and write it to the file
	require.NoError(t, err)

	keyBytes, err = ioutil.ReadFile(paths.Node.Key)
	require.NoError(t, err)
	require.Contains(t, string(keyBytes), pemHeaderRaftDEK) // header is written now

	keys := dekManager.GetKeys()
	require.NotNil(t, keys.CurrentDEK)
	require.Nil(t, keys.PendingDEK)
	require.False(t, dekManager.NeedsRotation())

	// If one exists, nothing is updated
	dekManager, err = NewRaftDEKManager(krw) // this should create a new DEK and write it to the file
	require.NoError(t, err)

	keyBytes2, err := ioutil.ReadFile(paths.Node.Key)
	require.NoError(t, err)
	require.Equal(t, keyBytes, keyBytes2)

	require.Equal(t, keys, dekManager.GetKeys())
	require.False(t, dekManager.NeedsRotation())
}
Example #12
0
func mustNotContain(t *testing.T, page, what string) {
	require.NotContains(t, page, what)
}
Example #13
0
func TestDelegationRolesParent(t *testing.T) {
	delgA := data.DelegationRole{
		BaseRole: data.BaseRole{
			Keys:      nil,
			Name:      "targets/a",
			Threshold: 1,
		},
		Paths: []string{"path", "anotherpath"},
	}

	delgB := data.DelegationRole{
		BaseRole: data.BaseRole{
			Keys:      nil,
			Name:      "targets/a/b",
			Threshold: 1,
		},
		Paths: []string{"path/b", "anotherpath/b", "b/invalidpath"},
	}

	// Assert direct parent relationship
	require.True(t, delgA.IsParentOf(delgB))
	require.False(t, delgB.IsParentOf(delgA))
	require.False(t, delgA.IsParentOf(delgA))

	delgC := data.DelegationRole{
		BaseRole: data.BaseRole{
			Keys:      nil,
			Name:      "targets/a/b/c",
			Threshold: 1,
		},
		Paths: []string{"path/b", "anotherpath/b/c", "c/invalidpath"},
	}

	// Assert direct parent relationship
	require.True(t, delgB.IsParentOf(delgC))
	require.False(t, delgB.IsParentOf(delgB))
	require.False(t, delgA.IsParentOf(delgC))
	require.False(t, delgC.IsParentOf(delgB))
	require.False(t, delgC.IsParentOf(delgA))
	require.False(t, delgC.IsParentOf(delgC))

	// Check that parents correctly restrict paths
	restrictedDelgB, err := delgA.Restrict(delgB)
	require.NoError(t, err)
	require.Contains(t, restrictedDelgB.Paths, "path/b")
	require.Contains(t, restrictedDelgB.Paths, "anotherpath/b")
	require.NotContains(t, restrictedDelgB.Paths, "b/invalidpath")

	_, err = delgB.Restrict(delgA)
	require.Error(t, err)
	_, err = delgA.Restrict(delgC)
	require.Error(t, err)
	_, err = delgC.Restrict(delgB)
	require.Error(t, err)
	_, err = delgC.Restrict(delgA)
	require.Error(t, err)

	// Make delgA have no paths and check that it changes delgB and delgC accordingly when chained
	delgA.Paths = []string{}
	restrictedDelgB, err = delgA.Restrict(delgB)
	require.NoError(t, err)
	require.Empty(t, restrictedDelgB.Paths)
	restrictedDelgC, err := restrictedDelgB.Restrict(delgC)
	require.NoError(t, err)
	require.Empty(t, restrictedDelgC.Paths)
}
Example #14
0
// Initialize repo and test publishing targets with delegation roles
func TestClientDelegationsPublishing(t *testing.T) {
	setUp(t)

	tempDir := tempDirWithConfig(t, "{}")
	defer os.RemoveAll(tempDir)

	server := setupServer()
	defer server.Close()

	// Setup certificate for delegation role
	tempFile, err := ioutil.TempFile("", "pemfile")
	require.NoError(t, err)

	privKey, err := trustmanager.GenerateRSAKey(rand.Reader, 2048)
	require.NoError(t, err)
	privKeyBytesNoRole, err := trustmanager.KeyToPEM(privKey, "")
	require.NoError(t, err)
	privKeyBytesWithRole, err := trustmanager.KeyToPEM(privKey, "user")
	require.NoError(t, err)
	startTime := time.Now()
	endTime := startTime.AddDate(10, 0, 0)
	cert, err := cryptoservice.GenerateCertificate(privKey, "gun", startTime, endTime)
	require.NoError(t, err)

	_, err = tempFile.Write(trustmanager.CertToPEM(cert))
	require.NoError(t, err)
	tempFile.Close()
	defer os.Remove(tempFile.Name())

	rawPubBytes, _ := ioutil.ReadFile(tempFile.Name())
	parsedPubKey, _ := trustmanager.ParsePEMPublicKey(rawPubBytes)
	canonicalKeyID, err := utils.CanonicalKeyID(parsedPubKey)
	require.NoError(t, err)

	// Set up targets for publishing
	tempTargetFile, err := ioutil.TempFile("", "targetfile")
	require.NoError(t, err)
	tempTargetFile.Close()
	defer os.Remove(tempTargetFile.Name())

	var target = "sdgkadga"

	var output string

	// init repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "init", "gun")
	require.NoError(t, err)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - none yet
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "No delegations present in this repository.")

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// validate that we have all keys, including snapshot
	assertNumKeys(t, tempDir, 1, 2, true)

	// rotate the snapshot key to server
	output, err = runCommand(t, tempDir, "-s", server.URL, "key", "rotate", "gun", "snapshot", "-r")
	require.NoError(t, err)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// validate that we lost the snapshot signing key
	_, signingKeyIDs := assertNumKeys(t, tempDir, 1, 1, true)
	targetKeyID := signingKeyIDs[0]

	// add new valid delegation with single new cert
	output, err = runCommand(t, tempDir, "delegation", "add", "gun", "targets/releases", tempFile.Name(), "--paths", "\"\"")
	require.NoError(t, err)
	require.Contains(t, output, "Addition of delegation role")
	require.Contains(t, output, canonicalKeyID)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should see our one delegation
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.NotContains(t, output, "No delegations present in this repository.")

	// remove the targets key to demonstrate that delegates don't need this key
	keyDir := filepath.Join(tempDir, "private", "tuf_keys")
	require.NoError(t, os.Remove(filepath.Join(keyDir, "gun", targetKeyID+".key")))

	// Note that we need to use the canonical key ID, followed by the base of the role here
	err = ioutil.WriteFile(filepath.Join(keyDir, canonicalKeyID+"_releases.key"), privKeyBytesNoRole, 0700)
	require.NoError(t, err)

	// add a target using the delegation -- will only add to targets/releases
	_, err = runCommand(t, tempDir, "add", "gun", target, tempTargetFile.Name(), "--roles", "targets/releases")
	require.NoError(t, err)

	// list targets for targets/releases - we should see no targets until we publish
	output, err = runCommand(t, tempDir, "-s", server.URL, "list", "gun", "--roles", "targets/releases")
	require.NoError(t, err)
	require.Contains(t, output, "No targets")

	output, err = runCommand(t, tempDir, "-s", server.URL, "status", "gun")
	require.NoError(t, err)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list targets for targets/releases - we should see our target!
	output, err = runCommand(t, tempDir, "-s", server.URL, "list", "gun", "--roles", "targets/releases")
	require.NoError(t, err)
	require.Contains(t, output, "targets/releases")

	// remove the target for this role only
	_, err = runCommand(t, tempDir, "remove", "gun", target, "--roles", "targets/releases")
	require.NoError(t, err)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list targets for targets/releases - we should see no targets
	output, err = runCommand(t, tempDir, "-s", server.URL, "list", "gun", "--roles", "targets/releases")
	require.NoError(t, err)
	require.Contains(t, output, "No targets present")

	// Try adding a target with a different key style - private/tuf_keys/canonicalKeyID.key with "user" set as the "role" PEM header
	// First remove the old key and add the new style
	require.NoError(t, os.Remove(filepath.Join(keyDir, canonicalKeyID+"_releases.key")))
	err = ioutil.WriteFile(filepath.Join(keyDir, canonicalKeyID+".key"), privKeyBytesWithRole, 0700)
	require.NoError(t, err)

	// add a target using the delegation -- will only add to targets/releases
	_, err = runCommand(t, tempDir, "add", "gun", target, tempTargetFile.Name(), "--roles", "targets/releases")
	require.NoError(t, err)

	// list targets for targets/releases - we should see no targets until we publish
	output, err = runCommand(t, tempDir, "-s", server.URL, "list", "gun", "--roles", "targets/releases")
	require.NoError(t, err)
	require.Contains(t, output, "No targets")

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list targets for targets/releases - we should see our target!
	output, err = runCommand(t, tempDir, "-s", server.URL, "list", "gun", "--roles", "targets/releases")
	require.NoError(t, err)
	require.Contains(t, output, "targets/releases")

	// remove the target for this role only
	_, err = runCommand(t, tempDir, "remove", "gun", target, "--roles", "targets/releases")
	require.NoError(t, err)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// Now remove this key, and make a new file to import the delegation's key from
	require.NoError(t, os.Remove(filepath.Join(keyDir, canonicalKeyID+".key")))
	tempPrivFile, err := ioutil.TempFile("/tmp", "privfile")
	require.NoError(t, err)
	defer os.Remove(tempPrivFile.Name())

	// Write the private key to a file so we can import it
	_, err = tempPrivFile.Write(privKeyBytesNoRole)
	require.NoError(t, err)
	tempPrivFile.Close()

	// Import the private key, associating it with our delegation role
	_, err = runCommand(t, tempDir, "key", "import", tempPrivFile.Name(), "--role", "targets/releases")
	require.NoError(t, err)

	// add a target using the delegation -- will only add to targets/releases
	_, err = runCommand(t, tempDir, "add", "gun", target, tempTargetFile.Name(), "--roles", "targets/releases")
	require.NoError(t, err)

	// list targets for targets/releases - we should see no targets until we publish
	output, err = runCommand(t, tempDir, "-s", server.URL, "list", "gun", "--roles", "targets/releases")
	require.NoError(t, err)
	require.Contains(t, output, "No targets")

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list targets for targets/releases - we should see our target!
	output, err = runCommand(t, tempDir, "-s", server.URL, "list", "gun", "--roles", "targets/releases")
	require.NoError(t, err)
	require.Contains(t, output, "targets/releases")
}
Example #15
0
// Initialize repo and test delegations commands by adding, listing, and removing delegations
func TestClientDelegationsInteraction(t *testing.T) {
	setUp(t)

	tempDir := tempDirWithConfig(t, "{}")
	defer os.RemoveAll(tempDir)

	server := setupServer()
	defer server.Close()

	// Setup certificate
	tempFile, err := ioutil.TempFile("", "pemfile")
	require.NoError(t, err)

	privKey, err := trustmanager.GenerateECDSAKey(rand.Reader)
	startTime := time.Now()
	endTime := startTime.AddDate(10, 0, 0)
	cert, err := cryptoservice.GenerateCertificate(privKey, "gun", startTime, endTime)
	require.NoError(t, err)

	_, err = tempFile.Write(trustmanager.CertToPEM(cert))
	require.NoError(t, err)
	tempFile.Close()
	defer os.Remove(tempFile.Name())

	rawPubBytes, _ := ioutil.ReadFile(tempFile.Name())
	parsedPubKey, _ := trustmanager.ParsePEMPublicKey(rawPubBytes)
	keyID, err := utils.CanonicalKeyID(parsedPubKey)
	require.NoError(t, err)

	var output string

	// -- tests --

	// init repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "init", "gun")
	require.NoError(t, err)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - none yet
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "No delegations present in this repository.")

	// add new valid delegation with single new cert, and no path
	output, err = runCommand(t, tempDir, "delegation", "add", "gun", "targets/delegation", tempFile.Name())
	require.NoError(t, err)
	require.Contains(t, output, "Addition of delegation role")
	require.Contains(t, output, keyID)
	require.NotContains(t, output, "path")

	// check status - see delegation
	output, err = runCommand(t, tempDir, "status", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "Unpublished changes for gun")

	// list delegations - none yet because still unpublished
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "No delegations present in this repository.")

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// check status - no changelist
	output, err = runCommand(t, tempDir, "status", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "No unpublished changes for gun")

	// list delegations - we should see our added delegation, with no paths
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "targets/delegation")
	require.Contains(t, output, keyID)
	require.NotContains(t, output, "\"\"")

	// add all paths to this delegation
	output, err = runCommand(t, tempDir, "delegation", "add", "gun", "targets/delegation", "--all-paths")
	require.NoError(t, err)
	require.Contains(t, output, "Addition of delegation role")
	require.Contains(t, output, "\"\"")
	require.Contains(t, output, "<all paths>")

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should see our added delegation, with no paths
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "targets/delegation")
	require.Contains(t, output, "\"\"")
	require.Contains(t, output, "<all paths>")

	// Setup another certificate
	tempFile2, err := ioutil.TempFile("", "pemfile2")
	require.NoError(t, err)

	privKey, err = trustmanager.GenerateECDSAKey(rand.Reader)
	startTime = time.Now()
	endTime = startTime.AddDate(10, 0, 0)
	cert, err = cryptoservice.GenerateCertificate(privKey, "gun", startTime, endTime)
	require.NoError(t, err)

	_, err = tempFile2.Write(trustmanager.CertToPEM(cert))
	require.NoError(t, err)
	require.NoError(t, err)
	tempFile2.Close()
	defer os.Remove(tempFile2.Name())

	rawPubBytes2, _ := ioutil.ReadFile(tempFile2.Name())
	parsedPubKey2, _ := trustmanager.ParsePEMPublicKey(rawPubBytes2)
	keyID2, err := utils.CanonicalKeyID(parsedPubKey2)
	require.NoError(t, err)

	// add to the delegation by specifying the same role, this time add a scoped path
	output, err = runCommand(t, tempDir, "delegation", "add", "gun", "targets/delegation", tempFile2.Name(), "--paths", "path")
	require.NoError(t, err)
	require.Contains(t, output, "Addition of delegation role")
	require.Contains(t, output, keyID2)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should see two keys
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "path")
	require.Contains(t, output, keyID)
	require.Contains(t, output, keyID2)

	// remove the delegation's first key
	output, err = runCommand(t, tempDir, "delegation", "remove", "gun", "targets/delegation", keyID)
	require.NoError(t, err)
	require.Contains(t, output, "Removal of delegation role")

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should see the delegation but with only the second key
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.NotContains(t, output, keyID)
	require.Contains(t, output, keyID2)

	// remove the delegation's second key
	output, err = runCommand(t, tempDir, "delegation", "remove", "gun", "targets/delegation", keyID2)
	require.NoError(t, err)
	require.Contains(t, output, "Removal of delegation role")

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should see no delegations
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "No delegations present in this repository.")

	// add delegation with multiple certs and multiple paths
	output, err = runCommand(t, tempDir, "delegation", "add", "gun", "targets/delegation", tempFile.Name(), tempFile2.Name(), "--paths", "path1,path2")
	require.NoError(t, err)
	require.Contains(t, output, "Addition of delegation role")
	require.Contains(t, output, keyID)
	require.Contains(t, output, keyID2)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should see two keys
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "path1")
	require.Contains(t, output, "path2")
	require.Contains(t, output, keyID)
	require.Contains(t, output, keyID2)

	// add delegation with multiple certs and multiple paths
	output, err = runCommand(t, tempDir, "delegation", "add", "gun", "targets/delegation", "--paths", "path3")
	require.NoError(t, err)
	require.Contains(t, output, "Addition of delegation role")

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should see two keys
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "path1")
	require.Contains(t, output, "path2")
	require.Contains(t, output, "path3")
	require.Contains(t, output, keyID)
	require.Contains(t, output, keyID2)

	// just remove two paths from this delegation
	output, err = runCommand(t, tempDir, "delegation", "remove", "gun", "targets/delegation", "--paths", "path2,path3")
	require.NoError(t, err)
	require.Contains(t, output, "Removal of delegation role")

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should see the same two keys, and only path1
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "path1")
	require.NotContains(t, output, "path2")
	require.NotContains(t, output, "path3")
	require.Contains(t, output, keyID)
	require.Contains(t, output, keyID2)

	// remove the remaining path, should not remove the delegation entirely
	output, err = runCommand(t, tempDir, "delegation", "remove", "gun", "targets/delegation", "--paths", "path1")
	require.NoError(t, err)
	require.Contains(t, output, "Removal of delegation role")

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should see the same two keys, and no paths
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.NotContains(t, output, "path1")
	require.NotContains(t, output, "path2")
	require.NotContains(t, output, "path3")
	require.Contains(t, output, keyID)
	require.Contains(t, output, keyID2)

	// Add a bunch of individual paths so we can test a delegation remove --all-paths
	output, err = runCommand(t, tempDir, "delegation", "add", "gun", "targets/delegation", "--paths", "abcdef,123456")
	require.NoError(t, err)

	// Add more individual paths so we can test a delegation remove --all-paths
	output, err = runCommand(t, tempDir, "delegation", "add", "gun", "targets/delegation", "--paths", "banana/split,apple/crumble/pie,orange.peel,kiwi")
	require.NoError(t, err)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should see all of our paths
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "abcdef")
	require.Contains(t, output, "123456")
	require.Contains(t, output, "banana/split")
	require.Contains(t, output, "apple/crumble/pie")
	require.Contains(t, output, "orange.peel")
	require.Contains(t, output, "kiwi")

	// Try adding "", and check that adding it with other paths clears out the others
	output, err = runCommand(t, tempDir, "delegation", "add", "gun", "targets/delegation", "--paths", "\"\",grapefruit,pomegranate")
	require.NoError(t, err)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should see all of our old paths, and ""
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "abcdef")
	require.Contains(t, output, "123456")
	require.Contains(t, output, "banana/split")
	require.Contains(t, output, "apple/crumble/pie")
	require.Contains(t, output, "orange.peel")
	require.Contains(t, output, "kiwi")
	require.Contains(t, output, "\"\"")
	require.NotContains(t, output, "grapefruit")
	require.NotContains(t, output, "pomegranate")

	// Try removing just ""
	output, err = runCommand(t, tempDir, "delegation", "remove", "gun", "targets/delegation", "--paths", "\"\"")
	require.NoError(t, err)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should see all of our old paths without ""
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "abcdef")
	require.Contains(t, output, "123456")
	require.Contains(t, output, "banana/split")
	require.Contains(t, output, "apple/crumble/pie")
	require.Contains(t, output, "orange.peel")
	require.Contains(t, output, "kiwi")
	require.NotContains(t, output, "\"\"")

	// Remove --all-paths to clear out all paths from this delegation
	output, err = runCommand(t, tempDir, "delegation", "remove", "gun", "targets/delegation", "--all-paths")
	require.NoError(t, err)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should see all of our paths
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.NotContains(t, output, "abcdef")
	require.NotContains(t, output, "123456")
	require.NotContains(t, output, "banana/split")
	require.NotContains(t, output, "apple/crumble/pie")
	require.NotContains(t, output, "orange.peel")
	require.NotContains(t, output, "kiwi")

	// Check that we ignore other --paths if we pass in --all-paths on an add
	output, err = runCommand(t, tempDir, "delegation", "add", "gun", "targets/delegation", "--all-paths", "--paths", "grapefruit,pomegranate")
	require.NoError(t, err)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should only see "", and not the other paths specified
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "\"\"")
	require.NotContains(t, output, "grapefruit")
	require.NotContains(t, output, "pomegranate")

	// Add those extra paths we ignored to set up the next test
	output, err = runCommand(t, tempDir, "delegation", "add", "gun", "targets/delegation", "--paths", "grapefruit,pomegranate")
	require.NoError(t, err)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// Check that we ignore other --paths if we pass in --all-paths on a remove
	output, err = runCommand(t, tempDir, "delegation", "remove", "gun", "targets/delegation", "--all-paths", "--paths", "pomegranate")
	require.NoError(t, err)

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should see no paths
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.NotContains(t, output, "\"\"")
	require.NotContains(t, output, "grapefruit")
	require.NotContains(t, output, "pomegranate")

	// remove by force to delete the delegation entirely
	output, err = runCommand(t, tempDir, "delegation", "remove", "gun", "targets/delegation", "-y")
	require.NoError(t, err)
	require.Contains(t, output, "Forced removal (including all keys and paths) of delegation role")

	// publish repo
	_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
	require.NoError(t, err)

	// list delegations - we should see no delegations
	output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
	require.NoError(t, err)
	require.Contains(t, output, "No delegations present in this repository.")
}