Ejemplo n.º 1
0
// NewKeyStoreManager returns an initialized KeyStoreManager, or an error
// if it fails to create the KeyFileStores or load certificates
func NewKeyStoreManager(baseDir string) (*KeyStoreManager, error) {
	trustPath := filepath.Join(baseDir, trustDir)

	// Load all CAs that aren't expired and don't use SHA1
	trustedCAStore, err := trustmanager.NewX509FilteredFileStore(trustPath, func(cert *x509.Certificate) bool {
		return cert.IsCA && cert.BasicConstraintsValid && cert.SubjectKeyId != nil &&
			time.Now().Before(cert.NotAfter) &&
			cert.SignatureAlgorithm != x509.SHA1WithRSA &&
			cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
			cert.SignatureAlgorithm != x509.ECDSAWithSHA1
	})
	if err != nil {
		return nil, err
	}

	// Load all individual (non-CA) certificates that aren't expired and don't use SHA1
	trustedCertificateStore, err := trustmanager.NewX509FilteredFileStore(trustPath, func(cert *x509.Certificate) bool {
		return !cert.IsCA &&
			time.Now().Before(cert.NotAfter) &&
			cert.SignatureAlgorithm != x509.SHA1WithRSA &&
			cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
			cert.SignatureAlgorithm != x509.ECDSAWithSHA1
	})
	if err != nil {
		return nil, err
	}

	return &KeyStoreManager{
		trustedCAStore:          trustedCAStore,
		trustedCertificateStore: trustedCertificateStore,
	}, nil
}
Ejemplo n.º 2
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
}
Ejemplo n.º 3
0
// Generates a X509Store in a temporary directory and returns the
// store and certificates for two keys which have been added to the keystore.
// Also returns the temporary directory so it can be cleaned up.
func filestoreWithTwoCerts(t *testing.T, gun, keyAlg string) (
	string, trustmanager.X509Store, *cryptoservice.CryptoService, []*x509.Certificate) {
	tempBaseDir, err := ioutil.TempDir("", "notary-test-")
	assert.NoError(t, err, "failed to create a temporary directory: %s", err)

	fileKeyStore, err := trustmanager.NewKeyFileStore(tempBaseDir, passphraseRetriever)
	assert.NoError(t, err)

	cryptoService := cryptoservice.NewCryptoService(gun, fileKeyStore)

	// Create a store
	trustPath := filepath.Join(tempBaseDir, notary.TrustedCertsDir)
	certStore, err := trustmanager.NewX509FilteredFileStore(
		trustPath,
		trustmanager.FilterCertsExpiredSha1,
	)
	assert.NoError(t, err)

	certificates := make([]*x509.Certificate, 2)
	for i := 0; i < 2; i++ {
		pubKey, err := cryptoService.Create("root", keyAlg)
		assert.NoError(t, err)

		key, _, err := fileKeyStore.GetKey(pubKey.ID())
		assert.NoError(t, err)

		cert, err := cryptoservice.GenerateTestingCertificate(key.CryptoSigner(), gun)
		assert.NoError(t, err)

		certificates[i] = cert
	}
	return tempBaseDir, certStore, cryptoService, certificates
}
Ejemplo n.º 4
0
// NewKeyStoreManager returns an initialized KeyStoreManager, or an error
// if it fails to create the KeyFileStores or load certificates
func NewKeyStoreManager(baseDir string, passphraseRetriever passphrase.Retriever) (*KeyStoreManager, error) {
	nonRootKeysPath := filepath.Join(baseDir, privDir, nonRootKeysSubdir)
	nonRootKeyStore, err := trustmanager.NewKeyFileStore(nonRootKeysPath, passphraseRetriever)
	if err != nil {
		return nil, err
	}

	// Load the keystore that will hold all of our encrypted Root Private Keys
	rootKeysPath := filepath.Join(baseDir, privDir, rootKeysSubdir)
	rootKeyStore, err := trustmanager.NewKeyFileStore(rootKeysPath, passphraseRetriever)
	if err != nil {
		return nil, err
	}

	trustPath := filepath.Join(baseDir, trustDir)

	// Load all CAs that aren't expired and don't use SHA1
	trustedCAStore, err := trustmanager.NewX509FilteredFileStore(trustPath, func(cert *x509.Certificate) bool {
		return cert.IsCA && cert.BasicConstraintsValid && cert.SubjectKeyId != nil &&
			time.Now().Before(cert.NotAfter) &&
			cert.SignatureAlgorithm != x509.SHA1WithRSA &&
			cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
			cert.SignatureAlgorithm != x509.ECDSAWithSHA1
	})
	if err != nil {
		return nil, err
	}

	// Load all individual (non-CA) certificates that aren't expired and don't use SHA1
	trustedCertificateStore, err := trustmanager.NewX509FilteredFileStore(trustPath, func(cert *x509.Certificate) bool {
		return !cert.IsCA &&
			time.Now().Before(cert.NotAfter) &&
			cert.SignatureAlgorithm != x509.SHA1WithRSA &&
			cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
			cert.SignatureAlgorithm != x509.ECDSAWithSHA1
	})
	if err != nil {
		return nil, err
	}

	return &KeyStoreManager{
		rootKeyStore:            rootKeyStore,
		nonRootKeyStore:         nonRootKeyStore,
		trustedCAStore:          trustedCAStore,
		trustedCertificateStore: trustedCertificateStore,
	}, nil
}
Ejemplo n.º 5
0
func init() {
	logrus.SetLevel(logrus.ErrorLevel)
	logrus.SetOutput(os.Stderr)
	// Retrieve current user to get home directory
	usr, err := user.Current()
	if err != nil {
		fatalf("cannot get current user: %v", err)
	}

	// Get home directory for current user
	homeDir := usr.HomeDir
	if homeDir == "" {
		fatalf("cannot get current user home directory")
	}

	// Setup the configuration details
	viper.SetConfigName(configFileName)
	viper.AddConfigPath(path.Join(homeDir, path.Dir(configPath)))
	viper.SetConfigType("json")

	// Find and read the config file
	err = viper.ReadInConfig()
	if err != nil {
		// Ignore if the configuration file doesn't exist, we can use the defaults
		if !os.IsNotExist(err) {
			fatalf("fatal error config file: %v", err)
		}
	}

	// Set up the defaults for our config
	viper.SetDefault("trustDir", path.Join(homeDir, path.Dir(trustDir)))
	viper.SetDefault("privDir", path.Join(homeDir, path.Dir(privDir)))
	viper.SetDefault("tufDir", path.Join(homeDir, path.Dir(tufDir)))

	// Get the final value for the CA directory
	finalTrustDir := viper.GetString("trustDir")
	finalPrivDir := viper.GetString("privDir")

	// Load all CAs that aren't expired and don't use SHA1
	// We could easily add "return cert.IsCA && cert.BasicConstraintsValid" in order
	// to have only valid CA certificates being loaded
	caStore, err = trustmanager.NewX509FilteredFileStore(finalTrustDir, func(cert *x509.Certificate) bool {
		return time.Now().Before(cert.NotAfter) &&
			cert.SignatureAlgorithm != x509.SHA1WithRSA &&
			cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
			cert.SignatureAlgorithm != x509.ECDSAWithSHA1
	})
	if err != nil {
		fatalf("could not create X509FileStore: %v", err)
	}

	privKeyStore, err = trustmanager.NewPrivateFileStore(finalPrivDir, "key")
	if err != nil {
		fatalf("could not create FileStore: %v", err)
	}

}
Ejemplo n.º 6
0
func (r *NotaryRepository) loadKeys(trustDir, rootKeysDir string) error {
	// Load all CAs that aren't expired and don't use SHA1
	caStore, err := trustmanager.NewX509FilteredFileStore(trustDir, func(cert *x509.Certificate) bool {
		return cert.IsCA && cert.BasicConstraintsValid && cert.SubjectKeyId != nil &&
			time.Now().Before(cert.NotAfter) &&
			cert.SignatureAlgorithm != x509.SHA1WithRSA &&
			cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
			cert.SignatureAlgorithm != x509.ECDSAWithSHA1
	})
	if err != nil {
		return err
	}

	// Load all individual (non-CA) certificates that aren't expired and don't use SHA1
	certificateStore, err := trustmanager.NewX509FilteredFileStore(trustDir, func(cert *x509.Certificate) bool {
		return !cert.IsCA &&
			time.Now().Before(cert.NotAfter) &&
			cert.SignatureAlgorithm != x509.SHA1WithRSA &&
			cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
			cert.SignatureAlgorithm != x509.ECDSAWithSHA1
	})
	if err != nil {
		return err
	}

	// Load the keystore that will hold all of our encrypted Root Private Keys
	rootKeyStore, err := trustmanager.NewKeyFileStore(rootKeysDir)
	if err != nil {
		return err
	}

	r.caStore = caStore
	r.certificateStore = certificateStore
	r.rootKeyStore = rootKeyStore

	return nil
}
Ejemplo n.º 7
0
// repositoryFromKeystores is a helper function for NewNotaryRepository that
// takes some basic NotaryRepository parameters as well as keystores (in order
// of usage preference), and returns a NotaryRepository.
func repositoryFromKeystores(baseDir, gun, baseURL string, rt http.RoundTripper,
	keyStores []trustmanager.KeyStore) (*NotaryRepository, error) {

	certPath := filepath.Join(baseDir, notary.TrustedCertsDir)
	certStore, err := trustmanager.NewX509FilteredFileStore(
		certPath,
		trustmanager.FilterCertsExpiredSha1,
	)
	if err != nil {
		return nil, err
	}

	cryptoService := cryptoservice.NewCryptoService(gun, keyStores...)

	nRepo := &NotaryRepository{
		gun:           gun,
		baseDir:       baseDir,
		baseURL:       baseURL,
		tufRepoPath:   filepath.Join(baseDir, tufDir, filepath.FromSlash(gun)),
		CryptoService: cryptoService,
		roundTrip:     rt,
		CertStore:     certStore,
	}

	fileStore, err := store.NewFilesystemStore(
		nRepo.tufRepoPath,
		"metadata",
		"json",
		"",
	)
	if err != nil {
		return nil, err
	}
	nRepo.fileStore = fileStore

	return nRepo, nil
}
Ejemplo n.º 8
0
func TestValidateRoot(t *testing.T) {
	var testSignedRoot data.Signed
	var signedRootBytes bytes.Buffer

	// Temporary directory where test files will be created
	tempBaseDir, err := ioutil.TempDir("", "notary-test-")
	defer os.RemoveAll(tempBaseDir)
	assert.NoError(t, err, "failed to create a temporary directory: %s", err)

	// Create a X509Store
	trustPath := filepath.Join(tempBaseDir, notary.TrustedCertsDir)
	certStore, err := trustmanager.NewX509FilteredFileStore(
		trustPath,
		trustmanager.FilterCertsExpiredSha1,
	)
	assert.NoError(t, err)

	// Execute our template
	templ, _ := template.New("SignedRSARootTemplate").Parse(signedRSARootTemplate)
	templ.Execute(&signedRootBytes, SignedRSARootTemplate{RootPem: validPEMEncodedRSARoot})

	// Unmarshal our signedroot
	json.Unmarshal(signedRootBytes.Bytes(), &testSignedRoot)

	// This call to ValidateRoot will succeed since we are using a valid PEM
	// encoded certificate, and have no other certificates for this CN
	err = ValidateRoot(certStore, &testSignedRoot, "docker.com/notary")
	assert.NoError(t, err)

	// This call to ValidateRoot will fail since we are passing in a dnsName that
	// doesn't match the CN of the certificate.
	err = ValidateRoot(certStore, &testSignedRoot, "diogomonica.com/notary")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, &ErrValidationFail{Reason: "unable to retrieve valid leaf certificates"})
	}

	//
	// This call to ValidateRoot will fail since we are passing an unparsable RootSigned
	//
	// Execute our template deleting the old buffer first
	signedRootBytes.Reset()
	templ, _ = template.New("SignedRSARootTemplate").Parse(signedRSARootTemplate)
	templ.Execute(&signedRootBytes, SignedRSARootTemplate{RootPem: "------ ABSOLUTELY NOT A PEM -------"})
	// Unmarshal our signedroot
	json.Unmarshal(signedRootBytes.Bytes(), &testSignedRoot)

	err = ValidateRoot(certStore, &testSignedRoot, "docker.com/notary")
	assert.Error(t, err, "illegal base64 data at input byte")

	//
	// This call to ValidateRoot will fail since we are passing an invalid PEM cert
	//
	// Execute our template deleting the old buffer first
	signedRootBytes.Reset()
	templ, _ = template.New("SignedRSARootTemplate").Parse(signedRSARootTemplate)
	templ.Execute(&signedRootBytes, SignedRSARootTemplate{RootPem: "LS0tLS1CRUdJTiBDRVJU"})
	// Unmarshal our signedroot
	json.Unmarshal(signedRootBytes.Bytes(), &testSignedRoot)

	err = ValidateRoot(certStore, &testSignedRoot, "docker.com/notary")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, &ErrValidationFail{Reason: "unable to retrieve valid leaf certificates"})
	}

	//
	// This call to ValidateRoot will fail since we are passing only CA certificate
	// This will fail due to the lack of a leaf certificate
	//
	// Execute our template deleting the old buffer first
	signedRootBytes.Reset()
	templ, _ = template.New("SignedRSARootTemplate").Parse(signedRSARootTemplate)
	templ.Execute(&signedRootBytes, SignedRSARootTemplate{RootPem: validCAPEMEncodeRSARoot})
	// Unmarshal our signedroot
	json.Unmarshal(signedRootBytes.Bytes(), &testSignedRoot)

	err = ValidateRoot(certStore, &testSignedRoot, "docker.com/notary")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, &ErrValidationFail{Reason: "unable to retrieve valid leaf certificates"})
	}

	//
	// This call to ValidateRoot will suceed in getting to the TUF validation, since
	// we are using a valid PEM encoded certificate chain of intermediate + leaf cert
	// that are signed by a trusted root authority and the leaf cert has a correct CN.
	// It will, however, fail to validate, because it has an invalid TUF signature
	//
	// Execute our template deleting the old buffer first
	signedRootBytes.Reset()
	templ, _ = template.New("SignedRSARootTemplate").Parse(signedRSARootTemplate)
	templ.Execute(&signedRootBytes, SignedRSARootTemplate{RootPem: validIntermediateAndCertRSA})

	// Unmarshal our signedroot
	json.Unmarshal(signedRootBytes.Bytes(), &testSignedRoot)

	err = ValidateRoot(certStore, &testSignedRoot, "secure.example.com")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, &ErrValidationFail{Reason: "failed to validate integrity of roots"})
	}
}
Ejemplo n.º 9
0
// 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
}
Ejemplo n.º 10
0
func init() {
	logrus.SetLevel(logrus.DebugLevel)
	logrus.SetOutput(os.Stderr)
	// Retrieve current user to get home directory
	usr, err := user.Current()
	if err != nil {
		fatalf("cannot get current user: %v", err)
	}

	// Get home directory for current user
	homeDir := usr.HomeDir
	if homeDir == "" {
		fatalf("cannot get current user home directory")
	}

	// Setup the configuration details
	viper.SetConfigName(configFileName)
	viper.AddConfigPath(path.Join(homeDir, path.Dir(configPath)))
	viper.SetConfigType("json")

	// Find and read the config file
	err = viper.ReadInConfig()
	if err != nil {
		// Ignore if the configuration file doesn't exist, we can use the defaults
		if !os.IsNotExist(err) {
			fatalf("fatal error config file: %v", err)
		}
	}

	// Set up the defaults for our config
	viper.SetDefault("baseTrustDir", path.Join(homeDir, path.Dir(configPath)))

	// Get the final value for the CA directory
	finalTrustDir := path.Join(viper.GetString("baseTrustDir"), trustDir)
	finalPrivDir := path.Join(viper.GetString("baseTrustDir"), privDir)

	// Load all CAs that aren't expired and don't use SHA1
	caStore, err = trustmanager.NewX509FilteredFileStore(finalTrustDir, func(cert *x509.Certificate) bool {
		return cert.IsCA && cert.BasicConstraintsValid && cert.SubjectKeyId != nil &&
			time.Now().Before(cert.NotAfter) &&
			cert.SignatureAlgorithm != x509.SHA1WithRSA &&
			cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
			cert.SignatureAlgorithm != x509.ECDSAWithSHA1
	})
	if err != nil {
		fatalf("could not create CA X509FileStore: %v", err)
	}

	// Load all individual (nonCA) certificates that aren't expired and don't use SHA1
	certificateStore, err = trustmanager.NewX509FilteredFileStore(finalTrustDir, func(cert *x509.Certificate) bool {
		return !cert.IsCA &&
			time.Now().Before(cert.NotAfter) &&
			cert.SignatureAlgorithm != x509.SHA1WithRSA &&
			cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
			cert.SignatureAlgorithm != x509.ECDSAWithSHA1
	})
	if err != nil {
		fatalf("could not create Certificate X509FileStore: %v", err)
	}

	privKeyStore, err = trustmanager.NewKeyFileStore(finalPrivDir)
	if err != nil {
		fatalf("could not create KeyFileStore: %v", err)
	}

}