Beispiel #1
0
func (certSuite) TestVerify(c *gc.C) {
	now := time.Now()
	caCert, caKey, err := cert.NewCA("foo", now.Add(1*time.Minute))
	c.Assert(err, jc.ErrorIsNil)

	var noHostnames []string
	srvCert, _, err := cert.NewServer(caCert, caKey, now.Add(3*time.Minute), noHostnames)
	c.Assert(err, jc.ErrorIsNil)

	err = cert.Verify(srvCert, caCert, now)
	c.Assert(err, jc.ErrorIsNil)

	err = cert.Verify(srvCert, caCert, now.Add(55*time.Second))
	c.Assert(err, jc.ErrorIsNil)

	err = cert.Verify(srvCert, caCert, now.AddDate(0, 0, -8))
	c.Check(err, gc.ErrorMatches, "x509: certificate has expired or is not yet valid")

	err = cert.Verify(srvCert, caCert, now.Add(2*time.Minute))
	c.Check(err, gc.ErrorMatches, "x509: certificate has expired or is not yet valid")

	caCert2, caKey2, err := cert.NewCA("bar", now.Add(1*time.Minute))
	c.Assert(err, jc.ErrorIsNil)

	// Check original server certificate against wrong CA.
	err = cert.Verify(srvCert, caCert2, now)
	c.Check(err, gc.ErrorMatches, "x509: certificate signed by unknown authority")

	srvCert2, _, err := cert.NewServer(caCert2, caKey2, now.Add(1*time.Minute), noHostnames)
	c.Assert(err, jc.ErrorIsNil)

	// Check new server certificate against original CA.
	err = cert.Verify(srvCert2, caCert, now)
	c.Check(err, gc.ErrorMatches, "x509: certificate signed by unknown authority")
}
Beispiel #2
0
func (certSuite) TestNewServerWithInvalidCert(c *gc.C) {
	var noHostnames []string
	srvCert, srvKey, err := cert.NewServer(nonCACert, nonCAKey, time.Now(), noHostnames)
	c.Check(srvCert, gc.Equals, "")
	c.Check(srvKey, gc.Equals, "")
	c.Assert(err, gc.ErrorMatches, "CA certificate is not a valid CA")
}
Beispiel #3
0
func (certSuite) TestNewServerHostnames(c *gc.C) {
	type test struct {
		hostnames           []string
		expectedDNSNames    []string
		expectedIPAddresses []net.IP
	}
	tests := []test{{
		[]string{},
		nil,
		nil,
	}, {
		[]string{"example.com"},
		[]string{"example.com"},
		nil,
	}, {
		[]string{"example.com", "127.0.0.1"},
		[]string{"example.com"},
		[]net.IP{net.IPv4(127, 0, 0, 1).To4()},
	}, {
		[]string{"::1"},
		nil,
		[]net.IP{net.IPv6loopback},
	}}
	for i, t := range tests {
		c.Logf("test %d: %v", i, t.hostnames)
		expiry := roundTime(time.Now().AddDate(1, 0, 0))
		srvCertPEM, srvKeyPEM, err := cert.NewServer(caCertPEM, caKeyPEM, expiry, t.hostnames)
		c.Assert(err, jc.ErrorIsNil)
		srvCert, _, err := cert.ParseCertAndKey(srvCertPEM, srvKeyPEM)
		c.Assert(err, jc.ErrorIsNil)
		c.Assert(srvCert.DNSNames, gc.DeepEquals, t.expectedDNSNames)
		c.Assert(srvCert.IPAddresses, gc.DeepEquals, t.expectedIPAddresses)
	}
}
Beispiel #4
0
func (certSuite) TestNewServer(c *gc.C) {
	now := time.Now()
	expiry := roundTime(now.AddDate(1, 0, 0))
	caCertPEM, caKeyPEM, err := cert.NewCA("foo", expiry)
	c.Assert(err, gc.IsNil)

	caCert, _, err := cert.ParseCertAndKey(caCertPEM, caKeyPEM)
	c.Assert(err, gc.IsNil)

	var noHostnames []string
	srvCertPEM, srvKeyPEM, err := cert.NewServer(caCertPEM, caKeyPEM, expiry, noHostnames)
	c.Assert(err, gc.IsNil)

	srvCert, srvKey, err := cert.ParseCertAndKey(srvCertPEM, srvKeyPEM)
	c.Assert(err, gc.IsNil)
	c.Assert(srvCert.Subject.CommonName, gc.Equals, "*")
	// Check that the certificate is valid from one week before today.
	c.Check(srvCert.NotBefore.Before(now), jc.IsTrue)
	c.Check(srvCert.NotBefore.Before(now.AddDate(0, 0, -6)), jc.IsTrue)
	c.Check(srvCert.NotBefore.After(now.AddDate(0, 0, -8)), jc.IsTrue)
	c.Assert(srvCert.NotAfter.Equal(expiry), gc.Equals, true)
	c.Assert(srvCert.BasicConstraintsValid, gc.Equals, false)
	c.Assert(srvCert.IsCA, gc.Equals, false)
	c.Assert(srvCert.ExtKeyUsage, gc.DeepEquals, []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth})

	checkTLSConnection(c, caCert, srvCert, srvKey)
}
Beispiel #5
0
// rsyslogServerCerts generates new certificates for RsyslogConfigHandler
// using the provider caCert and caKey. This is used during the setup of the
// rsyslog worker as well as when handling any changes to the rsyslog configuration,
// usually adding and removing of state machines through ensure-availability.
func (h *RsyslogConfigHandler) rsyslogServerCerts(caCert, caKey string) (string, string, error) {
	if caCert == "" {
		return "", "", errors.New("CACert is not set")
	}
	if caKey == "" {
		return "", "", errors.New("CAKey is not set")
	}

	expiry := time.Now().UTC().AddDate(10, 0, 0)
	// Add rsyslog servers in the subjectAltName so we can
	// successfully validate when connectiong via SSL
	hosts, err := h.rsyslogHosts()
	if err != nil {
		return "", "", err
	}
	// Add local IPs to SAN. When connecting via IP address,
	// the client will validate the server against any IP in
	// the subjectAltName. We add all local ips to make sure
	// this does not cause an error
	ips, err := localIPS()
	if err != nil {
		return "", "", err
	}
	hosts = append(hosts, ips...)
	return cert.NewServer(caCert, caKey, expiry, hosts)
}
Beispiel #6
0
func mustNewServer() (string, string) {
	cert.KeyBits = 512
	var hostnames []string
	srvCert, srvKey, err := cert.NewServer(CACert, CAKey, time.Now().AddDate(10, 0, 0), hostnames)
	if err != nil {
		panic(err)
	}
	return string(srvCert), string(srvKey)
}
Beispiel #7
0
func createCerts(c *gc.C, serverName string) (*x509.CertPool, tls.Certificate) {
	certCaPem, keyCaPem, err := cert.NewCA("sender-test", "1", time.Now().Add(time.Minute))
	c.Assert(err, jc.ErrorIsNil)
	certPem, keyPem, err := cert.NewServer(certCaPem, keyCaPem, time.Now().Add(time.Minute), []string{serverName})
	c.Assert(err, jc.ErrorIsNil)
	cert, err := tls.X509KeyPair([]byte(certPem), []byte(keyPem))
	c.Assert(err, jc.ErrorIsNil)
	certPool := x509.NewCertPool()
	certPool.AppendCertsFromPEM([]byte(certCaPem))
	return certPool, cert
}
Beispiel #8
0
// GenerateStateServerCertAndKey makes sure that the config has a CACert and
// CAPrivateKey, generates and retruns new certificate and key.
func (cfg *Config) GenerateStateServerCertAndKey() (string, string, error) {
	caCert, hasCACert := cfg.CACert()
	if !hasCACert {
		return "", "", fmt.Errorf("environment configuration has no ca-cert")
	}
	caKey, hasCAKey := cfg.CAPrivateKey()
	if !hasCAKey {
		return "", "", fmt.Errorf("environment configuration has no ca-private-key")
	}
	var noHostnames []string
	return cert.NewServer(caCert, caKey, time.Now().UTC().AddDate(10, 0, 0), noHostnames)
}
Beispiel #9
0
func (certSuite) TestNewServer(c *gc.C) {
	now := time.Now()
	expiry := roundTime(now.AddDate(1, 0, 0))
	caCertPEM, caKeyPEM, err := cert.NewCA("foo", expiry)
	c.Assert(err, jc.ErrorIsNil)

	caCert, _, err := cert.ParseCertAndKey(caCertPEM, caKeyPEM)
	c.Assert(err, jc.ErrorIsNil)

	srvCertPEM, srvKeyPEM, err := cert.NewServer(caCertPEM, caKeyPEM, expiry, nil)
	c.Assert(err, jc.ErrorIsNil)
	checkCertificate(c, caCert, srvCertPEM, srvKeyPEM, now, expiry)
}
Beispiel #10
0
func (certSuite) TestWithNonUTCExpiry(c *gc.C) {
	expiry, err := time.Parse("2006-01-02 15:04:05.999999999 -0700 MST", "2012-11-28 15:53:57 +0100 CET")
	c.Assert(err, jc.ErrorIsNil)
	certPEM, keyPEM, err := cert.NewCA("foo", expiry)
	xcert, err := cert.ParseCert(certPEM)
	c.Assert(err, jc.ErrorIsNil)
	checkNotAfter(c, xcert, expiry)

	var noHostnames []string
	certPEM, _, err = cert.NewServer(certPEM, keyPEM, expiry, noHostnames)
	xcert, err = cert.ParseCert(certPEM)
	c.Assert(err, jc.ErrorIsNil)
	checkNotAfter(c, xcert, expiry)
}
Beispiel #11
0
// ensureCertificates ensures that a CA certificate,
// server certificate, and private key exist in the log
// directory, and writes them if not. The CA certificate
// is entered into the environment configuration to be
// picked up by other agents.
func (h *RsyslogConfigHandler) ensureCertificates() error {
	// We write ca-cert.pem last, after propagating into state.
	// If it's there, then there's nothing to do. Otherwise,
	// start over.
	caCertPEM := h.syslogConfig.CACertPath()
	if _, err := os.Stat(caCertPEM); err == nil {
		return nil
	}

	// Files must be chowned to syslog:adm.
	syslogUid, syslogGid, err := lookupUser("syslog")
	if err != nil {
		return err
	}

	// Generate a new CA and server cert/key pairs.
	// The CA key will be discarded after the server
	// cert has been generated.
	expiry := time.Now().UTC().AddDate(10, 0, 0)
	caCertPEM, caKeyPEM, err := cert.NewCA("rsyslog", expiry)
	if err != nil {
		return err
	}
	rsyslogCertPEM, rsyslogKeyPEM, err := cert.NewServer(caCertPEM, caKeyPEM, expiry, nil)
	if err != nil {
		return err
	}

	// Update the environment config with the CA cert,
	// so clients can configure rsyslog.
	if err := h.st.SetRsyslogCert(caCertPEM); err != nil {
		return err
	}

	// Write the certificates and key. The CA certificate must be written last for idempotency.
	for _, pair := range []struct {
		path string
		data string
	}{
		{h.syslogConfig.ServerCertPath(), rsyslogCertPEM},
		{h.syslogConfig.ServerKeyPath(), rsyslogKeyPEM},
		{h.syslogConfig.CACertPath(), caCertPEM},
	} {
		if err := writeFileAtomic(pair.path, []byte(pair.data), 0600, syslogUid, syslogGid); err != nil {
			return err
		}
	}
	return nil
}
Beispiel #12
0
func (s *certSuite) TestUpdateCert(c *gc.C) {
	config := s.sampleConfig(c)
	certChanged := make(chan params.StateServingInfo)
	config.CertChanged = certChanged

	srv := s.newServer(c, config)

	// Sanity check that the server works initially.
	conn := s.OpenAPIAsAdmin(c, srv)
	c.Assert(pingConn(conn), jc.ErrorIsNil)

	// Create a new certificate that's a year out of date, so we can
	// tell that the server is using it because the connection
	// will fail.
	srvCert, srvKey, err := cert.NewServer(coretesting.CACert, coretesting.CAKey, time.Now().AddDate(-1, 0, 0), nil)
	c.Assert(err, jc.ErrorIsNil)
	info := params.StateServingInfo{
		Cert:       string(srvCert),
		PrivateKey: string(srvKey),
		// No other fields are used by the cert listener.
	}
	certChanged <- info
	// Send the same info again so that we are sure that
	// the previously received information was acted upon
	// (an alternative would be to sleep for a while, but this
	// approach is quicker and more certain).
	certChanged <- info

	// Check that we can't connect to the server because of the bad certificate.
	apiInfo := s.APIInfo(srv)
	apiInfo.Tag = s.Owner
	apiInfo.Password = ownerPassword
	_, err = api.Open(apiInfo, api.DialOpts{})
	c.Assert(err, gc.ErrorMatches, `unable to connect to API: .*: certificate has expired or is not yet valid`)

	// Now change it back and check that we can connect again.
	info = params.StateServingInfo{
		Cert:       coretesting.ServerCert,
		PrivateKey: coretesting.ServerKey,
		// No other fields are used by the cert listener.
	}
	certChanged <- info
	certChanged <- info

	conn = s.OpenAPIAsAdmin(c, srv)
	c.Assert(pingConn(conn), jc.ErrorIsNil)
}
Beispiel #13
0
// ServeTLS runs a storage server on the given network address, relaying
// requests to the given storage implementation. The server runs a TLS
// listener, and verifies client certificates (if given) against the
// specified CA certificate. A client certificate is only required for
// PUT and DELETE methods.
//
// This method returns the network listener, which can then be attached
// to with ClientTLS.
func ServeTLS(addr string, stor storage.Storage, caCertPEM, caKeyPEM string, hostnames []string, authkey string) (net.Listener, error) {
	expiry := time.Now().UTC().AddDate(10, 0, 0)
	certPEM, keyPEM, err := cert.NewServer(caCertPEM, caKeyPEM, expiry, hostnames)
	if err != nil {
		return nil, err
	}
	serverCert, err := tls.X509KeyPair([]byte(certPEM), []byte(keyPEM))
	if err != nil {
		return nil, err
	}
	caCerts := x509.NewCertPool()
	if !caCerts.AppendCertsFromPEM([]byte(caCertPEM)) {
		return nil, errors.New("error adding CA certificate to pool")
	}
	config := &tls.Config{
		NextProtos:   []string{"http/1.1"},
		Certificates: []tls.Certificate{serverCert},
		ClientAuth:   tls.VerifyClientCertIfGiven,
		ClientCAs:    caCerts,
	}
	return serve(addr, stor, config, authkey)
}
Beispiel #14
0
func (certSuite) TestNewServer(c *gc.C) {
	expiry := roundTime(time.Now().AddDate(1, 0, 0))
	caCertPEM, caKeyPEM, err := cert.NewCA("foo", expiry)
	c.Assert(err, gc.IsNil)

	caCert, _, err := cert.ParseCertAndKey(caCertPEM, caKeyPEM)
	c.Assert(err, gc.IsNil)

	var noHostnames []string
	srvCertPEM, srvKeyPEM, err := cert.NewServer(caCertPEM, caKeyPEM, expiry, noHostnames)
	c.Assert(err, gc.IsNil)

	srvCert, srvKey, err := cert.ParseCertAndKey(srvCertPEM, srvKeyPEM)
	c.Assert(err, gc.IsNil)
	c.Assert(srvCert.Subject.CommonName, gc.Equals, "*")
	c.Assert(srvCert.NotAfter.Equal(expiry), gc.Equals, true)
	c.Assert(srvCert.BasicConstraintsValid, gc.Equals, false)
	c.Assert(srvCert.IsCA, gc.Equals, false)
	c.Assert(srvCert.ExtKeyUsage, gc.DeepEquals, []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth})

	checkTLSConnection(c, caCert, srvCert, srvKey)
}
Beispiel #15
0
// ensureCertificates ensures that a CA certificate,
// server certificate, and private key exist in the log
// directory, and writes them if not. The CA certificate
// is entered into the environment configuration to be
// picked up by other agents.
func (h *RsyslogConfigHandler) ensureCertificates() error {
	// We write ca-cert.pem last, after propagating into state.
	// If it's there, then there's nothing to do. Otherwise,
	// start over.
	caCertPEM := h.syslogConfig.CACertPath()
	if _, err := os.Stat(caCertPEM); err == nil {
		return nil
	}

	// Files must be chowned to syslog:adm.
	syslogUid, syslogGid, err := lookupUser("syslog")
	if err != nil {
		return err
	}

	// Generate a new CA and server cert/key pairs.
	// The CA key will be discarded after the server
	// cert has been generated.
	expiry := time.Now().UTC().AddDate(10, 0, 0)
	caCertPEM, caKeyPEM, err := cert.NewCA("rsyslog", expiry)
	if err != nil {
		return err
	}

	// Add rsyslog servers in the subjectAltName so we can
	// successfully validate when connectiong via SSL
	hosts, err := h.rsyslogHosts()
	if err != nil {
		return err
	}
	// Add local IPs to SAN. When connecting via IP address,
	// the client will validate the server against any IP in
	// the subjectAltName. We add all local ips to make sure
	// this does not cause an error
	ips, err := localIPS()
	if err != nil {
		return err
	}
	hosts = append(hosts, ips...)
	rsyslogCertPEM, rsyslogKeyPEM, err := cert.NewServer(caCertPEM, caKeyPEM, expiry, hosts)
	if err != nil {
		return err
	}

	// Update the environment config with the CA cert,
	// so clients can configure rsyslog.
	if err := h.st.SetRsyslogCert(caCertPEM); err != nil {
		return err
	}

	// Write the certificates and key. The CA certificate must be written last for idempotency.
	for _, pair := range []struct {
		path string
		data string
	}{
		{h.syslogConfig.ServerCertPath(), rsyslogCertPEM},
		{h.syslogConfig.ServerKeyPath(), rsyslogKeyPEM},
		{h.syslogConfig.CACertPath(), caCertPEM},
	} {
		if err := writeFileAtomic(pair.path, []byte(pair.data), 0600, syslogUid, syslogGid); err != nil {
			return err
		}
	}
	return nil
}