mirror of https://github.com/docker/docs.git
				
				
				
			
		
			
				
	
	
		
			190 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			190 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
	
| package main
 | |
| 
 | |
| import (
 | |
| 	"crypto/x509"
 | |
| 	"fmt"
 | |
| 	"path/filepath"
 | |
| 
 | |
| 	"github.com/docker/notary"
 | |
| 	notaryclient "github.com/docker/notary/client"
 | |
| 	"github.com/docker/notary/passphrase"
 | |
| 	"github.com/docker/notary/trustmanager"
 | |
| 	"github.com/spf13/cobra"
 | |
| 	"github.com/spf13/viper"
 | |
| )
 | |
| 
 | |
| var cmdCertTemplate = usageTemplate{
 | |
| 	Use:   "cert",
 | |
| 	Short: "Operates on certificates.",
 | |
| 	Long:  `Operations on certificates.`,
 | |
| }
 | |
| 
 | |
| var cmdCertListTemplate = usageTemplate{
 | |
| 	Use:   "list",
 | |
| 	Short: "Lists certificates.",
 | |
| 	Long:  "Lists root certificates known to notary.",
 | |
| }
 | |
| 
 | |
| var cmdCertRemoveTemplate = usageTemplate{
 | |
| 	Use:   "remove [ certID ]",
 | |
| 	Short: "Removes the certificate with the given cert ID.",
 | |
| 	Long:  "Remove the certificate with the given cert ID from the local host.",
 | |
| }
 | |
| 
 | |
| type certCommander struct {
 | |
| 	// these need to be set
 | |
| 	configGetter func() (*viper.Viper, error)
 | |
| 	retriever    passphrase.Retriever
 | |
| 
 | |
| 	// these are for command line parsing - no need to set
 | |
| 	certRemoveGUN string
 | |
| 	certRemoveYes bool
 | |
| }
 | |
| 
 | |
| func (c *certCommander) GetCommand() *cobra.Command {
 | |
| 	cmd := cmdCertTemplate.ToCommand(nil)
 | |
| 	cmd.AddCommand(cmdCertListTemplate.ToCommand(c.certList))
 | |
| 
 | |
| 	cmdCertRemove := cmdCertRemoveTemplate.ToCommand(c.certRemove)
 | |
| 	cmdCertRemove.Flags().StringVarP(
 | |
| 		&c.certRemoveGUN, "gun", "g", "", "Globally unique name to delete certificates for")
 | |
| 	cmdCertRemove.Flags().BoolVarP(
 | |
| 		&c.certRemoveYes, "yes", "y", false, "Answer yes to the removal question (no confirmation)")
 | |
| 
 | |
| 	cmd.AddCommand(cmdCertRemove)
 | |
| 
 | |
| 	return cmd
 | |
| }
 | |
| 
 | |
| // certRemove deletes a certificate given a cert ID or a gun
 | |
| // If given a gun, certRemove will also remove local TUF data
 | |
| func (c *certCommander) certRemove(cmd *cobra.Command, args []string) error {
 | |
| 	// If the user hasn't provided -g with a gun, or a cert ID, show usage
 | |
| 	// If the user provided -g and a cert ID, also show usage
 | |
| 	if (len(args) < 1 && c.certRemoveGUN == "") || (len(args) > 0 && c.certRemoveGUN != "") {
 | |
| 		cmd.Usage()
 | |
| 		return fmt.Errorf("Must specify the cert ID or the GUN of the certificates to remove")
 | |
| 	}
 | |
| 	config, err := c.configGetter()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	trustDir := config.GetString("trust_dir")
 | |
| 	certPath := filepath.Join(trustDir, notary.TrustedCertsDir)
 | |
| 	certStore, err := trustmanager.NewX509FilteredFileStore(
 | |
| 		certPath,
 | |
| 		trustmanager.FilterCertsExpiredSha1,
 | |
| 	)
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("Failed to create a new truststore with directory: %s", trustDir)
 | |
| 	}
 | |
| 
 | |
| 	var certsToRemove []*x509.Certificate
 | |
| 	var certFoundByID *x509.Certificate
 | |
| 	var removeTrustData bool
 | |
| 
 | |
| 	// If there is no GUN, we expect a cert ID
 | |
| 	if c.certRemoveGUN == "" {
 | |
| 		certID := args[0]
 | |
| 		// Attempt to find this certificate
 | |
| 		certFoundByID, err = certStore.GetCertificateByCertID(certID)
 | |
| 		if err != nil {
 | |
| 			// This is an invalid ID, the user might have forgotten a character
 | |
| 			if len(certID) != notary.Sha256HexSize {
 | |
| 				return fmt.Errorf("Unable to retrieve certificate with invalid certificate ID provided: %s", certID)
 | |
| 			}
 | |
| 			return fmt.Errorf("Unable to retrieve certificate with cert ID: %s", certID)
 | |
| 		}
 | |
| 		// the GUN is the CN from the certificate
 | |
| 		c.certRemoveGUN = certFoundByID.Subject.CommonName
 | |
| 		certsToRemove = []*x509.Certificate{certFoundByID}
 | |
| 	}
 | |
| 
 | |
| 	toRemove, err := certStore.GetCertificatesByCN(c.certRemoveGUN)
 | |
| 	// We could not find any certificates matching the user's query, so propagate the error
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("%v", err)
 | |
| 	}
 | |
| 
 | |
| 	// If we specified a GUN or if the ID we specified is the only certificate with its CN, remove all GUN certs and trust data too
 | |
| 	if certFoundByID == nil || len(toRemove) == 1 {
 | |
| 		removeTrustData = true
 | |
| 		certsToRemove = toRemove
 | |
| 	}
 | |
| 
 | |
| 	// List all the certificates about to be removed
 | |
| 	cmd.Printf("The following certificates will be removed:\n\n")
 | |
| 	for _, cert := range certsToRemove {
 | |
| 		// This error can't occur because we're getting certs off of an
 | |
| 		// x509 store that indexes by ID.
 | |
| 		certID, _ := trustmanager.FingerprintCert(cert)
 | |
| 		cmd.Printf("%s - %s\n", cert.Subject.CommonName, certID)
 | |
| 	}
 | |
| 	// If we were given a GUN or the last ID for a GUN, inform the user that we'll also delete all TUF data
 | |
| 	if removeTrustData {
 | |
| 		cmd.Printf("\nAll local trust data will be removed for %s\n", c.certRemoveGUN)
 | |
| 	}
 | |
| 	cmd.Println("\nAre you sure you want to remove these certificates? (yes/no)")
 | |
| 
 | |
| 	// Ask for confirmation before removing certificates, unless -y is provided
 | |
| 	if !c.certRemoveYes {
 | |
| 		confirmed := askConfirm()
 | |
| 		if !confirmed {
 | |
| 			return fmt.Errorf("Aborting action.")
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if removeTrustData {
 | |
| 		// Remove all TUF data, so call RemoveTrustData on a NotaryRepository with the GUN
 | |
| 		// no online operations are performed so the transport argument is nil
 | |
| 		nRepo, err := notaryclient.NewNotaryRepository(
 | |
| 			trustDir, c.certRemoveGUN, getRemoteTrustServer(config), nil, c.retriever)
 | |
| 		if err != nil {
 | |
| 			return fmt.Errorf("Could not establish trust data for GUN %s", c.certRemoveGUN)
 | |
| 		}
 | |
| 		// DeleteTrustData will pick up all of the same certificates by GUN (CN) and remove them
 | |
| 		err = nRepo.DeleteTrustData()
 | |
| 		if err != nil {
 | |
| 			return fmt.Errorf("Failed to delete trust data for %s", c.certRemoveGUN)
 | |
| 		}
 | |
| 	} else {
 | |
| 		for _, cert := range certsToRemove {
 | |
| 			err = certStore.RemoveCert(cert)
 | |
| 			if err != nil {
 | |
| 				return fmt.Errorf("Failed to remove cert %s", cert)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| 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
 | |
| }
 |