Beispiel #1
0
func tufStatus(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		cmd.Usage()
		fatalf("Must specify a GUN")
	}

	parseConfig()
	gun := args[0]

	nRepo, err := notaryclient.NewNotaryRepository(mainViper.GetString("trust_dir"), gun, getRemoteTrustServer(), nil, retriever)
	if err != nil {
		fatalf(err.Error())
	}

	cl, err := nRepo.GetChangelist()
	if err != nil {
		fatalf(err.Error())
	}

	if len(cl.List()) == 0 {
		cmd.Printf("No unpublished changes for %s\n", gun)
		return
	}

	cmd.Printf("Unpublished changes for %s:\n\n", gun)
	cmd.Printf("%-10s%-10s%-12s%s\n", "action", "scope", "type", "path")
	cmd.Println("----------------------------------------------------")
	for _, ch := range cl.List() {
		cmd.Printf("%-10s%-10s%-12s%s\n", ch.Action(), ch.Scope(), ch.Type(), ch.Path())
	}
}
Beispiel #2
0
// runExecute is the code that implements the execute command.
func runExecute(cmd *cobra.Command, args []string) error {
	cmd.Printf("Executing View : Name[%s]\n", execute.viewName)

	// Validate the input parameters.
	if execute.viewName == "" || execute.itemKey == "" {
		return fmt.Errorf("view name and item key must be specified")
	}

	// Ready the view parameters.
	viewParams := wire.ViewParams{
		ViewName:          execute.viewName,
		ItemKey:           execute.itemKey,
		ResultsCollection: execute.resultsCollection,
		BufferLimit:       execute.bufferLimit,
	}

	// Execute the view.
	results, err := wire.Execute("", mgoDB, graphDB, &viewParams)
	if err != nil {
		return err
	}

	// Prepare the results for printing.
	data, err := json.MarshalIndent(results, "", "    ")
	if err != nil {
		return err
	}

	cmd.Printf("\n%s\n\n", string(data))
	cmd.Println("\n", "Executing View : Executed")
	return nil
}
Beispiel #3
0
// runIndex issues the command talking to the web service.
func runIndex(cmd *cobra.Command, args []string) error {
	cmd.Printf("Ensure Indexes : Name[%s]\n", index.name)

	set, err := runGetSet(cmd, index.name)
	if err != nil {
		return err
	}

	verb := "PUT"
	url := "/v1/index/" + index.name

	data, err := json.Marshal(set)
	if err != nil {
		return err
	}

	cmd.Printf("\n%s\n\n", string(data))

	if _, err := web.Request(cmd, verb, url, bytes.NewBuffer(data)); err != nil {
		return err
	}

	cmd.Println("\n", "Ensure Indexes : Ensured")
	return nil
}
Beispiel #4
0
func (t *tufCommander) tufPublish(cmd *cobra.Command, args []string) error {
	if len(args) < 1 {
		cmd.Usage()
		return fmt.Errorf("Must specify a GUN")
	}

	config, err := t.configGetter()
	if err != nil {
		return err
	}
	gun := args[0]

	cmd.Println("Pushing changes to", gun)

	rt, err := getTransport(config, gun, false)
	if err != nil {
		return err
	}

	trustPin, err := getTrustPinning(config)
	if err != nil {
		return err
	}

	nRepo, err := notaryclient.NewNotaryRepository(
		config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, t.retriever, trustPin)
	if err != nil {
		return err
	}

	if err = nRepo.Publish(); err != nil {
		return err
	}
	return nil
}
Beispiel #5
0
func (t *tufCommander) tufLookup(cmd *cobra.Command, args []string) error {
	if len(args) < 2 {
		cmd.Usage()
		return fmt.Errorf("Must specify a GUN and target")
	}
	config, err := t.configGetter()
	if err != nil {
		return err
	}

	gun := args[0]
	targetName := args[1]

	rt, err := getTransport(config, gun, true)
	if err != nil {
		return err
	}

	nRepo, err := notaryclient.NewNotaryRepository(
		config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, t.retriever)
	if err != nil {
		return err
	}

	target, err := nRepo.GetTargetByName(targetName)
	if err != nil {
		return err
	}

	cmd.Println(target.Name, fmt.Sprintf("sha256:%x", target.Hashes["sha256"]), target.Length)
	return nil
}
Beispiel #6
0
func (c *certCommander) certList(cmd *cobra.Command, args []string) error {
	if len(args) > 0 {
		cmd.Usage()
		return fmt.Errorf("")
	}
	config, err := c.configGetter()
	if err != nil {
		return err
	}

	trustDir := config.GetString("trust_dir")
	certPath := filepath.Join(trustDir, notary.TrustedCertsDir)
	// Load all individual (non-CA) certificates that aren't expired and don't use SHA1
	certStore, err := trustmanager.NewX509FilteredFileStore(
		certPath,
		trustmanager.FilterCertsExpiredSha1,
	)
	if err != nil {
		return fmt.Errorf("Failed to create a new truststore with directory: %s", trustDir)
	}

	trustedCerts := certStore.GetCertificates()

	cmd.Println("")
	prettyPrintCerts(trustedCerts, cmd.Out())
	cmd.Println("")
	return nil
}
Beispiel #7
0
func maybeAutoPublish(cmd *cobra.Command, doPublish bool, gun string, config *viper.Viper, passRetriever notary.PassRetriever) error {

	if !doPublish {
		return nil
	}

	// We need to set up a http RoundTripper when publishing
	rt, err := getTransport(config, gun, readWrite)
	if err != nil {
		return err
	}

	trustPin, err := getTrustPinning(config)
	if err != nil {
		return err
	}

	nRepo, err := notaryclient.NewFileCachedNotaryRepository(
		config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, passRetriever, trustPin)
	if err != nil {
		return err
	}

	cmd.Println("Auto-publishing changes to", gun)
	return publishAndPrintToCLI(cmd, nRepo, gun)
}
Beispiel #8
0
// keyRemove deletes a private key based on ID
func (k *keyCommander) keyRemove(cmd *cobra.Command, args []string) error {
	if len(args) < 1 {
		cmd.Usage()
		return fmt.Errorf("must specify the key ID of the key to remove")
	}

	config, err := k.configGetter()
	if err != nil {
		return err
	}
	ks, err := k.getKeyStores(config, true, false)
	if err != nil {
		return err
	}
	keyID := args[0]

	// This is an invalid ID
	if len(keyID) != notary.SHA256HexSize {
		return fmt.Errorf("invalid key ID provided: %s", keyID)
	}
	cmd.Println("")
	err = removeKeyInteractively(ks, keyID, k.input, cmd.Out())
	cmd.Println("")
	return err
}
Beispiel #9
0
func searchImages(ctx *cobra.Command, args []string) {
	if len(args) < 1 {
		ErrorExit(ctx, "Needs an argument <TERM> to search")
	}

	docker, err := client.NewDockerClient(configPath, hostName, ctx.Out())
	if err != nil {
		log.Fatal(err)
	}

	images, err := docker.SearchImages(args[0])
	if err != nil {
		log.Fatal(err)
	}

	if boolStar {
		sort.Sort(sort.Reverse(api.SortImagesByStars{ImageSearchResults: images}))
	} else {
		sort.Sort(api.SortImagesByName{ImageSearchResults: images})
	}

	if boolQuiet {
		for _, image := range images {
			ctx.Println(image.Name)
		}
		return
	}

	if boolYAML || boolJSON {
		if err := FormatPrint(ctx.Out(), images); err != nil {
			log.Fatal(err)
		}
		return
	}

	var items [][]string

	for _, image := range images {
		out := []string{
			image.Name,
			image.Description,
			FormatInt(int64(image.Stars)),
			FormatBool(image.Official, "*", " "),
			FormatBool(image.Automated, "*", " "),
		}
		items = append(items, out)
	}

	header := []string{
		"Name",
		"Description",
		"Stars",
		"Official",
		"Automated",
	}

	PrintInTable(ctx.Out(), header, items, 50, tablewriter.ALIGN_DEFAULT)
}
Beispiel #10
0
func composeContainers(ctx *cobra.Command, args []string) {
	if len(args) < 1 {
		ErrorExit(ctx, "Needs an argument <PATH/TO/YAML> to compose containers")
	}

	path := filepath.Clean(args[0])
	root := filepath.Dir(path)

	var names []string
	if len(args) > 1 {
		names = args[1:]
	}

	data, err := ioutil.ReadFile(path)
	if err != nil {
		log.Fatal(err)
	}

	var composers map[string]Composer
	if err := yaml.Unmarshal(data, &composers); err != nil {
		log.Fatal(err)
	}

	var gotError = false

	if len(names) == 0 {
		for name, composer := range composers {
			composer.Name = name
			composer = mergeComposeFlags(ctx, composer)
			if cid, err := composeContainer(ctx, root, composer); err != nil {
				log.Error(err)
				gotError = true
			} else {
				ctx.Println(cid)
			}
		}
	}

	for _, name := range names {
		if composer, ok := composers[name]; ok {
			composer.Name = name
			composer = mergeComposeFlags(ctx, composer)
			if cid, err := composeContainer(ctx, root, composer); err != nil {
				log.Error(err)
				gotError = true
			} else {
				ctx.Println(cid)
			}
		}
	}

	if gotError {
		log.Fatal("Error: failed to compose one or more containers")
	}
}
Beispiel #11
0
// runDelete issues the command talking to the web service.
func runDelete(cmd *cobra.Command, args []string) error {
	verb := "DELETE"
	url := "/v1/script/" + get.name

	if _, err := web.Request(cmd, verb, url, nil); err != nil {
		return err
	}

	cmd.Println("Deleting Script : Deleted")
	return nil
}
Beispiel #12
0
// runDelete issues the command talking to the web service.
func runDelete(cmd *cobra.Command, args []string) error {
	verb := "DELETE"
	url := "/v1/relationship/" + delete.predicate

	if _, err := web.Request(cmd, verb, url, nil); err != nil {
		return err
	}

	cmd.Println("Deleting Relationship : Deleted")
	return nil
}
Beispiel #13
0
// runDelete issues the command talking to the web service.
func runDelete(cmd *cobra.Command, args []string) error {
	verb := "DELETE"
	url := "/v1/mask/" + delete.collection + "/" + delete.field

	if _, err := web.Request(cmd, verb, url, nil); err != nil {
		return err
	}

	cmd.Println("Deleting Mask : Deleted")
	return nil
}
Beispiel #14
0
// runDelete issues the command talking to the web service.
func runDelete(cmd *cobra.Command, args []string) error {
	verb := "DELETE"
	url := "/v1/item/" + delete.ID

	if _, err := web.Request(cmd, verb, url, nil); err != nil {
		return err
	}

	cmd.Println("Deleting Item : Deleted")
	return nil
}
Beispiel #15
0
// delegationRemove removes a public key from a specific role in a GUN
func (d *delegationCommander) delegationRemove(cmd *cobra.Command, args []string) error {
	config, gun, role, keyIDs, err := delegationAddInput(d, cmd, args)
	if err != nil {
		return err
	}

	trustPin, err := getTrustPinning(config)
	if err != nil {
		return err
	}

	// no online operations are performed by add so the transport argument
	// should be nil
	nRepo, err := notaryclient.NewFileCachedNotaryRepository(
		config.GetString("trust_dir"), gun, getRemoteTrustServer(config), nil, d.retriever, trustPin)
	if err != nil {
		return err
	}

	if d.removeAll {
		cmd.Println("\nAre you sure you want to remove all data for this delegation? (yes/no)")
		// Ask for confirmation before force removing delegation
		if !d.forceYes {
			confirmed := askConfirm(os.Stdin)
			if !confirmed {
				fatalf("Aborting action.")
			}
		} else {
			cmd.Println("Confirmed `yes` from flag")
		}
		// Delete the entire delegation
		err = nRepo.RemoveDelegationRole(role)
		if err != nil {
			return fmt.Errorf("failed to remove delegation: %v", err)
		}
	} else {
		if d.allPaths {
			err = nRepo.ClearDelegationPaths(role)
			if err != nil {
				return fmt.Errorf("failed to remove delegation: %v", err)
			}
		}
		// Remove any keys or paths that we passed in
		err = nRepo.RemoveDelegationKeysAndPaths(role, keyIDs, d.paths)
		if err != nil {
			return fmt.Errorf("failed to remove delegation: %v", err)
		}
	}

	delegationRemoveOutput(cmd, d, gun, role, keyIDs)

	return maybeAutoPublish(cmd, d.autoPublish, gun, config, d.retriever)
}
Beispiel #16
0
func keysList(cmd *cobra.Command, args []string) {
	if len(args) > 0 {
		cmd.Usage()
		os.Exit(1)
	}

	parseConfig()

	stores := getKeyStores(cmd, mainViper.GetString("trust_dir"), retriever, true)
	cmd.Println("")
	prettyPrintKeys(stores, cmd.Out())
	cmd.Println("")
}
Beispiel #17
0
// keyPassphraseChange changes the passphrase for a root key's private key based on ID
func (k *keyCommander) keyPassphraseChange(cmd *cobra.Command, args []string) error {
	if len(args) < 1 {
		cmd.Usage()
		return fmt.Errorf("must specify the key ID of the key to change the passphrase of")
	}

	config, err := k.configGetter()
	if err != nil {
		return err
	}
	ks, err := k.getKeyStores(config, true)
	if err != nil {
		return err
	}

	keyID := args[0]

	// This is an invalid ID
	if len(keyID) != notary.Sha256HexSize {
		return fmt.Errorf("invalid key ID provided: %s", keyID)
	}

	// Find the key's GUN by ID, in case it is a non-root key
	var keyGUN string
	for _, store := range ks {
		for keypath := range store.ListKeys() {
			if filepath.Base(keypath) == keyID {
				keyGUN = filepath.Dir(keypath)
			}
		}
	}
	cs := cryptoservice.NewCryptoService(keyGUN, ks...)
	privKey, role, err := cs.GetPrivateKey(keyID)
	if err != nil {
		return fmt.Errorf("could not retrieve local key for key ID provided: %s", keyID)
	}

	// Must use a different passphrase retriever to avoid caching the
	// unlocking passphrase and reusing that.
	passChangeRetriever := k.getRetriever()
	keyStore, err := trustmanager.NewKeyFileStore(config.GetString("trust_dir"), passChangeRetriever)
	err = keyStore.AddKey(filepath.Join(keyGUN, keyID), role, privKey)
	if err != nil {
		return err
	}

	cmd.Println("")
	cmd.Printf("Successfully updated passphrase for key ID: %s", keyID)
	cmd.Println("")
	return nil
}
Beispiel #18
0
func (t *tufCommander) tufInit(cmd *cobra.Command, args []string) error {
	if len(args) < 1 {
		cmd.Usage()
		return fmt.Errorf("Must specify a GUN")
	}

	config, err := t.configGetter()
	if err != nil {
		return err
	}
	gun := args[0]

	rt, err := getTransport(config, gun, false)
	if err != nil {
		return err
	}

	trustPin, err := getTrustPinning(config)
	if err != nil {
		return err
	}

	nRepo, err := notaryclient.NewNotaryRepository(
		config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, t.retriever, trustPin)
	if err != nil {
		return err
	}

	rootKeyList := nRepo.CryptoService.ListKeys(data.CanonicalRootRole)

	var rootKeyID string
	if len(rootKeyList) < 1 {
		cmd.Println("No root keys found. Generating a new root key...")
		rootPublicKey, err := nRepo.CryptoService.Create(data.CanonicalRootRole, "", data.ECDSAKey)
		rootKeyID = rootPublicKey.ID()
		if err != nil {
			return err
		}
	} else {
		// Choses the first root key available, which is initialization specific
		// but should return the HW one first.
		rootKeyID = rootKeyList[0]
		cmd.Printf("Root key found, using: %s\n", rootKeyID)
	}

	if err = nRepo.Initialize(rootKeyID); err != nil {
		return err
	}
	return nil
}
Beispiel #19
0
// runCreate is the code that implements the create command.
func runCreate(cmd *cobra.Command, args []string) error {
	dbMeta, err := retrieveDatabaseMetadata(create.file)
	if err != nil {
		return err
	}

	for _, col := range dbMeta.Cols {
		cmd.Println("Creating collection", col.Name)
		if err := createCollection(conn, dbMeta, &col, true); err != nil && err != ErrCollectionExists {
			return err
		}
	}

	return nil
}
Beispiel #20
0
// runCreate is the code that implements the create command.
func runCreate(cmd *cobra.Command, args []string) {
	dbMeta, err := retrieveDatabaseMetadata(create.file)
	if err != nil {
		dbCmd.Printf("Error reading collections : %s : ERROR : %v\n", create.file, err)
		return
	}

	for _, col := range dbMeta.Cols {
		cmd.Println("Creating collection", col.Name)
		if err := createCollection(conn, dbMeta, &col, true); err != nil && err != ErrCollectionExists {
			cmd.Println("ERROR:", err)
			return
		}
	}
}
Beispiel #21
0
// runUpsert is the code that implements the upsert command.
func runUpsert(cmd *cobra.Command, args []string) error {
	cmd.Printf("Upserting Items : Path[%s]\n", upsert.path)

	if upsert.path == "" {
		return fmt.Errorf("path must be provided")
	}

	file := upsert.path

	stat, err := os.Stat(file)
	if err != nil {
		return err
	}

	if !stat.IsDir() {
		item, err := disk.LoadItem("", file)
		if err != nil {
			return err
		}

		if err := runUpsertWeb(cmd, *item); err != nil {
			return err
		}

		cmd.Println("\n", "Upserting Items : Upserted")
		return nil
	}

	f := func(path string) error {
		item, err := disk.LoadItem("", path)
		if err != nil {
			return err
		}

		if err := runUpsertWeb(cmd, *item); err != nil {
			return err
		}

		return nil
	}

	if err := disk.LoadDir(file, f); err != nil {
		return err
	}

	cmd.Println("\n", "Upserting Items : Upserted")
	return nil
}
Beispiel #22
0
func (k *keyCommander) keysList(cmd *cobra.Command, args []string) error {
	if len(args) > 0 {
		return fmt.Errorf("")
	}

	config := k.configGetter()
	ks, err := k.getKeyStores(config, true)
	if err != nil {
		return err
	}

	cmd.Println("")
	prettyPrintKeys(ks, cmd.Out())
	cmd.Println("")
	return nil
}
Beispiel #23
0
func removeVolumes(ctx *cobra.Command, args []string) {
	if len(args) < 1 {
		ErrorExit(ctx, "Needs an argument <ID> at least to inspect")
	}

	volumes, err := getVolumes(ctx)
	if err != nil {
		log.Fatal(err)
	}

	var gotError = false

	for _, id := range args {
		volume := volumes.Find(id)
		if volume == nil {
			log.Errorf("No such volume: %s", id)
			gotError = true
			continue
		}

		if len(volume.MountedOn) > 0 {
			log.Errorf("The volume is in use, cannot remove: %s", volume.ID)
			gotError = true
			continue
		}

		if volume.IsBindMount {
			log.Errorf("The volume is bound, cannot remove: %s", volume.ID)
			gotError = true
			continue
		}

		if err := removeVolume(ctx, volume); err != nil {
			log.Error(err)
			gotError = true
		} else {
			ctx.Println(volume.ID)
		}
	}

	if gotError {
		log.Fatal("Error: failed to remove one or more volumes")
	}
}
Beispiel #24
0
func certList(cmd *cobra.Command, args []string) {
	if len(args) > 0 {
		cmd.Usage()
		os.Exit(1)
	}
	parseConfig()

	trustDir := mainViper.GetString("trust_dir")
	certManager, err := certs.NewManager(trustDir)
	if err != nil {
		fatalf("Failed to create a new truststore manager with directory: %s", trustDir)
	}

	trustedCerts := certManager.TrustedCertificateStore().GetCertificates()

	cmd.Println("")
	prettyPrintCerts(trustedCerts, cmd.Out())
	cmd.Println("")
}
Beispiel #25
0
func listHosts(ctx *cobra.Command, args []string) {
	config, err := client.LoadConfig(configPath)
	if err != nil {
		log.Fatal(err)
	}

	if boolQuiet {
		for _, host := range config.Hosts {
			ctx.Println(host.Name)
		}
		return
	}

	if boolYAML || boolJSON {
		if err := FormatPrint(ctx.Out(), config.Hosts); err != nil {
			log.Fatal(err)
		}
		return
	}

	var items [][]string
	for _, host := range config.Hosts {
		out := []string{
			FormatBool(host.Name == config.Default, "*", ""),
			host.Name,
			host.URL,
			FormatNonBreakingString(host.Description),
			FormatBool(host.TLS, "YES", ""),
		}
		items = append(items, out)
	}

	header := []string{
		"",
		"Name",
		"URL",
		"Description",
		"TLS",
	}

	PrintInTable(ctx.Out(), header, items, 0, tablewriter.ALIGN_DEFAULT)
}
Beispiel #26
0
func certList(cmd *cobra.Command, args []string) {
	if len(args) > 0 {
		cmd.Usage()
		os.Exit(1)
	}
	parseConfig()

	trustDir := mainViper.GetString("trust_dir")
	keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir)
	if err != nil {
		fatalf("Failed to create a new truststore manager with directory: %s", trustDir)
	}

	cmd.Println("")
	cmd.Println("# Trusted Certificates:")
	trustedCerts := keyStoreManager.TrustedCertificateStore().GetCertificates()
	for _, c := range trustedCerts {
		printCert(cmd, c)
	}
}
Beispiel #27
0
// delegationsList lists all the delegations for a particular GUN
func (d *delegationCommander) delegationsList(cmd *cobra.Command, args []string) error {
	if len(args) != 1 {
		cmd.Usage()
		return fmt.Errorf(
			"Please provide a Global Unique Name as an argument to list")
	}

	config, err := d.configGetter()
	if err != nil {
		return err
	}

	gun := args[0]

	rt, err := getTransport(config, gun, true)
	if err != nil {
		return err
	}

	trustPin, err := getTrustPinning(config)
	if err != nil {
		return err
	}

	// initialize repo with transport to get latest state of the world before listing delegations
	nRepo, err := notaryclient.NewNotaryRepository(
		config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, d.retriever, trustPin)
	if err != nil {
		return err
	}

	delegationRoles, err := nRepo.GetDelegationRoles()
	if err != nil {
		return fmt.Errorf("Error retrieving delegation roles for repository %s: %v", gun, err)
	}

	cmd.Println("")
	prettyPrintRoles(delegationRoles, cmd.Out(), "delegations")
	cmd.Println("")
	return nil
}
Beispiel #28
0
func (t *tufCommander) tufStatus(cmd *cobra.Command, args []string) error {
	if len(args) < 1 {
		cmd.Usage()
		return fmt.Errorf("Must specify a GUN")
	}

	config, err := t.configGetter()
	if err != nil {
		return err
	}
	gun := args[0]

	trustPin, err := getTrustPinning(config)
	if err != nil {
		return err
	}

	nRepo, err := notaryclient.NewNotaryRepository(
		config.GetString("trust_dir"), gun, getRemoteTrustServer(config), nil, t.retriever, trustPin)
	if err != nil {
		return err
	}

	cl, err := nRepo.GetChangelist()
	if err != nil {
		return err
	}

	if len(cl.List()) == 0 {
		cmd.Printf("No unpublished changes for %s\n", gun)
		return nil
	}

	cmd.Printf("Unpublished changes for %s:\n\n", gun)
	cmd.Printf("%-10s%-10s%-12s%s\n", "action", "scope", "type", "path")
	cmd.Println("----------------------------------------------------")
	for _, ch := range cl.List() {
		cmd.Printf("%-10s%-10s%-12s%s\n", ch.Action(), ch.Scope(), ch.Type(), ch.Path())
	}
	return nil
}
Beispiel #29
0
func tufPublish(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		cmd.Usage()
		fatalf("Must specify a GUN")
	}

	parseConfig()
	gun := args[0]

	cmd.Println("Pushing changes to", gun)

	nRepo, err := notaryclient.NewNotaryRepository(mainViper.GetString("trust_dir"), gun, getRemoteTrustServer(), getTransport(gun, false), retriever)
	if err != nil {
		fatalf(err.Error())
	}

	err = nRepo.Publish()
	if err != nil {
		fatalf(err.Error())
	}
}
Beispiel #30
0
// keyRemove deletes a private key based on ID
func keyRemove(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		cmd.Usage()
		fatalf("must specify the key ID of the key to remove")
	}

	parseConfig()
	keyID := args[0]

	// This is an invalid ID
	if len(keyID) != idSize {
		fatalf("invalid key ID provided: %s", keyID)
	}
	stores := getKeyStores(cmd, mainViper.GetString("trust_dir"), retriever, true)
	cmd.Println("")
	err := removeKeyInteractively(stores, keyID, os.Stdin, cmd.Out())
	cmd.Println("")
	if err != nil {
		fatalf(err.Error())
	}
}