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") }
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") }
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) } }
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) }
// 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) }
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) }
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 }
// 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) }
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) }
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) }
// 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 }
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) }
// 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) }
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) }
// 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 }