// Tests that the server has handshaked the connection and seen the client // protocol announcement. Does not nest that the connection.open is successful. func TestTLSHandshake(t *testing.T) { srv := startTlsServer() defer srv.Close() cfg := new(tls.Config) cfg.RootCAs = x509.NewCertPool() cfg.RootCAs.AppendCertsFromPEM([]byte(caCert)) cert, _ := tls.X509KeyPair([]byte(clientCert), []byte(clientKey)) cfg.Certificates = append(cfg.Certificates, cert) _, err := amqp.DialTLS(srv.URL, cfg) select { case <-time.After(10 * time.Millisecond): t.Fatalf("did not succeed to handshake the TLS connection after 10ms") case header := <-srv.Header: if string(header) != "AMQP" { t.Fatalf("expected to handshake a TLS connection, got err: %v", err) } } }
// AmqpChannel sets a AMQP connection up using SSL if configuration is provided func AmqpChannel(conf cmd.Config) (*amqp.Channel, error) { var conn *amqp.Connection var err error log := blog.GetAuditLogger() if conf.AMQP.Insecure == true { // If the Insecure flag is true, then just go ahead and connect conn, err = amqp.Dial(conf.AMQP.Server) } else { // The insecure flag is false or not set, so we need to load up the options log.Info("AMQPS: Loading TLS Options.") if strings.HasPrefix(conf.AMQP.Server, "amqps") == false { err = fmt.Errorf("AMQPS: Not using an AMQPS URL. To use AMQP instead of AMQPS, set insecure=true.") return nil, err } if conf.AMQP.TLS == nil { err = fmt.Errorf("AMQPS: No TLS configuration provided. To use AMQP instead of AMQPS, set insecure=true.") return nil, err } cfg := new(tls.Config) // If the configuration specified a certificate (or key), load them if conf.AMQP.TLS.CertFile != nil || conf.AMQP.TLS.KeyFile != nil { // But they have to give both. if conf.AMQP.TLS.CertFile == nil || conf.AMQP.TLS.KeyFile == nil { err = fmt.Errorf("AMQPS: You must set both of the configuration values AMQP.TLS.KeyFile and AMQP.TLS.CertFile") return nil, err } cert, err := tls.LoadX509KeyPair(*conf.AMQP.TLS.CertFile, *conf.AMQP.TLS.KeyFile) if err != nil { err = fmt.Errorf("AMQPS: Could not load Client Certificate or Key: %s", err) return nil, err } log.Info("AMQPS: Configured client certificate for AMQPS.") cfg.Certificates = append(cfg.Certificates, cert) } // If the configuration specified a CA certificate, make it the only // available root. if conf.AMQP.TLS.CACertFile != nil { cfg.RootCAs = x509.NewCertPool() ca, err := ioutil.ReadFile(*conf.AMQP.TLS.CACertFile) if err != nil { err = fmt.Errorf("AMQPS: Could not load CA Certificate: %s", err) return nil, err } cfg.RootCAs.AppendCertsFromPEM(ca) log.Info("AMQPS: Configured CA certificate for AMQPS.") } conn, err = amqp.DialTLS(conf.AMQP.Server, cfg) } if err != nil { return nil, err } err = AMQPDeclareExchange(conn) if err != nil { return nil, err } return conn.Channel() }
// AmqpChannel sets a AMQP connection up using SSL if configuration is provided func AmqpChannel(conf cmd.Config) (*amqp.Channel, error) { var conn *amqp.Connection var err error log := blog.GetAuditLogger() if conf.AMQP.TLS == nil { // Configuration did not specify TLS options, but Dial will // use TLS anyway if the URL scheme is "amqps" conn, err = amqp.Dial(conf.AMQP.Server) } else { // They provided TLS options, so let's load them. log.Info("AMQPS: Loading TLS Options.") if strings.HasPrefix(conf.AMQP.Server, "amqps") == false { err = fmt.Errorf("AMQPS: TLS configuration provided, but not using an AMQPS URL") return nil, err } cfg := new(tls.Config) // If the configuration specified a certificate (or key), load them if conf.AMQP.TLS.CertFile != nil || conf.AMQP.TLS.KeyFile != nil { // But they have to give both. if conf.AMQP.TLS.CertFile == nil || conf.AMQP.TLS.KeyFile == nil { err = fmt.Errorf("AMQPS: You must set both of the configuration values AMQP.TLS.KeyFile and AMQP.TLS.CertFile") return nil, err } cert, err := tls.LoadX509KeyPair(*conf.AMQP.TLS.CertFile, *conf.AMQP.TLS.KeyFile) if err != nil { err = fmt.Errorf("AMQPS: Could not load Client Certificate or Key: %s", err) return nil, err } log.Info("AMQPS: Configured client certificate for AMQPS.") cfg.Certificates = append(cfg.Certificates, cert) } // If the configuration specified a CA certificate, make it the only // available root. if conf.AMQP.TLS.CACertFile != nil { cfg.RootCAs = x509.NewCertPool() ca, err := ioutil.ReadFile(*conf.AMQP.TLS.CACertFile) if err != nil { err = fmt.Errorf("AMQPS: Could not load CA Certificate: %s", err) return nil, err } cfg.RootCAs.AppendCertsFromPEM(ca) log.Info("AMQPS: Configured CA certificate for AMQPS.") } conn, err = amqp.DialTLS(conf.AMQP.Server, cfg) } if err != nil { return nil, err } err = AMQPDeclareExchange(conn) if err != nil { return nil, err } return conn.Channel() }
func ExampleDialTLS() { // To get started with SSL/TLS follow the instructions for adding SSL/TLS // support in RabbitMQ with a private certificate authority here: // // http://www.rabbitmq.com/ssl.html // // Then in your rabbitmq.config, disable the plain AMQP port, verify clients // and fail if no certificate is presented with the following: // // [ // {rabbit, [ // {tcp_listeners, []}, % listens on 127.0.0.1:5672 // {ssl_listeners, [5671]}, % listens on 0.0.0.0:5671 // {ssl_options, [{cacertfile,"/path/to/your/testca/cacert.pem"}, // {certfile,"/path/to/your/server/cert.pem"}, // {keyfile,"/path/to/your/server/key.pem"}, // {verify,verify_peer}, // {fail_if_no_peer_cert,true}]} // ]} // ]. cfg := new(tls.Config) // The self-signing certificate authority's certificate must be included in // the RootCAs to be trusted so that the server certificate can be verified. // // Alternatively to adding it to the tls.Config you can add the CA's cert to // your system's root CAs. The tls package will use the system roots // specific to each support OS. Under OS X, add (drag/drop) your cacert.pem // file to the 'Certificates' section of KeyChain.app to add and always // trust. // // Or with the command line add and trust the DER encoded certificate: // // security add-certificate testca/cacert.cer // security add-trusted-cert testca/cacert.cer // // If you depend on the system root CAs, then use nil for the RootCAs field // so the system roots will be loaded. cfg.RootCAs = x509.NewCertPool() if ca, err := ioutil.ReadFile("testca/cacert.pem"); err == nil { cfg.RootCAs.AppendCertsFromPEM(ca) } // Move the client cert and key to a location specific to your application // and load them here. if cert, err := tls.LoadX509KeyPair("client/cert.pem", "client/key.pem"); err == nil { cfg.Certificates = append(cfg.Certificates, cert) } // Server names are validated by the crypto/tls package, so the server // certificate must be made for the hostname in the URL. Find the commonName // (CN) and make sure the hostname in the URL matches this common name. Per // the RabbitMQ instructions for a self-signed cert, this defautls to the // current hostname. // // openssl x509 -noout -in server/cert.pem -subject // // If your server name in your certificate is different than the host you are // connecting to, set the hostname used for verification in // ServerName field of the tls.Config struct. conn, err := amqp.DialTLS("amqps://server-name-from-certificate/", cfg) log.Printf("conn: %v, err: %v", conn, err) }