func (c *tlsClient) Connect(timeout time.Duration) error { host, _, err := net.SplitHostPort(c.hostport) if err != nil { return err } var tlsconfig tls.Config tlsconfig.MinVersion = c.tls.MinVersion tlsconfig.RootCAs = c.tls.RootCAs tlsconfig.Certificates = c.tls.Certificates tlsconfig.ServerName = host if err := c.tcpClient.Connect(timeout); err != nil { return c.onFail(err) } socket := tls.Client(c.Conn, &tlsconfig) if err := socket.SetDeadline(time.Now().Add(timeout)); err != nil { _ = socket.Close() return c.onFail(err) } if err := socket.Handshake(); err != nil { _ = socket.Close() return c.onFail(err) } c.Conn = socket c.connected = true return nil }
// SecureCiphers updates a *tls.Config with a secure ciphersuite configuration. // If c is nil, a new config will be provided. func SecureCiphers(c *tls.Config) *tls.Config { if c == nil { c = &tls.Config{} } c.MinVersion = tls.VersionTLS10 // disable SSLv3 c.MaxVersion = tls.VersionTLS12 // enable TLS_FALLBACK_SCSV: https://go-review.googlesource.com/#/c/1776/ // Use all available ciphersuites minus RC4 and 3DES in a sane order. // This configuration has forward secrecy for supported browsers, and gets // an ‘A’ grade on SSL Labs. c.CipherSuites = []uint16{ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, tls.TLS_RSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA, } c.PreferServerCipherSuites = true return c }
// NewClient returns a new docker test client. func NewClient() ( cli *client.DockerCli, stdout *io.PipeReader, stdoutPipe *io.PipeWriter) { proto, addr, _ := DockerHost() stdout, stdoutPipe = io.Pipe() dockerCertPath := os.Getenv("DOCKER_CERT_PATH") // Boot2docker use TLS per default, Jenkins not if dockerCertPath != "" { var ( tlsConfig tls.Config ) tlsConfig.InsecureSkipVerify = true flCert := filepath.Join(dockerCertPath, defaultCertFile) flKey := filepath.Join(dockerCertPath, defaultKeyFile) _, errCert := os.Stat(flCert) _, errKey := os.Stat(flKey) if errCert == nil && errKey == nil { cert, err := tls.LoadX509KeyPair(flCert, flKey) if err != nil { log.Fatalf("Couldn't load X509 key pair: %s. Key encrypted?", err) } tlsConfig.Certificates = []tls.Certificate{cert} } // Avoid fallback to SSL protocols < TLS1.0 tlsConfig.MinVersion = tls.VersionTLS10 cli = client.NewDockerCli(nil, stdoutPipe, nil, nil, proto, addr, &tlsConfig) } else { cli = client.NewDockerCli(nil, stdoutPipe, nil, nil, proto, addr, nil) } return }
func (s *Server) Serve() error { var tlsconfig tls.Config tlsconfig.MinVersion = tls.VersionTLS10 cert, err := tls.LoadX509KeyPair(s.SSLCertificate, s.SSLKey) if err != nil { return fmt.Errorf("Failed loading client ssl certificate: %s", err) } tlsconfig.Certificates = []tls.Certificate{cert} tlsconfig.Rand = rand.Reader service := fmt.Sprintf("0.0.0.0:%s", s.Port) listener, err := tls.Listen("tcp", service, &tlsconfig) if err != nil { return err } log.Print("server: listening") for { conn, err := listener.Accept() if err != nil { log.Printf("server: accept: %s", err) break } defer conn.Close() log.Printf("server: accepted from %s", conn.RemoteAddr()) go s.handleClient(conn) } return nil }
// NewTLSConfig returns an initialized TLS configuration suitable for client // authentication. If caFile is non-empty, it will be loaded. func NewTLSConfig(caFile string, mutualTLS bool) (*tls.Config, error) { var c tls.Config // TLS 1.0 at a minimum (for mysql) c.MinVersion = tls.VersionTLS10 c.PreferServerCipherSuites = true if mutualTLS { log.Info("MutualTLS requested, client certificates will be verified") c.ClientAuth = tls.VerifyClientCertIfGiven } if caFile != "" { data, err := ioutil.ReadFile(caFile) if err != nil { return &c, err } c.ClientCAs = x509.NewCertPool() if !c.ClientCAs.AppendCertsFromPEM(data) { return &c, errors.New("No certificates parsed") } log.Info("Read in CA file:", caFile) } c.BuildNameToCertificate() return &c, nil }
func (host *Host) getTLSConfig() (*tls.Config, error) { var tlsConfig tls.Config if !host.TLS { return nil, nil } tlsConfig.InsecureSkipVerify = !host.TLSVerify if host.TLSVerify { certPool := x509.NewCertPool() file, err := ioutil.ReadFile(host.TLSCaCert) if err != nil { return nil, err } certPool.AppendCertsFromPEM(file) tlsConfig.RootCAs = certPool } cert, err := tls.LoadX509KeyPair(host.TLSCert, host.TLSKey) if err != nil { return nil, err } tlsConfig.Certificates = []tls.Certificate{cert} tlsConfig.MinVersion = tls.VersionTLS10 return &tlsConfig, nil }
func getTlsConfig(verify bool, cert, key, ca string) (*tls.Config, error) { var config tls.Config config.InsecureSkipVerify = true if verify { certPool := x509.NewCertPool() file, err := ioutil.ReadFile(ca) if err != nil { return nil, err } certPool.AppendCertsFromPEM(file) config.RootCAs = certPool config.InsecureSkipVerify = false } _, errCert := os.Stat(cert) _, errKey := os.Stat(key) if errCert == nil || errKey == nil { tlsCert, err := tls.LoadX509KeyPair(cert, key) if err != nil { return nil, fmt.Errorf("Couldn't load X509 key pair: %v. Key encrpyted?\n", err) } config.Certificates = []tls.Certificate{tlsCert} } config.MinVersion = tls.VersionTLS10 return &config, nil }
// This is like a combination of http.ListenAndServe and http.ListenAndServeTLS, which also // uses ThrottledListen to limit the number of open HTTP connections. func ListenAndServeHTTP(addr string, connLimit int, certFile *string, keyFile *string, handler http.Handler, readTimeout *int, writeTimeout *int) error { var config *tls.Config if certFile != nil { config = &tls.Config{} config.MinVersion = tls.VersionTLS10 // Disable SSLv3 due to POODLE vulnerability config.NextProtos = []string{"http/1.1"} config.Certificates = make([]tls.Certificate, 1) var err error config.Certificates[0], err = tls.LoadX509KeyPair(*certFile, *keyFile) if err != nil { return err } } listener, err := ThrottledListen("tcp", addr, connLimit) if err != nil { return err } if config != nil { listener = tls.NewListener(listener, config) } defer listener.Close() server := &http.Server{Addr: addr, Handler: handler} if readTimeout != nil { server.ReadTimeout = time.Duration(*readTimeout) * time.Second } if writeTimeout != nil { server.WriteTimeout = time.Duration(*writeTimeout) * time.Second } return server.Serve(listener) }
func setupTls(caFile, certFile, keyFile string) { if caFile == "" || certFile == "" || keyFile == "" { return } caData, err := ioutil.ReadFile(caFile) if os.IsNotExist(err) { return } if err != nil { fmt.Fprintf(os.Stderr, "Unable to load CA file\t%s\n", err) os.Exit(1) } caCertPool := x509.NewCertPool() if !caCertPool.AppendCertsFromPEM(caData) { fmt.Fprintln(os.Stderr, "Unable to parse CA file") os.Exit(1) } clientConfig := new(tls.Config) clientConfig.InsecureSkipVerify = true clientConfig.MinVersion = tls.VersionTLS12 clientConfig.RootCAs = caCertPool cert, err := tls.LoadX509KeyPair(certFile, keyFile) if os.IsNotExist(err) { return } if err != nil { fmt.Fprintf(os.Stderr, "Unable to load keypair\t%s\n", err) os.Exit(1) } clientConfig.Certificates = append(clientConfig.Certificates, cert) srpc.RegisterClientTlsConfig(clientConfig) }
func Init(messageQueue chan *bl.Message, conf map[string]interface{}) bl.Input { var tlsConfig tls.Config tag := bl.GString("tag", conf) bind := bl.GString("bind", conf) timeout := int64(bl.GInt("timeout", conf)) if timeout <= 0 { log.Fatalf("[ERROR] [%s] You must specify right timeout (%d)", module, timeout) } SSLCertificate := bl.GString("ssl_cert", conf) SSLKey := bl.GString("ssl_key", conf) SSLCA := bl.GString("ssl_ca", conf) if len(SSLCertificate) > 0 && len(SSLKey) > 0 { tlsConfig.MinVersion = tls.VersionTLS12 log.Printf("[INFO] [%s] Loading server ssl certificate and key from \"%s\" and \"%s\"", tag, SSLCertificate, SSLKey) cert, err := tls.LoadX509KeyPair(SSLCertificate, SSLKey) if err != nil { log.Fatalf("[ERROR] [%s] Failed loading server ssl certificate: %s", tag, err) } tlsConfig.Certificates = []tls.Certificate{cert} if len(SSLCA) > 0 { log.Printf("[INFO] [%s] Loading CA certificate from file: %s\n", tag, SSLCA) tlsConfig.ClientCAs = x509.NewCertPool() tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert pemdata, err := ioutil.ReadFile(SSLCA) if err != nil { log.Fatalf("[ERROR] [%s] Failure reading CA certificate: %s\n", tag, err) } block, _ := pem.Decode(pemdata) if block == nil { log.Fatalf("[ERROR] [%s] Failed to decode PEM data of CA certificate from \"%s\"\n", tag, SSLCA) } if block.Type != "CERTIFICATE" { log.Fatalf("[ERROR] [%s] This is not a certificate file: %s\n", tag, SSLCA) } cacert, err := x509.ParseCertificate(block.Bytes) if err != nil { log.Fatalf("[ERROR] [%s] Failed to parse CA certificate: %s\n", tag, SSLCA) } tlsConfig.ClientCAs.AddCert(cacert) } v := &In_logear_forwarder{tag: tag, messageQueue: messageQueue, tlsConfig: tlsConfig, bind: bind, timeout: time.Second * time.Duration(timeout)} return v } else { log.Fatalf("[ERROR] [%s] You must specify ssl_cert and ssl_key", module) } return nil }
func newDockerClient() *client.DockerCli { // Set terminal emulation based on platform as required. stdin, stdout, stderr := term.StdStreams() setDefaultConfFlag(flTrustKey, defaultTrustKeyFile) if len(flHosts) > 1 { log.Fatal("Please specify only one -H") } protoAddrParts := strings.SplitN(flHosts[0], "://", 2) var ( cli *client.DockerCli tlsConfig tls.Config ) tlsConfig.InsecureSkipVerify = true // Regardless of whether the user sets it to true or false, if they // specify --tlsverify at all then we need to turn on tls if flag.IsSet("-tlsverify") { *flTls = true } // If we should verify the server, we need to load a trusted ca if *flTlsVerify { certPool := x509.NewCertPool() file, err := ioutil.ReadFile(*flCa) if err != nil { log.Fatalf("Couldn't read ca cert %s: %s", *flCa, err) } certPool.AppendCertsFromPEM(file) tlsConfig.RootCAs = certPool tlsConfig.InsecureSkipVerify = false } // If tls is enabled, try to load and send client certificates if *flTls || *flTlsVerify { _, errCert := os.Stat(*flCert) _, errKey := os.Stat(*flKey) if errCert == nil && errKey == nil { *flTls = true cert, err := tls.LoadX509KeyPair(*flCert, *flKey) if err != nil { log.Fatalf("Couldn't load X509 key pair: %q. Make sure the key is encrypted", err) } tlsConfig.Certificates = []tls.Certificate{cert} } // Avoid fallback to SSL protocols < TLS1.0 tlsConfig.MinVersion = tls.VersionTLS10 } cli = client.NewDockerCli(stdin, stdout, stderr, *flTrustKey, protoAddrParts[0], protoAddrParts[1], &tlsConfig) return cli }
// SecureTLSConfig enforces the default minimum security settings for the // cluster. // TODO: allow override func SecureTLSConfig(config *tls.Config) *tls.Config { // Recommendations from https://wiki.mozilla.org/Security/Server_Side_TLS // Can't use SSLv3 because of POODLE and BEAST // Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher // Can't use TLSv1.1 because of RC4 cipher usage config.MinVersion = tls.VersionTLS12 // In a legacy environment, allow cipher control to be disabled. if len(os.Getenv("OPENSHIFT_ALLOW_DANGEROUS_TLS_CIPHER_SUITES")) == 0 { config.PreferServerCipherSuites = true config.CipherSuites = []uint16{ // Ciphers below are selected and ordered based on the recommended "Intermediate compatibility" suite // Compare with available ciphers when bumping Go versions // // Available ciphers from last comparison (go 1.6): // TLS_RSA_WITH_RC4_128_SHA - no // TLS_RSA_WITH_3DES_EDE_CBC_SHA // TLS_RSA_WITH_AES_128_CBC_SHA // TLS_RSA_WITH_AES_256_CBC_SHA // TLS_RSA_WITH_AES_128_GCM_SHA256 // TLS_RSA_WITH_AES_256_GCM_SHA384 // TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - no // TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA // TLS_ECDHE_RSA_WITH_RC4_128_SHA - no // TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA // TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, // the next two are in the intermediate suite, but go1.6 http2 complains when they are included at the recommended index // fixed in https://github.com/golang/go/commit/b5aae1a2845f157a2565b856fb2d7773a0f7af25 in go1.7 // tls.TLS_RSA_WITH_AES_128_GCM_SHA256, // tls.TLS_RSA_WITH_AES_256_GCM_SHA384, tls.TLS_RSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, } } else { glog.Warningf("Potentially insecure TLS cipher suites are allowed in client connections because environment variable OPENSHIFT_ALLOW_DANGEROUS_TLS_CIPHER_SUITES is set") } return config }
// ListenAndServeTLSWithSNI serves TLS with Server Name Indication (SNI) support, which allows // multiple sites (different hostnames) to be served from the same address. This method is // adapted directly from the std lib's net/http ListenAndServeTLS function, which was // written by the Go Authors. It has been modified to support multiple certificate/key pairs. func ListenAndServeTLSWithSNI(srv *http.Server, tlsConfigs []TLSConfig) error { addr := srv.Addr if addr == "" { addr = ":https" } config := new(tls.Config) if srv.TLSConfig != nil { *config = *srv.TLSConfig } if config.NextProtos == nil { config.NextProtos = []string{"http/1.1"} } // Here we diverge from the stdlib a bit by loading multiple certs/key pairs // then we map the server names to their certs var err error config.Certificates = make([]tls.Certificate, len(tlsConfigs)) for i, tlsConfig := range tlsConfigs { config.Certificates[i], err = tls.LoadX509KeyPair(tlsConfig.Certificate, tlsConfig.Key) if err != nil { return err } } config.BuildNameToCertificate() // Customize our TLS configuration config.MinVersion = tlsConfigs[0].ProtocolMinVersion config.MaxVersion = tlsConfigs[0].ProtocolMaxVersion config.CipherSuites = tlsConfigs[0].Ciphers config.PreferServerCipherSuites = tlsConfigs[0].PreferServerCipherSuites // TLS client authentication, if user enabled it err = setupClientAuth(tlsConfigs, config) if err != nil { return err } // Create listener and we're on our way conn, err := net.Listen("tcp", addr) if err != nil { return err } tlsListener := tls.NewListener(conn, config) return srv.Serve(tlsListener) }
func setTLSMinVersion(config Config, section string, tlsConfig *tls.Config) { // Default to TLSv1.2. minVersion := tls.VersionTLS12 minVersionString, err := config.GetString(section, "minVersion") if err == nil { switch minVersionString { case "SSLv3": minVersion = tls.VersionSSL30 case "TLSv1": minVersion = tls.VersionTLS10 case "TLSv1.1": minVersion = tls.VersionTLS11 case "TLSv1.2": minVersion = tls.VersionTLS12 } } tlsConfig.MinVersion = uint16(minVersion) }
func setupTls(certFile, keyFile string) { if certFile == "" || keyFile == "" { return } clientConfig := new(tls.Config) clientConfig.InsecureSkipVerify = true clientConfig.MinVersion = tls.VersionTLS12 cert, err := tls.LoadX509KeyPair(certFile, keyFile) if os.IsNotExist(err) { return } if err != nil { fmt.Fprintf(os.Stderr, "Unable to load keypair\t%s\n", err) os.Exit(1) } clientConfig.Certificates = append(clientConfig.Certificates, cert) srpc.RegisterClientTlsConfig(clientConfig) }
func ListenAndServeTLSWithSNI(srv *http.Server, tlsConfigs []TLSConfig) error { addr := srv.Addr if addr == "" { addr = ":https" } config := new(tls.Config) if srv.TLSConfig != nil { *config = *srv.TLSConfig } if config.NextProtos == nil { config.NextProtos = []string{"http/1.1"} } var err error config.Certificates = make([]tls.Certificate, len(tlsConfigs)) for i, tlsConfig := range tlsConfigs { config.Certificates[i], err = tls.LoadX509KeyPair(tlsConfig.Certificate, tlsConfig.Key) if err != nil { return err } } config.BuildNameToCertificate() config.MinVersion = tlsConfigs[0].ProtocolMinVersion config.MaxVersion = tlsConfigs[0].ProtocolMaxVersion config.CipherSuites = tlsConfigs[0].Ciphers config.PreferServerCipherSuites = tlsConfigs[0].PreferServerCipherSuites err = setupClientAuth(tlsConfigs, config) if err != nil { return err } conn, err := net.Listen("tcp", addr) if err != nil { return err } tlsListener := tls.NewListener(conn, config) return srv.Serve(tlsListener) }
func dialDocker() (net.Conn, error) { host := os.Getenv("DOCKER_HOST") if host == "" { return nil, fmt.Errorf("DOCKER_HOST environment variable not set") } host = strings.TrimPrefix(host, "tcp://") certPath := os.Getenv("DOCKER_CERT_PATH") if certPath == "" { return net.Dial("tcp", host) } tlsConfig := tls.Config{} tlsConfig.InsecureSkipVerify = os.Getenv("DOCKER_TLS_VERIFY") != "1" if !tlsConfig.InsecureSkipVerify { ca := filepath.Join(certPath, "ca.pem") file, err := ioutil.ReadFile(ca) if err != nil { return nil, fmt.Errorf("Couldn't read ca cert %s: %s", ca, err) } certPool := x509.NewCertPool() if !certPool.AppendCertsFromPEM(file) { return nil, fmt.Errorf("%s contained no certs", ca) } tlsConfig.RootCAs = certPool certFile := filepath.Join(certPath, "cert.pem") keyFile := filepath.Join(certPath, "key.pem") cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { return nil, fmt.Errorf("Couldn't load X509 key pair: %v", err) } tlsConfig.Certificates = []tls.Certificate{cert} // Avoid fallback to SSL protocols < TLS1.0 tlsConfig.MinVersion = tls.VersionTLS10 } return tls.Dial("tcp", host, &tlsConfig) }
// NewDefaultClient provides an arch specific default docker client. // On linux it connects to the default docker socket, on OS X it looks for // boot2docker environment variables. func NewDefaultClient(timeout time.Duration) (*Client, error) { host := os.Getenv("DOCKER_HOST") if host == "" { return nil, fmt.Errorf("DOCKER_HOST environment variable not set") } certPath := os.Getenv("DOCKER_CERT_PATH") if certPath == "" { return NewClient(host, nil, timeout) } tlsConfig := tls.Config{} tlsConfig.InsecureSkipVerify = true tlsVerify := os.Getenv("DOCKER_TLS_VERIFY") if tlsVerify == "1" { certPool := x509.NewCertPool() ca := filepath.Join(certPath, "ca.pem") file, err := ioutil.ReadFile(ca) if err != nil { return nil, fmt.Errorf("Couldn't read ca cert %s: %s", ca, err) } certPool.AppendCertsFromPEM(file) tlsConfig.RootCAs = certPool tlsConfig.InsecureSkipVerify = false certFile := filepath.Join(certPath, "cert.pem") keyFile := filepath.Join(certPath, "key.pem") cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { return nil, fmt.Errorf("Couldn't load X509 key pair: %v", err) } tlsConfig.Certificates = []tls.Certificate{cert} // Avoid fallback to SSL protocols < TLS1.0 tlsConfig.MinVersion = tls.VersionTLS10 } return NewClient(host, &tlsConfig, timeout) }
func setupTls(ignoreMissingCerts bool) error { if *certDirectory == "" { return nil } // Load certificates. certs, err := srpc.LoadCertificates(*certDirectory) if err != nil { return err } if certs == nil { if ignoreMissingCerts { return nil } return srpc.ErrorMissingCertificate } // Setup client. clientConfig := new(tls.Config) clientConfig.InsecureSkipVerify = true clientConfig.MinVersion = tls.VersionTLS12 clientConfig.Certificates = certs srpc.RegisterClientTlsConfig(clientConfig) return nil }
// setupTLSConfig returns a tls.Config for a credential set func setupTLSConfig(cert []byte, key []byte, ca []byte) (*tls.Config, error) { // TLS config var tlsConfig tls.Config //Use only modern ciphers tlsConfig.CipherSuites = []uint16{ tls.TLS_RSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, } // Use only TLS v1.2 tlsConfig.MinVersion = tls.VersionTLS12 // Don't allow session resumption tlsConfig.SessionTicketsDisabled = true certPool := x509.NewCertPool() certPool.AppendCertsFromPEM(ca) tlsConfig.RootCAs = certPool tlsConfig.ClientCAs = certPool tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert keypair, err := tls.X509KeyPair(cert, key) if err != nil { return &tlsConfig, err } tlsConfig.Certificates = []tls.Certificate{keypair} return &tlsConfig, nil }
func setupTls(caFile, certFile, keyFile string) { if caFile == "" || certFile == "" || keyFile == "" { return } // Load certificates and key. caData, err := ioutil.ReadFile(caFile) if os.IsNotExist(err) { return } if err != nil { fmt.Fprintf(os.Stderr, "Unable to load CA file\t%s\n", err) os.Exit(1) } caCertPool := x509.NewCertPool() if !caCertPool.AppendCertsFromPEM(caData) { fmt.Fprintln(os.Stderr, "Unable to parse CA file") os.Exit(1) } // Setup server. serverConfig := new(tls.Config) serverConfig.ClientAuth = tls.RequireAndVerifyClientCert serverConfig.MinVersion = tls.VersionTLS12 serverConfig.ClientCAs = caCertPool cert, err := tls.LoadX509KeyPair(certFile, keyFile) if os.IsNotExist(err) { return } if err != nil { fmt.Fprintf(os.Stderr, "Unable to load keypair\t%s\n", err) os.Exit(1) } serverConfig.Certificates = append(serverConfig.Certificates, cert) srpc.RegisterServerTlsConfig(serverConfig, true) }
func getDockerClient(ctx *cli.Context) docker.Docker { docker, err := docker.NewClient(ctx.GlobalString("host")) var tlsConfig tls.Config tlsConfig.InsecureSkipVerify = true if ctx.GlobalBool("tls") || ctx.GlobalString("tlsverify") != "" { if ctx.GlobalString("tlsverify") != "" { certPool := x509.NewCertPool() file, err := ioutil.ReadFile(ctx.GlobalString("tlscacert")) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } certPool.AppendCertsFromPEM(file) tlsConfig.RootCAs = certPool tlsConfig.InsecureSkipVerify = false } _, errCert := os.Stat(ctx.GlobalString("tlscert")) _, errKey := os.Stat(ctx.GlobalString("tlskey")) if errCert == nil || errKey == nil { cert, err := tls.LoadX509KeyPair(ctx.GlobalString("tlscert"), ctx.GlobalString("tlskey")) if err != nil { fmt.Fprintf(os.Stderr, "Couldn't load X509 key pair: %s. Key encrpyted?\n", err) os.Exit(1) } tlsConfig.Certificates = []tls.Certificate{cert} } tlsConfig.MinVersion = tls.VersionTLS10 docker.SetTlsConfig(&tlsConfig) } if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } return docker }
// SecureTLSConfig enforces the default minimum security settings for the // cluster. // TODO: allow override func SecureTLSConfig(config *tls.Config) *tls.Config { // Recommendations from https://wiki.mozilla.org/Security/Server_Side_TLS // Change default from SSLv3 to TLSv1.0 (because of POODLE vulnerability) config.MinVersion = tls.VersionTLS10 // In a legacy environment, allow cipher control to be disabled. if len(os.Getenv("OPENSHIFT_ALLOW_DANGEROUS_TLS_CIPHER_SUITES")) == 0 { config.PreferServerCipherSuites = true config.CipherSuites = []uint16{ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, tls.TLS_RSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, } } else { glog.Warningf("Potentially insecure TLS cipher suites are allowed in client connections because environment variable OPENSHIFT_ALLOW_DANGEROUS_TLS_CIPHER_SUITES is set") } return config }
// MakeTLSConfig reduces configs into a single tls.Config. // If TLS is to be disabled, a nil tls.Config will be returned. func MakeTLSConfig(configs []*Config) (*tls.Config, error) { if configs == nil || len(configs) == 0 { return nil, nil } config := new(tls.Config) ciphersAdded := make(map[uint16]struct{}) configMap := make(configGroup) for i, cfg := range configs { if cfg == nil { // avoid nil pointer dereference below configs[i] = new(Config) continue } // Key this config by its hostname; this // overwrites configs with the same hostname configMap[cfg.Hostname] = cfg // Can't serve TLS and not-TLS on same port if i > 0 && cfg.Enabled != configs[i-1].Enabled { thisConfProto, lastConfProto := "not TLS", "not TLS" if cfg.Enabled { thisConfProto = "TLS" } if configs[i-1].Enabled { lastConfProto = "TLS" } return nil, fmt.Errorf("cannot multiplex %s (%s) and %s (%s) on same listener", configs[i-1].Hostname, lastConfProto, cfg.Hostname, thisConfProto) } // Union cipher suites for _, ciph := range cfg.Ciphers { if _, ok := ciphersAdded[ciph]; !ok { ciphersAdded[ciph] = struct{}{} config.CipherSuites = append(config.CipherSuites, ciph) } } // Can't resolve conflicting PreferServerCipherSuites settings if i > 0 && cfg.PreferServerCipherSuites != configs[i-1].PreferServerCipherSuites { return nil, fmt.Errorf("cannot both use PreferServerCipherSuites and not use it") } config.PreferServerCipherSuites = cfg.PreferServerCipherSuites // Go with the widest range of protocol versions if config.MinVersion == 0 || cfg.ProtocolMinVersion < config.MinVersion { config.MinVersion = cfg.ProtocolMinVersion } if cfg.ProtocolMaxVersion > config.MaxVersion { config.MaxVersion = cfg.ProtocolMaxVersion } // Go with the strictest ClientAuth type if cfg.ClientAuth > config.ClientAuth { config.ClientAuth = cfg.ClientAuth } } // Is TLS disabled? If so, we're done here. // By now, we know that all configs agree // whether it is or not, so we can just look // at the first one. if len(configs) == 0 || !configs[0].Enabled { return nil, nil } // Default cipher suites if len(config.CipherSuites) == 0 { config.CipherSuites = defaultCiphers } // For security, ensure TLS_FALLBACK_SCSV is always included if config.CipherSuites[0] != tls.TLS_FALLBACK_SCSV { config.CipherSuites = append([]uint16{tls.TLS_FALLBACK_SCSV}, config.CipherSuites...) } // Set up client authentication if enabled if config.ClientAuth != tls.NoClientCert { pool := x509.NewCertPool() clientCertsAdded := make(map[string]struct{}) for _, cfg := range configs { for _, caFile := range cfg.ClientCerts { // don't add cert to pool more than once if _, ok := clientCertsAdded[caFile]; ok { continue } clientCertsAdded[caFile] = struct{}{} // Any client with a certificate from this CA will be allowed to connect caCrt, err := ioutil.ReadFile(caFile) if err != nil { return nil, err } if !pool.AppendCertsFromPEM(caCrt) { return nil, fmt.Errorf("error loading client certificate '%s': no certificates were successfully parsed", caFile) } } } config.ClientCAs = pool } // Associate the GetCertificate callback, or almost nothing we just did will work config.GetCertificate = configMap.GetCertificate return config, nil }
func (c *Context) CreateClient() error { if c.Client != nil { return nil } if c.Ca == "" { c.Ca = filepath.Join(dockerCertPath, defaultCaFile) } if c.Cert == "" { c.Cert = filepath.Join(dockerCertPath, defaultCertFile) } if c.Key == "" { c.Key = filepath.Join(dockerCertPath, defaultKeyFile) } if c.Host == "" { defaultHost := os.Getenv("DOCKER_HOST") if defaultHost == "" { if runtime.GOOS != "windows" { // If we do not have a host, default to unix socket defaultHost = fmt.Sprintf("unix://%s", opts.DefaultUnixSocket) } else { // If we do not have a host, default to TCP socket on Windows defaultHost = fmt.Sprintf("tcp://%s:%d", opts.DefaultHTTPHost, opts.DefaultHTTPPort) } } defaultHost, err := opts.ValidateHost(defaultHost) if err != nil { return err } c.Host = defaultHost } if c.TrustKey == "" { c.TrustKey = filepath.Join(homedir.Get(), ".docker", defaultTrustKeyFile) } var tlsConfig tls.Config tlsConfig.InsecureSkipVerify = true // Regardless of whether the user sets it to true or false, if they // specify --tlsverify at all then we need to turn on tls if c.TlsVerify { c.Tls = true } // If we should verify the server, we need to load a trusted ca if c.TlsVerify { certPool := x509.NewCertPool() file, err := ioutil.ReadFile(c.Ca) if err != nil { logrus.Errorf("Couldn't read ca cert %s: %s", c.Ca, err) return err } certPool.AppendCertsFromPEM(file) tlsConfig.RootCAs = certPool tlsConfig.InsecureSkipVerify = false } // If tls is enabled, try to load and send client certificates if c.Tls { _, errCert := os.Stat(c.Cert) _, errKey := os.Stat(c.Key) if errCert == nil && errKey == nil { c.Tls = true cert, err := tls.LoadX509KeyPair(c.Cert, c.Key) if err != nil { logrus.Errorf("Couldn't load X509 key pair: %q. Make sure the key is encrypted", err) return err } tlsConfig.Certificates = []tls.Certificate{cert} } // Avoid fallback to SSL protocols < TLS1.0 tlsConfig.MinVersion = tls.VersionTLS10 } if c.Tls { c.tlsConfig = &tlsConfig } client, err := dockerclient.NewDockerClient(c.Host, c.tlsConfig) c.Client = client return err }
func connect(config *NetworkConfig) (socket *tls.Conn) { var tlsconfig tls.Config tlsconfig.MinVersion = tls.VersionTLS10 if len(config.SSLCertificate) > 0 && len(config.SSLKey) > 0 { emit("Loading client ssl certificate: %s and %s\n", config.SSLCertificate, config.SSLKey) cert, err := tls.LoadX509KeyPair(config.SSLCertificate, config.SSLKey) if err != nil { fault("Failed loading client ssl certificate: %s\n", err) } tlsconfig.Certificates = []tls.Certificate{cert} } if len(config.SSLCA) > 0 { emit("Setting trusted CA from file: %s\n", config.SSLCA) tlsconfig.RootCAs = x509.NewCertPool() pemdata, err := ioutil.ReadFile(config.SSLCA) if err != nil { fault("Failure reading CA certificate: %s\n", err) } block, _ := pem.Decode(pemdata) if block == nil { fault("Failed to decode PEM data, is %s a valid cert?\n", config.SSLCA) } if block.Type != "CERTIFICATE" { fault("This is not a certificate file: %s\n", config.SSLCA) } cert, err := x509.ParseCertificate(block.Bytes) if err != nil { fault("Failed to parse a certificate: %s\n", config.SSLCA) } tlsconfig.RootCAs.AddCert(cert) } var host string var port int var addresses []string k := 1 for { // Pick a random server from the list. hostport := config.Servers[rand.Int()%len(config.Servers)] submatch := hostport_re.FindSubmatch([]byte(hostport)) if submatch == nil { fault("Invalid host:port given: %s", hostport) } host = string(submatch[1]) port = string(submatch[2]) emit("%d) DNS lookup name: %s\n", k, host) var err error addresses, err = net.LookupHost(host) if err != nil { emit("DNS lookup failure \"%s\": %s. Retrying...\n", host, err) time.Sleep(2 * k * time.Second) k = k + 1 continue } } for { address := addresses[rand.Int()%len(addresses)] var addressport string ip := net.ParseIP(address) if len(ip) == net.IPv4len { addressport = fmt.Sprintf("%s:%s", address, port) } else if len(ip) == net.IPv6len { addressport = fmt.Sprintf("[%s]:%s", address, port) } emit("Connecting to %s (%s) \n", addressport, host) tcpsocket, err := net.DialTimeout("tcp", addressport, config.timeout) if err != nil { emit("Failure connecting to %s: %s\n", address, err) time.Sleep(1 * time.Second) continue } tlsconfig.ServerName = host socket = tls.Client(tcpsocket, &tlsconfig) socket.SetDeadline(time.Now().Add(config.timeout)) err = socket.Handshake() if err != nil { emit("Failed to tls handshake with %s %s\n", address, err) time.Sleep(1 * time.Second) socket.Close() continue } emit("Connected to %s\n", address) // connected, let's rock and roll. return } return }
func main() { if reexec.Init() { return } flag.Parse() // FIXME: validate daemon flags here if *flVersion { showVersion() return } if *flDebug { os.Setenv("DEBUG", "1") } if len(flHosts) == 0 { defaultHost := os.Getenv("DOCKER_HOST") if defaultHost == "" || *flDaemon { // If we do not have a host, default to unix socket defaultHost = fmt.Sprintf("unix://%s", api.DEFAULTUNIXSOCKET) } defaultHost, err := api.ValidateHost(defaultHost) if err != nil { log.Fatal(err) } flHosts = append(flHosts, defaultHost) } if *flDaemon { mainDaemon() return } if len(flHosts) > 1 { log.Fatal("Please specify only one -H") } protoAddrParts := strings.SplitN(flHosts[0], "://", 2) var ( cli *client.DockerCli tlsConfig tls.Config ) tlsConfig.InsecureSkipVerify = true // If we should verify the server, we need to load a trusted ca if *flTlsVerify { *flTls = true certPool := x509.NewCertPool() file, err := ioutil.ReadFile(*flCa) if err != nil { log.Fatalf("Couldn't read ca cert %s: %s", *flCa, err) } certPool.AppendCertsFromPEM(file) tlsConfig.RootCAs = certPool tlsConfig.InsecureSkipVerify = false } // If tls is enabled, try to load and send client certificates if *flTls || *flTlsVerify { _, errCert := os.Stat(*flCert) _, errKey := os.Stat(*flKey) if errCert == nil && errKey == nil { *flTls = true cert, err := tls.LoadX509KeyPair(*flCert, *flKey) if err != nil { log.Fatalf("Couldn't load X509 key pair: %s. Key encrypted?", err) } tlsConfig.Certificates = []tls.Certificate{cert} } // Avoid fallback to SSL protocols < TLS1.0 tlsConfig.MinVersion = tls.VersionTLS10 } if *flTls || *flTlsVerify { cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, nil, protoAddrParts[0], protoAddrParts[1], &tlsConfig) } else { cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, nil, protoAddrParts[0], protoAddrParts[1], nil) } if err := cli.Cmd(flag.Args()...); err != nil { if sterr, ok := err.(*utils.StatusError); ok { if sterr.Status != "" { log.Infof("%s", sterr.Status) } os.Exit(sterr.StatusCode) } log.Fatal(err) } }
func connect(config *NetworkConfig) (socket *tls.Conn) { var tlsconfig tls.Config tlsconfig.MinVersion = tls.VersionTLS10 if len(config.SSLCertificate) > 0 && len(config.SSLKey) > 0 { emit("Loading client ssl certificate: %s and %s\n", config.SSLCertificate, config.SSLKey) cert, err := tls.LoadX509KeyPair(config.SSLCertificate, config.SSLKey) if err != nil { fault("Failed loading client ssl certificate: %s\n", err) } tlsconfig.Certificates = []tls.Certificate{cert} } if len(config.SSLCA) > 0 { emit("Setting trusted CA certificates from file: %s\n", config.SSLCA) tlsconfig.RootCAs = x509.NewCertPool() pemdata, err := ioutil.ReadFile(config.SSLCA) if err != nil { fault("Failure reading CA certificates: %s\n", err) } if !tlsconfig.RootCAs.AppendCertsFromPEM(pemdata) { fault("Failed to import CA certificates: %s\n", config.SSLCA) } } for { // Pick a random server from the list. hostport := config.Servers[rand.Int()%len(config.Servers)] submatch := hostport_re.FindSubmatch([]byte(hostport)) if submatch == nil { fault("Invalid host:port given: %s", hostport) } host := string(submatch[1]) port := string(submatch[2]) addresses, err := net.LookupHost(host) if err != nil { emit("DNS lookup failure \"%s\": %s\n", host, err) time.Sleep(1 * time.Second) continue } address := addresses[rand.Int()%len(addresses)] var addressport string ip := net.ParseIP(address) if len(ip) == net.IPv4len { addressport = fmt.Sprintf("%s:%s", address, port) } else if len(ip) == net.IPv6len { addressport = fmt.Sprintf("[%s]:%s", address, port) } emit("Connecting to %s (%s) \n", addressport, host) tcpsocket, err := net.DialTimeout("tcp", addressport, config.timeout) if err != nil { emit("Failure connecting to %s: %s\n", address, err) time.Sleep(1 * time.Second) continue } tlsconfig.ServerName = host socket = tls.Client(tcpsocket, &tlsconfig) socket.SetDeadline(time.Now().Add(config.timeout)) err = socket.Handshake() if err != nil { emit("Failed to tls handshake with %s %s\n", address, err) time.Sleep(1 * time.Second) socket.Close() continue } emit("Connected to %s\n", address) // connected, let's rock and roll. return } return }
func main() { http.HandleFunc("/", newLoggingHandleFunc(rootHandler)) http.HandleFunc("/new", newLoggingHandleFunc(newHandler)) http.HandleFunc("/view/", newLoggingHandleFunc(newGzipHandleFunc(titleHandler(viewHandler)))) http.HandleFunc("/edit/", newLoggingHandleFunc(newGzipHandleFunc(titleHandler(editHandler)))) http.HandleFunc("/save/", newLoggingHandleFunc(titleHandler(saveHandler))) http.HandleFunc("/del/", newLoggingHandleFunc(titleHandler(delHandler))) http.HandleFunc("/front", newLoggingHandleFunc(newGzipHandleFunc(frontHandler))) http.HandleFunc("/hsts_hpkp", hsts_hpkp) log.SetPrefix("goWiki: ") log.Println("listening... on port", HTTPS_PORT) go func() { for { err := func() error { var OCSPC OCSPCert var err error cert, err := tls.LoadX509KeyPair(CERT, KEY) if err != nil { return err } OCSPC.cert = &cert if OCSPC.cert.Leaf, err = x509.ParseCertificate(OCSPC.cert.Certificate[0]); err != nil { return err } issuerRAW, err := ioutil.ReadFile(ISSUER) if err != nil { return err } for { var issuerPEM *pem.Block issuerPEM, issuerRAW = pem.Decode(issuerRAW) if issuerPEM == nil { break } if issuerPEM.Type == "CERTIFICATE" { OCSPC.issuer, err = x509.ParseCertificate(issuerPEM.Bytes) if err != nil { return err } } } if OCSPC.issuer == nil { return errors.New("no issuer") } OCSPC.req, err = ocsp.CreateRequest(OCSPC.cert.Leaf, OCSPC.issuer, nil) if err != nil { return err } err = OCSPC.updateStaple() if err != nil { return err } go OCSPC.stapleLoop() TLSConfig := new(tls.Config) TLSConfig.Certificates = []tls.Certificate{cert} TLSConfig.CipherSuites = []uint16{ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, tls.TLS_RSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA} TLSConfig.PreferServerCipherSuites = true TLSConfig.MinVersion = tls.VersionTLS11 //MaxVersion needed because of bug with TLS_FALLBACK_SCSV gonna be fixed in go 1.5 TLSConfig.MaxVersion = tls.VersionTLS12 TLSConfig.NextProtos = []string{"http/1.1"} TLSConfig.GetCertificate = func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { OCSPC.RLock() defer OCSPC.RUnlock() return OCSPC.cert, nil } ln, err := net.Listen("tcp", HTTPS_PORT) if err != nil { return err } tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, TLSConfig) return new(http.Server).Serve(tlsListener) }() if err != nil { log.Println(err) } time.Sleep(time.Second * TIMEOUT) } }() for { log.Println("redirecting from port", HTTP_PORT, "to", HTTPS_PORT) err := http.ListenAndServe(HTTP_PORT, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-Frame-Options", "SAMEORIGIN") w.Header().Set("Server", "Jesus") log.Println("redirecting http", r.RemoteAddr, "to https", DOMAIN+HTTPS_PORT+r.URL.Path) http.Redirect(w, r, "https://"+DOMAIN+HTTPS_PORT+r.URL.Path, http.StatusMovedPermanently) })) if err != nil { log.Println(err) } time.Sleep(time.Second * TIMEOUT) } }
func main() { if reexec.Init() { return } flag.Parse() // FIXME: validate daemon flags here if *flVersion { showVersion() return } if *flLogLevel != "" { lvl, err := log.ParseLevel(*flLogLevel) if err != nil { log.Fatalf("Unable to parse logging level: %s", *flLogLevel) } initLogging(lvl) } else { initLogging(log.InfoLevel) } // -D, --debug, -l/--log-level=debug processing // When/if -D is removed this block can be deleted if *flDebug { os.Setenv("DEBUG", "1") initLogging(log.DebugLevel) } if len(flHosts) == 0 { defaultHost := os.Getenv("DOCKER_HOST") if defaultHost == "" || *flDaemon { // If we do not have a host, default to unix socket defaultHost = fmt.Sprintf("unix://%s", api.DEFAULTUNIXSOCKET) } defaultHost, err := api.ValidateHost(defaultHost) if err != nil { log.Fatal(err) } flHosts = append(flHosts, defaultHost) } setDefaultConfFlag(flTrustKey, defaultTrustKeyFile) if *flDaemon { mainDaemon() return } if len(flHosts) > 1 { log.Fatal("Please specify only one -H") } protoAddrParts := strings.SplitN(flHosts[0], "://", 2) var ( cli *client.DockerCli tlsConfig tls.Config ) tlsConfig.InsecureSkipVerify = true // Regardless of whether the user sets it to true or false, if they // specify --tlsverify at all then we need to turn on tls if flag.IsSet("-tlsverify") { *flTls = true } // If we should verify the server, we need to load a trusted ca if *flTlsVerify { certPool := x509.NewCertPool() file, err := ioutil.ReadFile(*flCa) if err != nil { log.Fatalf("Couldn't read ca cert %s: %s", *flCa, err) } certPool.AppendCertsFromPEM(file) tlsConfig.RootCAs = certPool tlsConfig.InsecureSkipVerify = false } // If tls is enabled, try to load and send client certificates if *flTls || *flTlsVerify { _, errCert := os.Stat(*flCert) _, errKey := os.Stat(*flKey) if errCert == nil && errKey == nil { *flTls = true cert, err := tls.LoadX509KeyPair(*flCert, *flKey) if err != nil { log.Fatalf("Couldn't load X509 key pair: %s. Key encrypted?", err) } tlsConfig.Certificates = []tls.Certificate{cert} } // Avoid fallback to SSL protocols < TLS1.0 tlsConfig.MinVersion = tls.VersionTLS10 } if *flTls || *flTlsVerify { cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, *flTrustKey, protoAddrParts[0], protoAddrParts[1], &tlsConfig) } else { cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, *flTrustKey, protoAddrParts[0], protoAddrParts[1], nil) } if err := cli.Cmd(flag.Args()...); err != nil { if sterr, ok := err.(*utils.StatusError); ok { if sterr.Status != "" { log.Println(sterr.Status) } os.Exit(sterr.StatusCode) } log.Fatal(err) } }