Example #1
0
// NewSignerFromFile reads the issuer cert, the responder cert and the responder key
// from PEM files, and takes an interval in seconds
func NewSignerFromFile(issuerFile, responderFile, keyFile string, interval time.Duration) (Signer, error) {
	log.Debug("Loading issuer cert: ", issuerFile)
	issuerBytes, err := ioutil.ReadFile(issuerFile)
	if err != nil {
		return nil, err
	}
	log.Debug("Loading responder cert: ", responderFile)
	responderBytes, err := ioutil.ReadFile(responderFile)
	if err != nil {
		return nil, err
	}
	log.Debug("Loading responder key: ", keyFile)
	keyBytes, err := ioutil.ReadFile(keyFile)
	if err != nil {
		return nil, cferr.Wrap(cferr.CertificateError, cferr.ReadFailed, err)
	}

	issuerCert, err := helpers.ParseCertificatePEM(issuerBytes)
	if err != nil {
		return nil, err
	}

	responderCert, err := helpers.ParseCertificatePEM(responderBytes)
	if err != nil {
		return nil, err
	}

	key, err := helpers.ParsePrivateKeyPEM(keyBytes)
	if err != nil {
		log.Debug("Malformed private key %v", err)
		return nil, err
	}

	return NewSigner(issuerCert, responderCert, key, interval)
}
Example #2
0
func TestCAIssuing(t *testing.T) {
	var caCerts = []string{testCaFile, testECDSACaFile}
	var caKeys = []string{testCaKeyFile, testECDSACaKeyFile}
	var interCSRs = []string{ecdsaInterCSR, rsaInterCSR}
	var interKeys = []string{ecdsaInterKey, rsaInterKey}
	var CAPolicy = &config.Signing{
		Default: &config.SigningProfile{
			Usage:        []string{"cert sign", "crl sign"},
			ExpiryString: "1h",
			Expiry:       1 * time.Hour,
			CA:           true,
		},
	}
	var hostname = "cloudflare-inter.com"
	// Each RSA or ECDSA root CA issues two intermediate CAs (one ECDSA and one RSA).
	// For each intermediate CA, use it to issue additional RSA and ECDSA intermediate CSRs.
	for i, caFile := range caCerts {
		caKeyFile := caKeys[i]
		s := newCustomSigner(t, caFile, caKeyFile)
		s.policy = CAPolicy
		for j, csr := range interCSRs {
			csrBytes, _ := ioutil.ReadFile(csr)
			certBytes, err := s.Sign(signer.SignRequest{Hosts: signer.SplitHosts(hostname), Request: string(csrBytes)})
			if err != nil {
				t.Fatal(err)
			}
			interCert, err := helpers.ParseCertificatePEM(certBytes)
			if err != nil {
				t.Fatal(err)
			}
			keyBytes, _ := ioutil.ReadFile(interKeys[j])
			interKey, _ := helpers.ParsePrivateKeyPEM(keyBytes)
			interSigner := &Signer{interCert, interKey, CAPolicy, signer.DefaultSigAlgo(interKey)}
			for _, anotherCSR := range interCSRs {
				anotherCSRBytes, _ := ioutil.ReadFile(anotherCSR)
				bytes, err := interSigner.Sign(
					signer.SignRequest{
						Hosts:   signer.SplitHosts(hostname),
						Request: string(anotherCSRBytes),
					})
				if err != nil {
					t.Fatal(err)
				}
				cert, err := helpers.ParseCertificatePEM(bytes)
				if err != nil {
					t.Fatal(err)
				}
				if cert.SignatureAlgorithm != interSigner.SigAlgo() {
					t.Fatal("Cert Signature Algorithm does not match the issuer.")
				}
			}
		}
	}

}
Example #3
0
func TestECDSASigner(t *testing.T) {
	s := newCustomSigner(t, testECDSACaFile, testECDSACaKeyFile)
	hostname := "cloudflare.com"
	for _, test := range csrTests {
		csr, err := ioutil.ReadFile(test.file)
		if err != nil {
			t.Fatal("CSR loading error:", err)
		}
		// Try all ECDSA SignatureAlgorithm
		SigAlgos := []x509.SignatureAlgorithm{x509.ECDSAWithSHA1, x509.ECDSAWithSHA256, x509.ECDSAWithSHA384, x509.ECDSAWithSHA512}
		for _, sigAlgo := range SigAlgos {
			s.sigAlgo = sigAlgo
			certBytes, err := s.Sign(signer.SignRequest{Hosts: signer.SplitHosts(hostname), Request: string(csr)})
			if test.errorCallback != nil {
				test.errorCallback(t, err)
			} else {
				if err != nil {
					t.Fatalf("Expected no error. Got %s. Param %s %d", err.Error(), test.keyAlgo, test.keyLen)
				}
				cert, _ := helpers.ParseCertificatePEM(certBytes)
				if cert.SignatureAlgorithm != s.SigAlgo() {
					t.Fatal("Cert Signature Algorithm does not match the issuer.")
				}
			}
		}
	}
}
Example #4
0
func TestSignCSRs(t *testing.T) {
	s := newTestSigner(t)
	hostname := "cloudflare.com"
	for _, test := range csrTests {
		csr, err := ioutil.ReadFile(test.file)
		if err != nil {
			t.Fatal("CSR loading error:", err)
		}
		// It is possible to use different SHA2 algorithm with RSA CA key.
		rsaSigAlgos := []x509.SignatureAlgorithm{x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA}
		for _, sigAlgo := range rsaSigAlgos {
			s.sigAlgo = sigAlgo
			certBytes, err := s.Sign(signer.SignRequest{Hosts: signer.SplitHosts(hostname), Request: string(csr)})
			if test.errorCallback != nil {
				test.errorCallback(t, err)
			} else {
				if err != nil {
					t.Fatalf("Expected no error. Got %s. Param %s %d", err.Error(), test.keyAlgo, test.keyLen)
				}
				cert, _ := helpers.ParseCertificatePEM(certBytes)
				if cert.SignatureAlgorithm != s.SigAlgo() {
					t.Fatal("Cert Signature Algorithm does not match the issuer.")
				}
			}
		}
	}
}
Example #5
0
// fetchRemoteCertificate retrieves a single URL pointing to a certificate
// and attempts to first parse it as a DER-encoded certificate; if
// this fails, it attempts to decode it as a PEM-encoded certificate.
func fetchRemoteCertificate(certURL string) (fi *fetchedIntermediate, err error) {
	log.Debugf("fetching remote certificate: %s", certURL)
	var resp *http.Response
	resp, err = http.Get(certURL)
	if err != nil {
		log.Debugf("failed HTTP get: %v", err)
		return
	}

	defer resp.Body.Close()
	var certData []byte
	certData, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Debugf("failed to read response body: %v", err)
		return
	}

	log.Debugf("attempting to parse certificate as DER")
	crt, err := x509.ParseCertificate(certData)
	if err != nil {
		log.Debugf("attempting to parse certificate as PEM")
		crt, err = helpers.ParseCertificatePEM(certData)
		if err != nil {
			log.Debugf("failed to parse certificate: %v", err)
			return
		}
	}

	log.Debugf("certificate fetch succeeds")
	fi = &fetchedIntermediate{Cert: crt, Name: constructCertFileName(crt)}
	return
}
Example #6
0
func TestRemoteSignBadServerAndOverride(t *testing.T) {
	remoteServer := newTestSignServer(t)
	defer closeTestServer(t, remoteServer)

	// remoteConfig contains port 80 that no test server will listen on
	remoteConfig := newConfig(t, []byte(validMinimalRemoteConfig))
	s := newRemoteSigner(t, remoteConfig.Signing)

	hosts := []string{"cloudflare.com"}
	csr, err := ioutil.ReadFile("../local/testdata/rsa2048.csr")
	if err != nil {
		t.Fatal("CSR loading error:", err)
	}

	_, err = s.Sign(signer.SignRequest{Hosts: hosts, Request: string(csr)})
	if err == nil {
		t.Fatal("Should return error")
	}

	remoteConfig.Signing.OverrideRemotes(remoteServer.URL[7:])
	s.SetPolicy(remoteConfig.Signing)
	certBytes, err := s.Sign(signer.SignRequest{Hosts: hosts, Request: string(csr)})
	if err != nil {
		t.Fatalf("Expected no error. Got %s.", err.Error())
	}
	_, err = helpers.ParseCertificatePEM(certBytes)
	if err != nil {
		t.Fatal("Fail to parse returned certificate:", err)
	}

}
Example #7
0
// NewSignerFromFile generates a new local signer from a caFile
// and a caKey file, both PEM encoded.
func NewSignerFromFile(caFile, caKeyFile string, policy *config.Signing) (*Signer, error) {
	log.Debug("Loading CA: ", caFile)
	ca, err := ioutil.ReadFile(caFile)
	if err != nil {
		return nil, err
	}
	log.Debug("Loading CA key: ", caKeyFile)
	cakey, err := ioutil.ReadFile(caKeyFile)
	if err != nil {
		return nil, cferr.Wrap(cferr.CertificateError, cferr.ReadFailed, err)
	}

	parsedCa, err := helpers.ParseCertificatePEM(ca)
	if err != nil {
		return nil, err
	}

	priv, err := helpers.ParsePrivateKeyPEM(cakey)
	if err != nil {
		log.Debug("Malformed private key %v", err)
		return nil, err
	}

	return NewSigner(priv, parsedCa, signer.DefaultSigAlgo(priv), policy)
}
Example #8
0
func TestOverrideSubject(t *testing.T) {
	csrPEM, err := ioutil.ReadFile(fullSubjectCSR)
	if err != nil {
		t.Fatalf("%v", err)
	}

	req := &signer.Subject{
		Names: []csr.Name{
			{O: "example.net"},
		},
	}

	s := newCustomSigner(t, testECDSACaFile, testECDSACaKeyFile)

	request := signer.SignRequest{
		Hosts:   []string{"127.0.0.1", "localhost"},
		Request: string(csrPEM),
		Subject: req,
	}

	certPEM, err := s.Sign(request)

	if err != nil {
		t.Fatalf("%v", err)
	}

	cert, err := helpers.ParseCertificatePEM(certPEM)
	if err != nil {
		t.Fatalf("%v", err)
	}

	block, _ := pem.Decode(csrPEM)
	template, err := x509.ParseCertificateRequest(block.Bytes)
	if err != nil {
		t.Fatal(err.Error())
	}
	if cert.Subject.Organization[0] != "example.net" {
		t.Fatalf("Failed to override subject: want example.net but have %s", cert.Subject.Organization[0])
	}

	if cert.Subject.Country[0] != template.Subject.Country[0] {
		t.Fatal("Failed to override Country")
	}

	if cert.Subject.Locality[0] != template.Subject.Locality[0] {
		t.Fatal("Failed to override Locality")
	}

	if cert.Subject.Organization[0] == template.Subject.Organization[0] {
		t.Fatal("Shouldn't have overrode Organization")
	}

	if cert.Subject.OrganizationalUnit[0] != template.Subject.OrganizationalUnit[0] {
		t.Fatal("Failed to override OrganizationalUnit")
	}

	log.Info("Overrode subject info")
}
Example #9
0
func TestNoWhitelistSign(t *testing.T) {
	csrPEM, err := ioutil.ReadFile(fullSubjectCSR)
	if err != nil {
		t.Fatalf("%v", err)
	}

	req := &signer.Subject{
		Names: []csr.Name{
			{O: "sam certificate authority"},
		},
		CN: "localhost",
	}

	s := newCustomSigner(t, testECDSACaFile, testECDSACaKeyFile)
	// No policy CSR whitelist: the normal set of CSR fields get passed through to
	// certificate.
	s.policy = &config.Signing{
		Default: &config.SigningProfile{
			Usage:        []string{"cert sign", "crl sign"},
			ExpiryString: "1h",
			Expiry:       1 * time.Hour,
			CA:           true,
		},
	}

	request := signer.SignRequest{
		Hosts:   []string{"127.0.0.1", "localhost"},
		Request: string(csrPEM),
		Subject: req,
	}

	certPEM, err := s.Sign(request)
	if err != nil {
		t.Fatalf("%v", err)
	}

	cert, err := helpers.ParseCertificatePEM(certPEM)
	if err != nil {
		t.Fatalf("%v", err)
	}

	name := cert.Subject
	if name.CommonName != "localhost" {
		t.Fatalf("Expected certificate common name to be 'localhost' but have '%v'", name.CommonName)
	}

	// CSR has: Subject: C=US, O=CloudFlare, OU=WWW, L=Ithaca, ST=New York
	// Expect all to be passed through.
	expectOneValueOf(t, name.Organization, "sam certificate authority", "O")
	expectOneValueOf(t, name.OrganizationalUnit, "WWW", "OU")
	expectOneValueOf(t, name.Province, "New York", "ST")
	expectOneValueOf(t, name.Locality, "Ithaca", "L")
	expectOneValueOf(t, name.Country, "US", "C")
}
Example #10
0
// Certificate returns the signer's certificate.
func (s *Signer) Certificate(label, profile string) (*x509.Certificate, error) {
	certStr, err := s.Info(client.InfoReq{Label: label, Profile: profile})
	if err != nil {
		return nil, err
	}
	cert, err := helpers.ParseCertificatePEM(certStr)
	if err != nil {
		return nil, err
	}
	return cert, nil
}
Example #11
0
func TestSign(t *testing.T) {
	dur, _ := time.ParseDuration("1ms")
	// expected case
	s, err := NewSignerFromFile(serverCertFile, otherCertFile, serverKeyFile, dur)
	if err != nil {
		t.Fatalf("Signer creation failed: %v", err)
	}

	_, err = s.Sign(SignRequest{})
	if err == nil {
		t.Fatal("Signed request with nil certificate")
	}

	certPEM, err := ioutil.ReadFile(otherCertFile)
	if err != nil {
		t.Fatal(err)
	}

	cert, err := helpers.ParseCertificatePEM(certPEM)
	if err != nil {
		t.Fatal(err)
	}

	req := SignRequest{
		Certificate: cert,
		Status:      "good",
	}

	_, err = s.Sign(req)
	if err != nil {
		t.Fatal("Sign failed")
	}

	sMismatch, err := NewSignerFromFile(wrongServerCertFile, otherCertFile, wrongServerKeyFile, dur)
	_, err = sMismatch.Sign(req)
	if err == nil {
		t.Fatal("Signed a certificate from the wrong issuer")
	}

	// incorrect status code
	req.Status = "aalkjsfdlkafdslkjahds"
	_, err = s.Sign(req)
	if err == nil {
		t.Fatal("Failed to fail on improper status code")
	}

	// revoked
	req.Status = "revoked"
	_, err = s.Sign(req)
	if err != nil {
		t.Fatal("Error on revoked certificate")
	}
}
Example #12
0
func loadIssuer(filename string) (issuerCert *x509.Certificate, err error) {
	if filename == "" {
		err = errors.New("Issuer certificate was not provided in config.")
		return
	}
	issuerCertPEM, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}
	issuerCert, err = helpers.ParseCertificatePEM(issuerCertPEM)
	return
}
Example #13
0
// ocspSignerMain is the main CLI of OCSP signer functionality.
func ocspSignerMain(args []string, c cli.Config) (err error) {
	// Read the cert to be revoked from file
	certBytes, err := ioutil.ReadFile(c.CertFile)
	if err != nil {
		log.Critical("Unable to read certificate: ", err)
		return
	}
	cert, err := helpers.ParseCertificatePEM(certBytes)
	if err != nil {
		log.Critical("Unable to parse certificate: ", err)
		return
	}

	req := ocsp.SignRequest{
		Certificate: cert,
		Status:      c.Status,
	}

	if c.Status == "revoked" {
		req.Reason = c.Reason

		req.RevokedAt = time.Now()
		if c.RevokedAt != "now" {
			req.RevokedAt, err = time.Parse("2006-01-02", c.RevokedAt)
			if err != nil {
				log.Critical("Malformed revocation time: ", c.RevokedAt)
				return
			}
		}
	}

	s, err := ocsp.NewSignerFromFile(c.CAFile, c.ResponderFile, c.KeyFile, time.Duration(c.Interval))
	if err != nil {
		log.Critical("Unable to create OCSP signer: ", err)
		return
	}

	resp, err := s.Sign(req)
	if err != nil {
		log.Critical("Unable to sign OCSP response: ", err)
		return
	}

	cli.PrintOCSPResponse(resp)
	return
}
func TestMain(m *testing.M) {
	caKeyPEM, _ := ioutil.ReadFile(caKeyFile)
	caKey, _ := helpers.ParsePrivateKeyPEM(caKeyPEM)

	caCertPEM, _ := ioutil.ReadFile(caCertFile)
	caCert, _ := helpers.ParseCertificatePEM(caCertPEM)

	// Create an online CFSSL instance
	// This is designed to mimic what LE plans to do
	authHandler, _ := auth.New(authKey, nil)
	policy := &cfsslConfig.Signing{
		Profiles: map[string]*cfsslConfig.SigningProfile{
			profileName: &cfsslConfig.SigningProfile{
				Usage:     []string{"server auth"},
				CA:        false,
				IssuerURL: []string{"http://not-example.com/issuer-url"},
				OCSP:      "http://not-example.com/ocsp",
				CRL:       "http://not-example.com/crl",

				Policies: []asn1.ObjectIdentifier{
					asn1.ObjectIdentifier{2, 23, 140, 1, 2, 1},
				},
				Expiry:   8760 * time.Hour,
				Backdate: time.Hour,
				Provider: authHandler,
				CSRWhitelist: &cfsslConfig.CSRWhitelist{
					PublicKeyAlgorithm: true,
					PublicKey:          true,
					SignatureAlgorithm: true,
				},
			},
		},
		Default: &cfsslConfig.SigningProfile{
			Expiry: time.Hour,
		},
	}
	cfsslSigner, _ = local.NewSigner(caKey, caCert, x509.SHA256WithRSA, policy)
	signHandler, _ := apisign.NewAuthHandlerFromSigner(cfsslSigner)
	http.Handle("/api/v1/cfssl/authsign", signHandler)
	// This goroutine should get killed when main() return
	go (func() { http.ListenAndServe(hostPort, nil) })()

	os.Exit(m.Run())
}
Example #15
0
// New returns a new PKCS #11 signer.
func NewPKCS11Signer(cfg ocspConfig.Config) (ocsp.Signer, error) {
	log.Debugf("Loading PKCS #11 module %s", cfg.PKCS11.Module)
	certData, err := ioutil.ReadFile(cfg.CACertFile)
	if err != nil {
		return nil, errors.New(errors.CertificateError, errors.ReadFailed)
	}

	cert, err := helpers.ParseCertificatePEM(certData)
	if err != nil {
		return nil, err
	}

	PKCS11 := cfg.PKCS11
	priv, err := pkcs11key.New(PKCS11.Module, PKCS11.Token, PKCS11.PIN,
		PKCS11.Label)
	if err != nil {
		return nil, errors.New(errors.PrivateKeyError, errors.ReadFailed)
	}

	return ocsp.NewSigner(cert, cert, priv, cfg.Interval)
}
Example #16
0
func TestRemoteSign(t *testing.T) {
	remoteServer := newTestSignServer(t)
	defer closeTestServer(t, remoteServer)

	remoteConfig := newConfig(t, []byte(validMinimalRemoteConfig))
	// override with test server address, ignore url prefix "http://"
	remoteConfig.Signing.OverrideRemotes(remoteServer.URL[7:])
	s := newRemoteSigner(t, remoteConfig.Signing)

	hosts := []string{"cloudflare.com"}
	for _, test := range csrTests {
		csr, err := ioutil.ReadFile(test.file)
		if err != nil {
			t.Fatal("CSR loading error:", err)
		}
		testSeq := "7007F"
		certBytes, err := s.Sign(signer.SignRequest{Hosts: hosts, Request: string(csr), SerialSeq: testSeq})
		if test.errorCallback != nil {
			test.errorCallback(t, err)
		} else {
			if err != nil {
				t.Fatalf("Expected no error. Got %s. Param %s %d", err.Error(), test.keyAlgo, test.keyLen)
			}
			cert, err := helpers.ParseCertificatePEM(certBytes)
			if err != nil {
				t.Fatal("Fail to parse returned certificate:", err)
			}
			sn := fmt.Sprintf("%X", cert.SerialNumber)
			if sn[0:len(testSeq)] != testSeq {
				t.Fatal("Serial Number did not begin with seq:", sn)
			}
			if len(sn) != len(testSeq)+16 {
				t.Fatal("Serial Number unexpected length:", sn)
			}
		}
	}
}
Example #17
0
// New returns a new PKCS #11 signer.
func New(caCertFile string, policy *config.Signing, cfg *pkcs11key.Config) (signer.Signer, error) {
	if cfg == nil {
		return nil, errors.New(errors.PrivateKeyError, errors.ReadFailed)
	}

	log.Debugf("Loading PKCS #11 module %s", cfg.Module)
	certData, err := ioutil.ReadFile(caCertFile)
	if err != nil {
		return nil, errors.New(errors.PrivateKeyError, errors.ReadFailed)
	}

	cert, err := helpers.ParseCertificatePEM(certData)
	if err != nil {
		return nil, err
	}

	priv, err := pkcs11key.New(cfg.Module, cfg.TokenLabel, cfg.PIN, cfg.PrivateKeyLabel)
	if err != nil {
		return nil, errors.New(errors.PrivateKeyError, errors.ReadFailed)
	}
	sigAlgo := signer.DefaultSigAlgo(priv)

	return local.NewSigner(priv, cert, sigAlgo, policy)
}
Example #18
0
// test the private method
func testSign(t *testing.T) {
	signer, err := NewSignerFromFile("testdata/ca.pem", "testdata/ca_key.pem", nil)
	if signer == nil || err != nil {
		t.Fatal("Failed to produce signer")
	}

	pem, _ := ioutil.ReadFile("../../helpers/testdata/cert.pem")
	cert, _ := helpers.ParseCertificatePEM(pem)

	badcert := *cert
	badcert.PublicKey = nil
	profl := config.SigningProfile{Usage: []string{"Certificates", "Rule"}}
	_, err = signer.sign(&badcert, &profl, "")

	if err == nil {
		t.Fatal("Improper input failed to raise an error")
	}

	// nil profile
	_, err = signer.sign(cert, &profl, "")
	if err == nil {
		t.Fatal("Nil profile failed to raise an error")
	}

	// empty profile
	_, err = signer.sign(cert, &config.SigningProfile{}, "")
	if err == nil {
		t.Fatal("Empty profile failed to raise an error")
	}

	// empty expiry
	prof := signer.policy.Default
	prof.Expiry = 0
	_, err = signer.sign(cert, prof, "")
	if err != nil {
		t.Fatal("nil expiry raised an error")
	}

	// non empty urls
	prof = signer.policy.Default
	prof.CRL = "stuff"
	prof.OCSP = "stuff"
	prof.IssuerURL = []string{"stuff"}
	_, err = signer.sign(cert, prof, "")
	if err != nil {
		t.Fatal("non nil urls raised an error")
	}

	// nil ca
	nilca := *signer
	prof = signer.policy.Default
	prof.CA = false
	nilca.ca = nil
	_, err = nilca.sign(cert, prof, "")
	if err == nil {
		t.Fatal("nil ca with isca false raised an error")
	}
	prof.CA = true
	_, err = nilca.sign(cert, prof, "")
	if err != nil {
		t.Fatal("nil ca with CA true raised an error")
	}
}
Example #19
0
func TestOverwriteHosts(t *testing.T) {
	for _, csrFile := range []string{testCSR, testSANCSR} {
		csrPEM, err := ioutil.ReadFile(csrFile)
		if err != nil {
			t.Fatal(err)
		}

		csrDER, _ := pem.Decode([]byte(csrPEM))
		if err != nil {
			t.Fatal(err)
		}

		csr, err := x509.ParseCertificateRequest(csrDER.Bytes)
		if err != nil {
			t.Fatal(err)
		}

		csrHosts := csr.DNSNames
		for _, ip := range csr.IPAddresses {
			csrHosts = append(csrHosts, ip.String())
		}
		sort.Strings(csrHosts)

		s := newCustomSigner(t, testECDSACaFile, testECDSACaKeyFile)

		for _, hosts := range [][]string{
			nil,
			[]string{},
			[]string{"127.0.0.1", "localhost"},
		} {
			request := signer.SignRequest{
				Hosts:   hosts,
				Request: string(csrPEM),
				Subject: nil,
			}
			certPEM, err := s.Sign(request)

			if err != nil {
				t.Fatalf("%v", err)
			}

			cert, err := helpers.ParseCertificatePEM(certPEM)
			if err != nil {
				t.Fatalf("%v", err)
			}

			// get the hosts, and add the ips
			certHosts := cert.DNSNames
			for _, ip := range cert.IPAddresses {
				certHosts = append(certHosts, ip.String())
			}

			// compare the sorted host lists
			sort.Strings(certHosts)
			sort.Strings(request.Hosts)
			if len(request.Hosts) > 0 && !reflect.DeepEqual(certHosts, request.Hosts) {
				t.Fatalf("Hosts not the same. cert hosts: %v, expected: %v", certHosts, request.Hosts)
			}

			if request.Hosts == nil && !reflect.DeepEqual(certHosts, csrHosts) {
				t.Fatalf("Hosts not the same. cert hosts: %v, expected csr hosts: %v", certHosts, csrHosts)
			}

			if request.Hosts != nil && len(request.Hosts) == 0 && len(certHosts) != 0 {
				t.Fatalf("Hosts not the same. cert hosts: %v, expected: %v", certHosts, request.Hosts)
			}
		}
	}

}
Example #20
0
func TestWhitelistSign(t *testing.T) {
	csrPEM, err := ioutil.ReadFile(fullSubjectCSR)
	if err != nil {
		t.Fatalf("%v", err)
	}

	req := &signer.Subject{
		Names: []csr.Name{
			{O: "sam certificate authority"},
		},
	}

	s := newCustomSigner(t, testECDSACaFile, testECDSACaKeyFile)
	// Whitelist only key-related fields. Subject, DNSNames, etc shouldn't get
	// passed through from CSR.
	s.policy = &config.Signing{
		Default: &config.SigningProfile{
			Usage:        []string{"cert sign", "crl sign"},
			ExpiryString: "1h",
			Expiry:       1 * time.Hour,
			CA:           true,
			CSRWhitelist: &config.CSRWhitelist{
				PublicKey:          true,
				PublicKeyAlgorithm: true,
				SignatureAlgorithm: true,
			},
		},
	}

	request := signer.SignRequest{
		Hosts:   []string{"127.0.0.1", "localhost"},
		Request: string(csrPEM),
		Subject: req,
	}

	certPEM, err := s.Sign(request)
	if err != nil {
		t.Fatalf("%v", err)
	}

	cert, err := helpers.ParseCertificatePEM(certPEM)
	if err != nil {
		t.Fatalf("%v", err)
	}

	name := cert.Subject
	if name.CommonName != "" {
		t.Fatalf("Expected empty certificate common name under policy without "+
			"Subject whitelist, got %v", name.CommonName)
	}
	// O is provided by the signing API request, not the CSR, so it's allowed to
	// be copied into the certificate.
	expectOneValueOf(t, name.Organization, "sam certificate authority", "O")
	expectEmpty(t, name.OrganizationalUnit, "OU")
	expectEmpty(t, name.Province, "ST")
	expectEmpty(t, name.Locality, "L")
	expectEmpty(t, name.Country, "C")
	if cert.PublicKeyAlgorithm != x509.RSA {
		t.Fatalf("Expected public key algorithm to be RSA")
	}

	// Signature algorithm is allowed to be copied from CSR, but is overridden by
	// DefaultSigAlgo.
	if cert.SignatureAlgorithm != x509.ECDSAWithSHA256 {
		t.Fatalf("Expected public key algorithm to be ECDSAWithSHA256, got %v",
			cert.SignatureAlgorithm)
	}
}
Example #21
0
// readCert read a PEM file and returns a cert.
func readCert(filename string) *x509.Certificate {
	bytes, _ := ioutil.ReadFile(filename)
	cert, _ := helpers.ParseCertificatePEM(bytes)
	return cert
}
Example #22
0
func TestInitCA(t *testing.T) {
	var req *csr.CertificateRequest
	hostname := "cloudflare.com"
	for _, param := range validKeyParams {
		req = &csr.CertificateRequest{
			Names: []csr.Name{
				{
					C:  "US",
					ST: "California",
					L:  "San Francisco",
					O:  "CloudFlare",
					OU: "Systems Engineering",
				},
			},
			CN:    hostname,
			Hosts: []string{hostname, "www." + hostname},
			KeyRequest: &csr.KeyRequest{
				Algo: param.keyAlgo,
				Size: param.keyLen,
			},
		}
		certBytes, keyBytes, err := New(req)
		if err != nil {
			t.Fatal("InitCA failed:", err)
		}
		key, err := helpers.ParsePrivateKeyPEM(keyBytes)
		if err != nil {
			t.Fatal("InitCA private key parsing failed:", err)
		}
		cert, err := helpers.ParseCertificatePEM(certBytes)
		if err != nil {
			t.Fatal("InitCA cert parsing failed:", err)
		}

		// Verify key parameters.
		switch req.KeyRequest.Algo {
		case "rsa":
			if cert.PublicKey.(*rsa.PublicKey).N.BitLen() != param.keyLen {
				t.Fatal("Cert key length mismatch.")
			}
			if key.(*rsa.PrivateKey).N.BitLen() != param.keyLen {
				t.Fatal("Private key length mismatch.")
			}
		case "ecdsa":
			if cert.PublicKey.(*ecdsa.PublicKey).Curve.Params().BitSize != param.keyLen {
				t.Fatal("Cert key length mismatch.")
			}
			if key.(*ecdsa.PrivateKey).Curve.Params().BitSize != param.keyLen {
				t.Fatal("Private key length mismatch.")
			}
		}

		// Start a signer
		var CAPolicy = &config.Signing{
			Default: &config.SigningProfile{
				Usage:        []string{"cert sign", "crl sign"},
				ExpiryString: "300s",
				Expiry:       300 * time.Second,
				CA:           true,
			},
		}
		s, err := local.NewSigner(key, cert, signer.DefaultSigAlgo(key), nil)
		if err != nil {
			t.Fatal("Signer Creation error:", err)
		}
		s.SetPolicy(CAPolicy)

		// Sign RSA and ECDSA customer CSRs.
		for _, csrFile := range csrFiles {
			csrBytes, err := ioutil.ReadFile(csrFile)
			if err != nil {
				t.Fatal("CSR loading error:", err)
			}
			req := signer.SignRequest{
				Request: string(csrBytes),
				Hosts:   signer.SplitHosts(hostname),
				Profile: "",
				Label:   "",
			}

			bytes, err := s.Sign(req)
			if err != nil {
				t.Fatal(err)
			}
			customerCert, _ := helpers.ParseCertificatePEM(bytes)
			if customerCert.SignatureAlgorithm != s.SigAlgo() {
				t.Fatal("Signature Algorithm mismatch")
			}
			err = customerCert.CheckSignatureFrom(cert)
			if err != nil {
				t.Fatal("Signing CSR failed.", err)
			}
		}

	}
}