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, 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, t.retriever, trustPin) if err != nil { return err } return publishAndPrintToCLI(cmd, nRepo, gun) }
func (t *tufCommander) tufRemove(cmd *cobra.Command, args []string) error { if len(args) < 2 { return fmt.Errorf("Must specify a GUN and target") } config, err := t.configGetter() if err != nil { return err } gun := args[0] targetName := args[1] trustPin, err := getTrustPinning(config) if err != nil { return err } // no online operation are performed by remove so the transport argument // should be nil. repo, err := notaryclient.NewFileCachedNotaryRepository( config.GetString("trust_dir"), gun, getRemoteTrustServer(config), nil, t.retriever, trustPin) if err != nil { return err } // If roles is empty, we default to removing from targets if err = repo.RemoveTarget(targetName, t.roles...); err != nil { return err } cmd.Printf("Removal of %s from %s staged for next publish.\n", targetName, gun) return maybeAutoPublish(cmd, t.autoPublish, gun, config, t.retriever) }
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) }
// initialize a repo with keys, so they can be rotated func setUpRepo(t *testing.T, tempBaseDir, gun string, ret notary.PassRetriever) ( *httptest.Server, map[string]string) { // Set up server ctx := context.WithValue( context.Background(), notary.CtxKeyMetaStore, storage.NewMemStorage()) // Do not pass one of the const KeyAlgorithms here as the value! Passing a // string is in itself good test that we are handling it correctly as we // will be receiving a string from the configuration. ctx = context.WithValue(ctx, notary.CtxKeyKeyAlgo, "ecdsa") // Eat the logs instead of spewing them out l := logrus.New() l.Out = bytes.NewBuffer(nil) ctx = ctxu.WithLogger(ctx, logrus.NewEntry(l)) cryptoService := cryptoservice.NewCryptoService(trustmanager.NewKeyMemoryStore(ret)) ts := httptest.NewServer(server.RootHandler(ctx, nil, cryptoService, nil, nil, nil)) repo, err := client.NewFileCachedNotaryRepository( tempBaseDir, gun, ts.URL, http.DefaultTransport, ret, trustpinning.TrustPinConfig{}) require.NoError(t, err, "error creating repo: %s", err) rootPubKey, err := repo.CryptoService.Create("root", "", data.ECDSAKey) require.NoError(t, err, "error generating root key: %s", err) err = repo.Initialize([]string{rootPubKey.ID()}) require.NoError(t, err) return ts, repo.CryptoService.ListAllKeys() }
// The command line uses NotaryRepository's RotateKey - this is just testing // that multiple keys can be rotated at once locally func TestRotateKeyBothKeys(t *testing.T) { setUp(t) // Temporary directory where test files will be created tempBaseDir, err := ioutil.TempDir("", "notary-test-") defer os.RemoveAll(tempBaseDir) require.NoError(t, err, "failed to create a temporary directory: %s", err) gun := "docker.com/notary" ret := passphrase.ConstantRetriever("pass") ts, initialKeys := setUpRepo(t, tempBaseDir, gun, ret) defer ts.Close() k := &keyCommander{ configGetter: func() (*viper.Viper, error) { v := viper.New() v.SetDefault("trust_dir", tempBaseDir) v.SetDefault("remote_server.url", ts.URL) return v, nil }, getRetriever: func() notary.PassRetriever { return ret }, } require.NoError(t, k.keysRotate(&cobra.Command{}, []string{gun, data.CanonicalTargetsRole})) require.NoError(t, k.keysRotate(&cobra.Command{}, []string{gun, data.CanonicalSnapshotRole})) repo, err := client.NewFileCachedNotaryRepository(tempBaseDir, gun, ts.URL, nil, ret, trustpinning.TrustPinConfig{}) require.NoError(t, err, "error creating repo: %s", err) cl, err := repo.GetChangelist() require.NoError(t, err, "unable to get changelist: %v", err) require.Len(t, cl.List(), 0) // two new keys have been created, and the old keys should still be gone newKeys := repo.CryptoService.ListAllKeys() // there should be 3 keys - snapshot, targets, and root require.Len(t, newKeys, 3) // the old snapshot/targets keys should be gone for keyID, role := range initialKeys { r, ok := newKeys[keyID] switch r { case data.CanonicalSnapshotRole, data.CanonicalTargetsRole: require.False(t, ok, "original key %s still there", keyID) case data.CanonicalRootRole: require.Equal(t, role, r) require.True(t, ok, "old root key has changed") } } found := make(map[string]bool) for _, role := range newKeys { found[role] = true } require.True(t, found[data.CanonicalTargetsRole], "targets key was not created") require.True(t, found[data.CanonicalSnapshotRole], "snapshot key was not created") require.True(t, found[data.CanonicalRootRole], "root key was removed somehow") }
func (t *tufCommander) tufAddByHash(cmd *cobra.Command, args []string) error { if len(args) < 3 || t.sha256 == "" && t.sha512 == "" { cmd.Usage() return fmt.Errorf("Must specify a GUN, target, byte size of target data, and at least one hash") } config, err := t.configGetter() if err != nil { return err } gun := args[0] targetName := args[1] targetSize := args[2] targetInt64Len, err := strconv.ParseInt(targetSize, 0, 64) 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, t.retriever, trustPin) if err != nil { return err } targetHashes, err := getTargetHashes(t) if err != nil { return err } // Manually construct the target with the given byte size and hashes target := ¬aryclient.Target{Name: targetName, Hashes: targetHashes, Length: targetInt64Len} // If roles is empty, we default to adding to targets if err = nRepo.AddTarget(target, t.roles...); err != nil { return err } // Include the hash algorithms we're using for pretty printing hashesUsed := []string{} for hashName := range targetHashes { hashesUsed = append(hashesUsed, hashName) } cmd.Printf( "Addition of target \"%s\" by %s hash to repository \"%s\" staged for next publish.\n", targetName, strings.Join(hashesUsed, ", "), gun) return maybeAutoPublish(cmd, t.autoPublish, gun, config, t.retriever) }
// 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) }
// The command line uses NotaryRepository's RotateKey - this is just testing // that the correct config variables are passed for the client to request a key // from the remote server. func TestRotateKeyRemoteServerManagesKey(t *testing.T) { for _, role := range []string{data.CanonicalSnapshotRole, data.CanonicalTimestampRole} { setUp(t) // Temporary directory where test files will be created tempBaseDir, err := ioutil.TempDir("", "notary-test-") defer os.RemoveAll(tempBaseDir) require.NoError(t, err, "failed to create a temporary directory: %s", err) gun := "docker.com/notary" ret := passphrase.ConstantRetriever("pass") ts, initialKeys := setUpRepo(t, tempBaseDir, gun, ret) defer ts.Close() require.Len(t, initialKeys, 3) k := &keyCommander{ configGetter: func() (*viper.Viper, error) { v := viper.New() v.SetDefault("trust_dir", tempBaseDir) v.SetDefault("remote_server.url", ts.URL) return v, nil }, getRetriever: func() notary.PassRetriever { return ret }, rotateKeyServerManaged: true, } require.NoError(t, k.keysRotate(&cobra.Command{}, []string{gun, role, "-r"})) repo, err := client.NewFileCachedNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, ret, trustpinning.TrustPinConfig{}) require.NoError(t, err, "error creating repo: %s", err) cl, err := repo.GetChangelist() require.NoError(t, err, "unable to get changelist: %v", err) require.Len(t, cl.List(), 0, "expected the changes to have been published") finalKeys := repo.CryptoService.ListAllKeys() // no keys have been created, since a remote key was specified if role == data.CanonicalSnapshotRole { require.Len(t, finalKeys, 2) for k, r := range initialKeys { if r != data.CanonicalSnapshotRole { _, ok := finalKeys[k] require.True(t, ok) } } } else { require.Len(t, finalKeys, 3) for k := range initialKeys { _, ok := finalKeys[k] require.True(t, ok) } } } }
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.NewFileCachedNotaryRepository( 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) tw := initTabWriter( []string{"#", "ACTION", "SCOPE", "TYPE", "PATH"}, cmd.Out(), ) for i, ch := range cl.List() { fmt.Fprintf( tw, fiveItemRow, fmt.Sprintf("%d", i), ch.Action(), ch.Scope(), ch.Type(), ch.Path(), ) } tw.Flush() return nil }
func (k *keyCommander) keysRotate(cmd *cobra.Command, args []string) error { if len(args) < 2 { cmd.Usage() return fmt.Errorf("Must specify a GUN and a key role to rotate") } config, err := k.configGetter() if err != nil { return err } gun := args[0] rotateKeyRole := args[1] rt, err := getTransport(config, gun, admin) 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, k.getRetriever(), trustPin) if err != nil { return err } if rotateKeyRole == data.CanonicalRootRole { cmd.Print("Warning: you are about to rotate your root key.\n\n" + "You must use your old key to sign this root rotation. We recommend that\n" + "you sign all your future root changes with this key as well, so that\n" + "clients can have a smoother update process. Please do not delete\n" + "this key after rotating.\n\n" + "Are you sure you want to proceed? (yes/no) ") if !askConfirm(k.input) { fmt.Fprintln(cmd.Out(), "\nAborting action.") return nil } } if err := nRepo.RotateKey(rotateKeyRole, k.rotateKeyServerManaged); err != nil { return err } cmd.Printf("Successfully rotated %s key for repository %s\n", rotateKeyRole, gun) return nil }
func (d *delegationCommander) delegationPurgeKeys(cmd *cobra.Command, args []string) error { if len(args) != 1 { cmd.Usage() return fmt.Errorf("Please provide a single Global Unique Name as an argument to remove") } if len(d.keyIDs) == 0 { cmd.Usage() return fmt.Errorf("Please provide at least one key ID to be removed using the --key flag") } gun := args[0] config, err := d.configGetter() 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), nil, d.retriever, trustPin, ) if err != nil { return err } err = nRepo.RemoveDelegationKeys("targets/*", d.keyIDs) if err != nil { return fmt.Errorf("failed to remove keys from delegations: %v", err) } fmt.Printf( "Removal of the following keys from all delegations in %s staged for next publish:\n\t- %s\n", gun, strings.Join(d.keyIDs, "\n\t- "), ) return maybeAutoPublish(cmd, d.autoPublish, gun, config, d.retriever) }
func (t *tufCommander) tufVerify(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 } payload, err := getPayload(t) if err != nil { return err } gun := args[0] targetName := args[1] rt, err := getTransport(config, gun, readOnly) 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, t.retriever, trustPin) if err != nil { return err } target, err := nRepo.GetTargetByName(targetName) if err != nil { return fmt.Errorf("error retrieving target by name:%s, error:%v", targetName, err) } if err := data.CheckHashes(payload, targetName, target.Hashes); err != nil { return fmt.Errorf("data not present in the trusted collection, %v", err) } return feedback(t, payload) }
func (t *tufCommander) tufReset(cmd *cobra.Command, args []string) error { if len(args) < 1 { cmd.Usage() return fmt.Errorf("Must specify a GUN") } if !t.resetAll && len(t.deleteIdx) < 1 { cmd.Usage() return fmt.Errorf("Must specify changes to reset with -n or the --all flag") } config, err := t.configGetter() if err != nil { return err } gun := args[0] trustPin, err := getTrustPinning(config) if err != nil { return err } nRepo, err := notaryclient.NewFileCachedNotaryRepository( 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 t.resetAll { err = cl.Clear(t.archiveChangelist) } else { err = cl.Remove(t.deleteIdx) } // If it was a success, print to terminal if err == nil { cmd.Printf("Successfully reset specified changes for repository %s\n", gun) } return err }
func (t *tufCommander) tufDeleteGUN(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 } // Only initialize a roundtripper if we get the remote flag var rt http.RoundTripper var remoteDeleteInfo string if t.deleteRemote { rt, err = getTransport(config, gun, admin) if err != nil { return err } remoteDeleteInfo = " and remote" } nRepo, err := notaryclient.NewFileCachedNotaryRepository( config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, t.retriever, trustPin) if err != nil { return err } cmd.Printf("Deleting trust data for repository %s\n", gun) if err := nRepo.DeleteTrustData(t.deleteRemote); err != nil { return err } cmd.Printf("Successfully deleted local%s trust data for repository %s\n", remoteDeleteInfo, gun) return nil }
// 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, readOnly) 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.NewFileCachedNotaryRepository( 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 }
func (t *tufCommander) tufAdd(cmd *cobra.Command, args []string) error { if len(args) < 3 { cmd.Usage() return fmt.Errorf("Must specify a GUN, target, and path to target data") } config, err := t.configGetter() if err != nil { return err } gun := args[0] targetName := args[1] targetPath := args[2] 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, t.retriever, trustPin) if err != nil { return err } target, err := notaryclient.NewTarget(targetName, targetPath) if err != nil { return err } // If roles is empty, we default to adding to targets if err = nRepo.AddTarget(target, t.roles...); err != nil { return err } cmd.Printf("Addition of target \"%s\" to repository \"%s\" staged for next publish.\n", targetName, gun) return maybeAutoPublish(cmd, t.autoPublish, gun, config, t.retriever) }
// RotateKey when rotating a root requires extra confirmation func TestRotateKeyRootIsInteractive(t *testing.T) { setUp(t) // Temporary directory where test files will be created tempBaseDir, err := ioutil.TempDir("", "notary-test-") defer os.RemoveAll(tempBaseDir) require.NoError(t, err, "failed to create a temporary directory: %s", err) gun := "docker.com/notary" ret := passphrase.ConstantRetriever("pass") ts, _ := setUpRepo(t, tempBaseDir, gun, ret) defer ts.Close() k := &keyCommander{ configGetter: func() (*viper.Viper, error) { v := viper.New() v.SetDefault("trust_dir", tempBaseDir) v.SetDefault("remote_server.url", ts.URL) return v, nil }, getRetriever: func() notary.PassRetriever { return ret }, input: bytes.NewBuffer([]byte("\n")), } c := &cobra.Command{} out := bytes.NewBuffer(make([]byte, 0, 10)) c.SetOutput(out) require.NoError(t, k.keysRotate(c, []string{gun, data.CanonicalRootRole})) require.Contains(t, out.String(), "Aborting action") repo, err := client.NewFileCachedNotaryRepository(tempBaseDir, gun, ts.URL, nil, ret, trustpinning.TrustPinConfig{}) require.NoError(t, err, "error creating repo: %s", err) // There should still just be one root key (and one targets and one snapshot) allKeys := repo.CryptoService.ListAllKeys() require.Len(t, allKeys, 3) }
func (t *tufCommander) tufList(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, readOnly) 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, t.retriever, trustPin) if err != nil { return err } // Retrieve the remote list of signed targets, prioritizing the passed-in list over targets roles := append(t.roles, data.CanonicalTargetsRole) targetList, err := nRepo.ListTargets(roles...) if err != nil { return err } prettyPrintTargets(targetList, cmd.Out()) return nil }
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, readOnly) 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, t.retriever, trustPin) 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 }
func (t *tufCommander) tufWitness(cmd *cobra.Command, args []string) error { if len(args) < 2 { cmd.Usage() return fmt.Errorf("Please provide a GUN and at least one role to witness") } config, err := t.configGetter() if err != nil { return err } trustPin, err := getTrustPinning(config) if err != nil { return err } gun := args[0] roles := args[1:] // 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, t.retriever, trustPin) if err != nil { return err } success, err := nRepo.Witness(roles...) if err != nil { cmd.Printf("Some roles have failed to be marked for witnessing: %s", err.Error()) } cmd.Printf( "The following roles were successfully marked for witnessing on the next publish:\n\t- %s\n", strings.Join(success, "\n\t- "), ) return maybeAutoPublish(cmd, t.autoPublish, gun, config, t.retriever) }
// delegationAdd creates a new delegation by adding a public key from a certificate to a specific role in a GUN func (d *delegationCommander) delegationAdd(cmd *cobra.Command, args []string) error { // We must have at least the gun and role name, and at least one key or path (or the --all-paths flag) to add if len(args) < 2 || len(args) < 3 && d.paths == nil && !d.allPaths { cmd.Usage() return fmt.Errorf("must specify the Global Unique Name and the role of the delegation along with the public key certificate paths and/or a list of paths to add") } config, err := d.configGetter() if err != nil { return err } gun := args[0] role := args[1] pubKeys, err := ingestPublicKeys(args) if err != nil { return err } checkAllPaths(d) 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 } // Add the delegation to the repository err = nRepo.AddDelegation(role, pubKeys, d.paths) if err != nil { return fmt.Errorf("failed to create delegation: %v", err) } // Make keyID slice for better CLI print pubKeyIDs := []string{} for _, pubKey := range pubKeys { pubKeyID, err := utils.CanonicalKeyID(pubKey) if err != nil { return err } pubKeyIDs = append(pubKeyIDs, pubKeyID) } cmd.Println("") addingItems := "" if len(pubKeyIDs) > 0 { addingItems = addingItems + fmt.Sprintf("with keys %s, ", pubKeyIDs) } if d.paths != nil || d.allPaths { addingItems = addingItems + fmt.Sprintf( "with paths [%s], ", strings.Join(prettyPaths(d.paths), "\n"), ) } cmd.Printf( "Addition of delegation role %s %sto repository \"%s\" staged for next publish.\n", role, addingItems, gun) cmd.Println("") return maybeAutoPublish(cmd, d.autoPublish, gun, config, d.retriever) }
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, 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, t.retriever, trustPin) if err != nil { return err } var rootKeyList []string if t.rootKey != "" { privKey, err := readRootKey(t.rootKey, t.retriever) if err != nil { return err } err = nRepo.CryptoService.AddKey(data.CanonicalRootRole, "", privKey) if err != nil { return fmt.Errorf("Error importing key: %v", err) } rootKeyList = []string{privKey.ID()} } else { 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) if err != nil { return err } rootKeyID = rootPublicKey.ID() } else { // Chooses 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([]string{rootKeyID}); err != nil { return err } return maybeAutoPublish(cmd, t.autoPublish, gun, config, t.retriever) }