// Starts listening for client connections. // When a new application connects, launches listeners in a goroutine. // Returns an error when error occurs. func StartListen(port int, useTls bool, crtPath string, keyPath string, sname string) error { // Create a listening address addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf(":%d", port)) if err != nil { return err } // start a new server and listen on the address var l net.Listener l, err = net.ListenTCP("tcp", addr) if err != nil { return err } // wrap with TLS if required if useTls { cert, err := tls.LoadX509KeyPair(crtPath, keyPath) if err != nil { return err } conf := tls.Config{} certs := make([]tls.Certificate, 1) certs[0] = cert conf.Certificates = certs cp := x509.NewCertPool() caCert, err := ioutil.ReadFile(crtPath) if err != nil { return err } if !cp.AppendCertsFromPEM(caCert) { return errors.New("Could not append PEM cert") } conf.RootCAs = cp conf.ServerName = sname conf.ClientAuth = tls.RequireAndVerifyClientCert conf.ClientCAs = cp l = tls.NewListener(l, &conf) } // at the end of this function close the server connection defer l.Close() logging.Debug("Starting listen loop") for { a, err := acceptApp(l) if err != nil { return err } else { logging.Debug("Got connection") go ListenForCommands(a) } } return nil }
// setupClientAuth sets up TLS client authentication only if // any of the TLS configs specified at least one cert file. func setupClientAuth(tlsConfigs []TLSConfig, config *tls.Config) error { whatClientAuth := tls.NoClientCert for _, cfg := range tlsConfigs { if whatClientAuth < cfg.ClientAuth { // Use the most restrictive. whatClientAuth = cfg.ClientAuth } } if whatClientAuth != tls.NoClientCert { pool := x509.NewCertPool() for _, cfg := range tlsConfigs { if len(cfg.ClientCerts) == 0 { continue } for _, caFile := range cfg.ClientCerts { caCrt, err := ioutil.ReadFile(caFile) // Anyone that gets a cert from this CA can connect if err != nil { return err } if !pool.AppendCertsFromPEM(caCrt) { return fmt.Errorf("error loading client certificate '%s': no certificates were successfully parsed", caFile) } } } config.ClientCAs = pool config.ClientAuth = whatClientAuth } return nil }
// GetServerTLSConfig returns a TLS config for using with ListenAndServeTLS // This sets up the Root and Client CAs for verification func GetServerTLSConfig(caCert, serverCert, serverKey []byte, allowInsecure bool) (*tls.Config, error) { // TLS config var tlsConfig tls.Config tlsConfig.InsecureSkipVerify = allowInsecure certPool := x509.NewCertPool() // load system certs if err := loadSystemCertificates(certPool); err != nil { return nil, err } // append custom CA certPool.AppendCertsFromPEM(caCert) tlsConfig.RootCAs = certPool tlsConfig.ClientCAs = certPool log.Debugf("tls root CAs: %d", len(tlsConfig.RootCAs.Subjects())) // require client auth tlsConfig.ClientAuth = tls.VerifyClientCertIfGiven // server cert keypair, err := tls.X509KeyPair(serverCert, serverKey) if err != nil { return &tlsConfig, err } tlsConfig.Certificates = []tls.Certificate{keypair} return &tlsConfig, nil }
// serverWithAuth builds a gRPC server, possibly with authentication if key / cert files are given. func serverWithAuth(keyFile, certFile, caCertFile string) *grpc.Server { if keyFile == "" { return grpc.NewServer(grpc.MaxMsgSize(maxMsgSize)) // No auth. } log.Debug("Loading x509 key pair from key: %s cert: %s", keyFile, certFile) cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { log.Fatalf("Failed to load x509 key pair: %s", err) } config := tls.Config{ Certificates: []tls.Certificate{cert}, ClientAuth: tls.RequestClientCert, } if caCertFile != "" { cert, err := ioutil.ReadFile(caCertFile) if err != nil { log.Fatalf("Failed to read CA cert file: %s", err) } config.ClientCAs = x509.NewCertPool() if !config.ClientCAs.AppendCertsFromPEM(cert) { log.Fatalf("Failed to find any PEM certificates in CA cert") } } return grpc.NewServer(grpc.Creds(credentials.NewTLS(&config)), grpc.MaxMsgSize(maxMsgSize)) }
// SecureListen obtains a listener that accepts // secure connections func SecureServe(addr string, certFile, keyFile, caFile string) { config := tls.Config{} // load the server cert / key cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { log.Fatalf("%s", err) } config.Certificates = []tls.Certificate{cert} // load the ca if necessary // FIXME(alainjobart) this doesn't quite work yet, have // to investigate if caFile != "" { config.ClientCAs = x509.NewCertPool() pemCerts, err := ioutil.ReadFile(caFile) if err != nil { log.Fatalf("%s", err) } if !config.ClientCAs.AppendCertsFromPEM(pemCerts) { log.Fatalf("%s", err) } config.ClientAuth = tls.RequireAndVerifyClientCert } l, err := tls.Listen("tcp", addr, &config) if err != nil { log.Fatalf("%s", err) } throttled := NewThrottledListener(l, *secureThrottle, *secureMaxBuffer) cl := proc.Published(throttled, "SecureConnections", "SecureAccepts") go http.Serve(cl, nil) }
// setupClientAuth sets up TLS client authentication only if // any of the TLS configs specified at least one cert file. func setupClientAuth(tlsConfigs []TLSConfig, config *tls.Config) error { var clientAuth bool for _, cfg := range tlsConfigs { if len(cfg.ClientCerts) > 0 { clientAuth = true break } } if clientAuth { pool := x509.NewCertPool() for _, cfg := range tlsConfigs { for _, caFile := range cfg.ClientCerts { caCrt, err := ioutil.ReadFile(caFile) // Anyone that gets a cert from Matt Holt can connect if err != nil { return err } if !pool.AppendCertsFromPEM(caCrt) { return fmt.Errorf("error loading client certificate '%s': no certificates were successfully parsed", caFile) } } } config.ClientCAs = pool config.ClientAuth = tls.RequireAndVerifyClientCert } 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 }
// Generates a tls.Config object for a server from the given files. func (info TLSInfo) ServerConfig() (*tls.Config, error) { // Both the key and cert must be present. if info.KeyFile == "" || info.CertFile == "" { return nil, fmt.Errorf("KeyFile and CertFile must both be present[key: %v, cert: %v]", info.KeyFile, info.CertFile) } var cfg tls.Config tlsCert, err := tls.LoadX509KeyPair(info.CertFile, info.KeyFile) if err != nil { return nil, err } cfg.Certificates = []tls.Certificate{tlsCert} if info.CAFile != "" { cfg.ClientAuth = tls.RequireAndVerifyClientCert cp, err := newCertPool(info.CAFile) if err != nil { return nil, err } cfg.RootCAs = cp cfg.ClientCAs = cp } else { cfg.ClientAuth = tls.NoClientCert } return &cfg, nil }
// NewTestServer wraps a Service as an httptest.Server. func NewTestServer(s Service, cert, key, caCert []byte) (*httptest.Server, error) { var tlsConfig *tls.Config if cert != nil { cert, err := tls.X509KeyPair(cert, key) if err != nil { return nil, err } tlsConfig = &tls.Config{Certificates: []tls.Certificate{cert}} } if caCert != nil { rootCAs := x509.NewCertPool() rootCAs.AppendCertsFromPEM(caCert) if tlsConfig == nil { tlsConfig = &tls.Config{} } tlsConfig.ClientCAs = rootCAs tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert } serveHTTP := func(w http.ResponseWriter, r *http.Request) { var review v1beta1.TokenReview if err := json.NewDecoder(r.Body).Decode(&review); err != nil { http.Error(w, fmt.Sprintf("failed to decode body: %v", err), http.StatusBadRequest) return } s.Review(&review) type userInfo struct { Username string `json:"username"` UID string `json:"uid"` Groups []string `json:"groups"` } type status struct { Authenticated bool `json:"authenticated"` User userInfo `json:"user"` } resp := struct { APIVersion string `json:"apiVersion"` Status status `json:"status"` }{ APIVersion: v1beta1.SchemeGroupVersion.String(), Status: status{ review.Status.Authenticated, userInfo{ Username: review.Status.User.Username, UID: review.Status.User.UID, Groups: review.Status.User.Groups, }, }, } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(resp) } server := httptest.NewUnstartedServer(http.HandlerFunc(serveHTTP)) server.TLS = tlsConfig server.StartTLS() return server, nil }
// ServerSecurePort obtains a listener that accepts secure connections. // If the provided port is zero, the listening is disabled. func ServeSecurePort(securePort int, certFile, keyFile, caCertFile string) { if securePort == 0 { log.Info("Not listening on secure port") return } config := tls.Config{} // load the server cert / key cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { log.Fatalf("SecureServe.LoadX509KeyPair(%v, %v) failed: %v", certFile, keyFile, err) } config.Certificates = []tls.Certificate{cert} // load the ca if necessary // FIXME(alainjobart) this doesn't quite work yet, have // to investigate if caCertFile != "" { config.ClientCAs = x509.NewCertPool() pemCerts, err := ioutil.ReadFile(caCertFile) if err != nil { log.Fatalf("SecureServe: cannot read ca file %v: %v", caCertFile, err) } if !config.ClientCAs.AppendCertsFromPEM(pemCerts) { log.Fatalf("SecureServe: AppendCertsFromPEM failed: %v", err) } config.ClientAuth = tls.RequireAndVerifyClientCert } l, err := tls.Listen("tcp", fmt.Sprintf(":%d", securePort), &config) if err != nil { log.Fatalf("Error listening on secure port %v: %v", securePort, err) } log.Infof("Listening on secure port %v", securePort) throttled := NewThrottledListener(l, *secureThrottle, *secureMaxBuffer) cl := proc.Published(throttled, "SecureConnections", "SecureAccepts") // rpc.HandleHTTP registers the default GOB handler at /_goRPC_ // and the debug RPC service at /debug/rpc (it displays a list // of registered services and their methods). if ServiceMap["gob-vts"] { log.Infof("Registering GOB handler and /debug/rpc URL for vts port") secureRpcServer.HandleHTTP(rpcwrap.GetRpcPath("gob", false), rpcplus.DefaultDebugPath) } if ServiceMap["gob-auth-vts"] { log.Infof("Registering GOB handler and /debug/rpcs URL for SASL vts port") authenticatedSecureRpcServer.HandleHTTP(rpcwrap.GetRpcPath("gob", true), rpcplus.DefaultDebugPath+"s") } handler := http.NewServeMux() bsonrpc.ServeCustomRPC(handler, secureRpcServer, false) bsonrpc.ServeCustomRPC(handler, authenticatedSecureRpcServer, true) httpServer := http.Server{ Handler: handler, } go httpServer.Serve(cl) }
// NewServer starts an HTTPS server the handles the redoctober JSON // API. Each of the URIs in the functions map above is setup with a // separate HandleFunc. Each HandleFunc is an instance of queueRequest // above. // // Returns a valid http.Server handling redoctober JSON requests (and // its associated listener) or an error func NewServer(process chan userRequest, addr string, certPath, keyPath, caPath string) (*http.Server, *net.Listener, error) { mux := http.NewServeMux() srv := http.Server{ Addr: addr, Handler: mux, } cert, err := tls.LoadX509KeyPair(certPath, keyPath) if err != nil { return nil, nil, fmt.Errorf("Error loading certificate (%s, %s): %s", certPath, keyPath, err) } config := tls.Config{ Certificates: []tls.Certificate{cert}, Rand: rand.Reader, ClientAuth: tls.RequestClientCert, PreferServerCipherSuites: true, SessionTicketsDisabled: true, } // If a caPath has been specified then a local CA is being used // and not the system configuration. if caPath != "" { rootPool := x509.NewCertPool() pemCert, err := ioutil.ReadFile(caPath) if err != nil { return nil, nil, fmt.Errorf("Error reading %s: %s\n", caPath, err) } derCert, pemCert := pem.Decode(pemCert) if derCert == nil { return nil, nil, fmt.Errorf("Error decoding CA certificate: %s\n", err) } cert, err := x509.ParseCertificate(derCert.Bytes) if err != nil { return nil, nil, fmt.Errorf("Error parsing CA certificate: %s\n", err) } rootPool.AddCert(cert) config.ClientCAs = rootPool } conn, err := net.Listen("tcp", addr) if err != nil { return nil, nil, fmt.Errorf("Error starting TCP listener on %s: %s\n", addr, err) } lstnr := tls.NewListener(conn, &config) for requestType := range functions { mux.HandleFunc(requestType, func(w http.ResponseWriter, r *http.Request) { queueRequest(process, requestType, w, r) }) } return &srv, &lstnr, nil }
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 }
// NewTestServer wraps a Service as an httptest.Server. func NewTestServer(s Service, cert, key, caCert []byte) (*httptest.Server, error) { var tlsConfig *tls.Config if cert != nil { cert, err := tls.X509KeyPair(cert, key) if err != nil { return nil, err } tlsConfig = &tls.Config{Certificates: []tls.Certificate{cert}} } if caCert != nil { rootCAs := x509.NewCertPool() rootCAs.AppendCertsFromPEM(caCert) if tlsConfig == nil { tlsConfig = &tls.Config{} } tlsConfig.ClientCAs = rootCAs tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert } serveHTTP := func(w http.ResponseWriter, r *http.Request) { var review v1alpha1.ImageReview if err := json.NewDecoder(r.Body).Decode(&review); err != nil { http.Error(w, fmt.Sprintf("failed to decode body: %v", err), http.StatusBadRequest) return } if s.HTTPStatusCode() < 200 || s.HTTPStatusCode() >= 300 { http.Error(w, "HTTP Error", s.HTTPStatusCode()) return } s.Review(&review) type status struct { Allowed bool `json:"allowed"` Reason string `json:"reason"` } resp := struct { APIVersion string `json:"apiVersion"` Kind string `json:"kind"` Status status `json:"status"` }{ APIVersion: v1alpha1.SchemeGroupVersion.String(), Kind: "ImageReview", Status: status{review.Status.Allowed, review.Status.Reason}, } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(resp) } server := httptest.NewUnstartedServer(http.HandlerFunc(serveHTTP)) server.TLS = tlsConfig server.StartTLS() return server, nil }
func (c Config) TLSConfig() *tls.Config { certs := []tls.Certificate{c.TLSCertificate()} tlsConfig := tls.Config{ Certificates: certs, } if c.TLSClientAuthEnabled() { tlsConfig.ClientCAs = c.ClientCAsPool() tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert } return &tlsConfig }
func tlsConfig() *tls.Config { cfg := new(tls.Config) cfg.ClientCAs = x509.NewCertPool() cfg.ClientCAs.AppendCertsFromPEM([]byte(caCert)) cert, err := tls.X509KeyPair([]byte(serverCert), []byte(serverKey)) if err != nil { panic(err) } cfg.Certificates = append(cfg.Certificates, cert) cfg.ClientAuth = tls.RequireAndVerifyClientCert return cfg }
// RegisterTLSConfig registers a tls configuration to manager // such that any changes to the keys may be reflected in // the tls client CA pool func (c *ClientKeyManager) RegisterTLSConfig(tlsConfig *tls.Config) error { c.clientLock.RLock() certPool, err := libtrust.GenerateCACertPool(c.key, c.clients) if err != nil { return fmt.Errorf("CA pool generation error: %s", err) } c.clientLock.RUnlock() tlsConfig.ClientCAs = certPool c.configLock.Lock() c.configs = append(c.configs, tlsConfig) c.configLock.Unlock() return nil }
// StartHttpsServer binds and starts an https server. func StartHttpsServer(addr string, certFile, keyFile, caFile string) { config := tls.Config{} // load the server cert / key cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { relog.Fatal("StartHttpsServer.LoadX509KeyPair failed: %v", err) } config.Certificates = []tls.Certificate{cert} // load the ca if necessary // FIXME(alainjobart) this doesn't quite work yet, have // to investigate if caFile != "" { config.ClientCAs = x509.NewCertPool() ca, err := os.Open(caFile) if err != nil { relog.Fatal("StartHttpsServer failed to open caFile %v: %v", caFile, err) } defer ca.Close() fi, err := ca.Stat() if err != nil { relog.Fatal("StartHttpsServer failed to stat caFile %v: %v", caFile, err) } pemCerts := make([]byte, fi.Size()) if _, err = ca.Read(pemCerts); err != nil { relog.Fatal("StartHttpsServer failed to read caFile %v: %v", caFile, err) } if !config.ClientCAs.AppendCertsFromPEM(pemCerts) { relog.Fatal("StartHttpsServer failed to parse caFile %v", caFile) } config.ClientAuth = tls.RequireAndVerifyClientCert } httpsListener, err := tls.Listen("tcp", addr, &config) if err != nil { relog.Fatal("StartHttpsServer failed: %v", err) } go asyncListener(httpsListener) }
func buildTLSConfig(opts *nsqd.Options) (*tls.Config, error) { var tlsConfig *tls.Config if opts.TLSCert == "" && opts.TLSKey == "" { return nil, nil } tlsClientAuthPolicy := tls.VerifyClientCertIfGiven cert, err := tls.LoadX509KeyPair(opts.TLSCert, opts.TLSKey) if err != nil { return nil, err } switch opts.TLSClientAuthPolicy { case "require": tlsClientAuthPolicy = tls.RequireAnyClientCert case "require-verify": tlsClientAuthPolicy = tls.RequireAndVerifyClientCert default: tlsClientAuthPolicy = tls.NoClientCert } tlsConfig = &tls.Config{ Certificates: []tls.Certificate{cert}, ClientAuth: tlsClientAuthPolicy, MinVersion: opts.TLSMinVersion, MaxVersion: tls.VersionTLS12, // enable TLS_FALLBACK_SCSV prior to Go 1.5: https://go-review.googlesource.com/#/c/1776/ } if opts.TLSRootCAFile != "" { tlsCertPool := x509.NewCertPool() caCertFile, err := ioutil.ReadFile(opts.TLSRootCAFile) if err != nil { return nil, err } if !tlsCertPool.AppendCertsFromPEM(caCertFile) { return nil, errors.New("failed to append certificate to pool") } tlsConfig.ClientCAs = tlsCertPool } tlsConfig.BuildNameToCertificate() return tlsConfig, nil }
func buildTLSConfig(options *nsqdOptions) *tls.Config { var tlsConfig *tls.Config if options.TLSCert == "" && options.TLSKey == "" { return nil } tlsClientAuthPolicy := tls.VerifyClientCertIfGiven cert, err := tls.LoadX509KeyPair(options.TLSCert, options.TLSKey) if err != nil { log.Fatalf("ERROR: failed to LoadX509KeyPair %s", err.Error()) } switch options.TLSClientAuthPolicy { case "require": tlsClientAuthPolicy = tls.RequireAnyClientCert case "require-verify": tlsClientAuthPolicy = tls.RequireAndVerifyClientCert default: tlsClientAuthPolicy = tls.NoClientCert } tlsConfig = &tls.Config{ Certificates: []tls.Certificate{cert}, ClientAuth: tlsClientAuthPolicy, } if options.TLSRootCAFile != "" { tlsCertPool := x509.NewCertPool() ca_cert_file, err := ioutil.ReadFile(options.TLSRootCAFile) if err != nil { log.Fatalf("ERROR: failed to read custom Certificate Authority file %s", err.Error()) } if !tlsCertPool.AppendCertsFromPEM(ca_cert_file) { log.Fatalf("ERROR: failed to append certificates from Certificate Authority file") } tlsConfig.ClientCAs = tlsCertPool } tlsConfig.BuildNameToCertificate() return tlsConfig }
func buildTLSConfig(opts *nsqdOptions) (*tls.Config, error) { var tlsConfig *tls.Config if opts.TLSCert == "" && opts.TLSKey == "" { return nil, nil } tlsClientAuthPolicy := tls.VerifyClientCertIfGiven cert, err := tls.LoadX509KeyPair(opts.TLSCert, opts.TLSKey) if err != nil { return nil, err } switch opts.TLSClientAuthPolicy { case "require": tlsClientAuthPolicy = tls.RequireAnyClientCert case "require-verify": tlsClientAuthPolicy = tls.RequireAndVerifyClientCert default: tlsClientAuthPolicy = tls.NoClientCert } tlsConfig = &tls.Config{ Certificates: []tls.Certificate{cert}, ClientAuth: tlsClientAuthPolicy, } if opts.TLSRootCAFile != "" { tlsCertPool := x509.NewCertPool() ca_cert_file, err := ioutil.ReadFile(opts.TLSRootCAFile) if err != nil { return nil, err } if !tlsCertPool.AppendCertsFromPEM(ca_cert_file) { return nil, errors.New("failed to append certificate to pool") } tlsConfig.ClientCAs = tlsCertPool } tlsConfig.BuildNameToCertificate() 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) // Setup client. clientConfig := new(tls.Config) clientConfig.InsecureSkipVerify = true clientConfig.MinVersion = tls.VersionTLS12 clientConfig.Certificates = append(clientConfig.Certificates, cert) srpc.RegisterClientTlsConfig(clientConfig) }
// GenTLSConfig loads TLS related configuration parameters. func GenTLSConfig(tc *TLSConfigOpts) (*tls.Config, error) { // Now load in cert and private key cert, err := tls.LoadX509KeyPair(tc.CertFile, tc.KeyFile) if err != nil { return nil, fmt.Errorf("error parsing X509 certificate/key pair: %v", err) } cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0]) if err != nil { return nil, fmt.Errorf("error parsing certificate: %v", err) } // Create TLSConfig // We will determine the cipher suites that we prefer. config := tls.Config{ Certificates: []tls.Certificate{cert}, PreferServerCipherSuites: true, MinVersion: tls.VersionTLS12, CipherSuites: tc.Ciphers, } // Require client certificates as needed if tc.Verify { config.ClientAuth = tls.RequireAndVerifyClientCert } // Add in CAs if applicable. if tc.CaFile != "" { rootPEM, err := ioutil.ReadFile(tc.CaFile) if err != nil || rootPEM == nil { return nil, err } pool := x509.NewCertPool() ok := pool.AppendCertsFromPEM([]byte(rootPEM)) if !ok { return nil, fmt.Errorf("failed to parse root ca certificate") } config.ClientCAs = pool } return &config, nil }
// serverSecurePort obtains a listener that accepts secure connections. // All of this is based on *SecurePort being non-zero. func serveSecurePort() { if *SecurePort == 0 { log.Info("Not listening on secure port") return } config := tls.Config{} // load the server cert / key cert, err := tls.LoadX509KeyPair(*certFile, *keyFile) if err != nil { log.Fatalf("SecureServe.LoadX509KeyPair(%v, %v) failed: %v", *certFile, *keyFile, err) } config.Certificates = []tls.Certificate{cert} // load the ca if necessary // FIXME(alainjobart) this doesn't quite work yet, have // to investigate if *caCertFile != "" { config.ClientCAs = x509.NewCertPool() pemCerts, err := ioutil.ReadFile(*caCertFile) if err != nil { log.Fatalf("SecureServe: cannot read ca file %v: %v", *caCertFile, err) } if !config.ClientCAs.AppendCertsFromPEM(pemCerts) { log.Fatalf("SecureServe: AppendCertsFromPEM failed: %v", err) } config.ClientAuth = tls.RequireAndVerifyClientCert } l, err := tls.Listen("tcp", fmt.Sprintf(":%d", *SecurePort), &config) if err != nil { log.Fatalf("Error listening on secure port %v: %v", *SecurePort, err) } log.Infof("Listening on secure port %v", *SecurePort) throttled := NewThrottledListener(l, *secureThrottle, *secureMaxBuffer) cl := proc.Published(throttled, "SecureConnections", "SecureAccepts") go http.Serve(cl, nil) }
func (p *Protocol) tlsSetup(config *tls.Config, identity *security.Identity, caCertificate *security.Certificate) error { var ( certBuf bytes.Buffer keyBuf bytes.Buffer err error ) // We need to prepare our certs & keys for the TLS config // Write out our identity certificate and the authority certificate to a single buffer identity.Certificate.WritePEM(&certBuf) caCertificate.WritePEM(&certBuf) // Write the key to the other identity.Key.WritePEM(&keyBuf) // Load the key pair cert, err := tls.X509KeyPair(certBuf.Bytes(), keyBuf.Bytes()) if err != nil { return err } ca, err := x509.ParseCertificate(cert.Certificate[1]) if err != nil { return err } // Make our authority certificate as the only item in the pool used for root CAs certPool := x509.NewCertPool() certPool.AddCert(ca) // Update the config config.Certificates = []tls.Certificate{cert} config.RootCAs = certPool config.ClientCAs = certPool 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 GetConfig(ca_f []byte, ee_f []byte, key_f []byte) (*tls.Config, error) { ca, err := x509.ParseCertificate(ca_f) if err != nil { return nil, err } pkey, err := x509.ParsePKCS1PrivateKey(key_f) if err != nil { return nil, err } ca_pool := x509.NewCertPool() ca_pool.AddCert(ca) ee_cert := tls.Certificate{ Certificate: [][]byte{ee_f}, PrivateKey: pkey, } config := new(tls.Config) config.ClientAuth = tls.RequireAndVerifyClientCert config.Certificates = []tls.Certificate{ee_cert} config.ClientCAs = ca_pool config.RootCAs = ca_pool config.Rand = rand.Reader config.BuildNameToCertificate() return config, nil }
// 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 }
// NewServer starts an HTTPS server the handles the redoctober JSON // API. Each of the URIs in the functions map above is setup with a // separate HandleFunc. Each HandleFunc is an instance of queueRequest // above. // // Returns a valid http.Server handling redoctober JSON requests (and // its associated listener) or an error func NewServer(process chan<- userRequest, staticPath, addr, certPath, keyPath, caPath string) (*http.Server, *net.Listener, error) { cert, err := tls.LoadX509KeyPair(certPath, keyPath) if err != nil { return nil, nil, fmt.Errorf("Error loading certificate (%s, %s): %s", certPath, keyPath, err) } config := tls.Config{ Certificates: []tls.Certificate{cert}, Rand: rand.Reader, PreferServerCipherSuites: true, SessionTicketsDisabled: true, MinVersion: tls.VersionTLS10, } // If a caPath has been specified then a local CA is being used // and not the system configuration. if caPath != "" { pemCert, err := ioutil.ReadFile(caPath) if err != nil { return nil, nil, fmt.Errorf("Error reading %s: %s\n", caPath, err) } derCert, _ := pem.Decode(pemCert) if derCert == nil { return nil, nil, fmt.Errorf("No PEM data was found in the CA certificate file\n") } cert, err := x509.ParseCertificate(derCert.Bytes) if err != nil { return nil, nil, fmt.Errorf("Error parsing CA certificate: %s\n", err) } rootPool := x509.NewCertPool() rootPool.AddCert(cert) config.ClientAuth = tls.RequireAndVerifyClientCert config.ClientCAs = rootPool } conn, err := net.Listen("tcp", addr) if err != nil { return nil, nil, fmt.Errorf("Error starting TCP listener on %s: %s\n", addr, err) } lstnr := tls.NewListener(conn, &config) mux := http.NewServeMux() // queue up post URIs for current := range functions { // copy this so reference does not get overwritten requestType := current mux.HandleFunc(requestType, func(w http.ResponseWriter, r *http.Request) { log.Printf("http.server: endpoint=%s remote=%s", requestType, r.RemoteAddr) queueRequest(process, requestType, w, r) }) } // queue up web frontend idxHandler := &indexHandler{staticPath} mux.HandleFunc("/index", idxHandler.handle) mux.HandleFunc("/", idxHandler.handle) srv := http.Server{ Addr: addr, Handler: mux, } return &srv, &lstnr, nil }
// NewTestServer wraps a Service as an httptest.Server. func NewTestServer(s Service, cert, key, caCert []byte) (*httptest.Server, error) { const webhookPath = "/testserver" var tlsConfig *tls.Config if cert != nil { cert, err := tls.X509KeyPair(cert, key) if err != nil { return nil, err } tlsConfig = &tls.Config{Certificates: []tls.Certificate{cert}} } if caCert != nil { rootCAs := x509.NewCertPool() rootCAs.AppendCertsFromPEM(caCert) if tlsConfig == nil { tlsConfig = &tls.Config{} } tlsConfig.ClientCAs = rootCAs tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert } serveHTTP := func(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { http.Error(w, fmt.Sprintf("unexpected method: %v", r.Method), http.StatusMethodNotAllowed) return } if r.URL.Path != webhookPath { http.Error(w, fmt.Sprintf("unexpected path: %v", r.URL.Path), http.StatusNotFound) return } var review v1beta1.TokenReview bodyData, _ := ioutil.ReadAll(r.Body) if err := json.Unmarshal(bodyData, &review); err != nil { http.Error(w, fmt.Sprintf("failed to decode body: %v", err), http.StatusBadRequest) return } // ensure we received the serialized tokenreview as expected if review.APIVersion != "authentication.k8s.io/v1beta1" { http.Error(w, fmt.Sprintf("wrong api version: %s", string(bodyData)), http.StatusBadRequest) return } // once we have a successful request, always call the review to record that we were called s.Review(&review) if s.HTTPStatusCode() < 200 || s.HTTPStatusCode() >= 300 { http.Error(w, "HTTP Error", s.HTTPStatusCode()) return } type userInfo struct { Username string `json:"username"` UID string `json:"uid"` Groups []string `json:"groups"` Extra map[string][]string `json:"extra"` } type status struct { Authenticated bool `json:"authenticated"` User userInfo `json:"user"` } var extra map[string][]string if review.Status.User.Extra != nil { extra = map[string][]string{} for k, v := range review.Status.User.Extra { extra[k] = v } } resp := struct { Kind string `json:"kind"` APIVersion string `json:"apiVersion"` Status status `json:"status"` }{ Kind: "TokenReview", APIVersion: v1beta1.SchemeGroupVersion.String(), Status: status{ review.Status.Authenticated, userInfo{ Username: review.Status.User.Username, UID: review.Status.User.UID, Groups: review.Status.User.Groups, Extra: extra, }, }, } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(resp) } server := httptest.NewUnstartedServer(http.HandlerFunc(serveHTTP)) server.TLS = tlsConfig server.StartTLS() // Adjust the path to point to our custom path serverURL, _ := url.Parse(server.URL) serverURL.Path = webhookPath server.URL = serverURL.String() return server, nil }
func ServiceRequests() { var sockConfig tls.Config // resolve the bind address bindAddressStr := GetStringOpt("bind address") var bindAddr *net.IPAddr if bindAddressStr != "" { var err error bindAddr, err = net.ResolveIPAddr("ip", bindAddressStr) if err != nil { o.Warn("Ignoring bind address. Couldn't resolve \"%s\": %s", bindAddressStr, err) } else { bindAddr = nil } } // load the x509 certificate and key, then attach it to the tls config. x509CertFilename := GetStringOpt("x509 certificate") x509PrivateKeyFilename := GetStringOpt("x509 private key") serverCert, err := tls.LoadX509KeyPair(x509CertFilename, x509PrivateKeyFilename) o.MightFail(err, "Couldn't load certificates") sockConfig.Certificates = append(sockConfig.Certificates, serverCert) // load the CA certs CACertPool = x509.NewCertPool() caCertNames := GetCACertList() if caCertNames != nil { for _, filename := range caCertNames { fh, err := os.Open(filename) if err != nil { o.Warn("Whilst parsing CA certs, couldn't open %s: %s", filename, err) continue } defer fh.Close() fi, err := fh.Stat() o.MightFail(err, "Couldn't stat CA certificate file: %s", filename) data := make([]byte, fi.Size()) fh.Read(data) CACertPool.AppendCertsFromPEM(data) } } sockConfig.ClientCAs = CACertPool // determine the server hostname. servername := GetStringOpt("server name") if servername != "" { o.Info("Using %s as the server name", servername) sockConfig.ServerName = servername } else { if bindAddr != nil { o.Warn("Probing for FQDN for bind address as none was provided") hostnames, err := net.LookupAddr(bindAddr.String()) o.MightFail(err, "Failed to get full hostname for bind address") sockConfig.ServerName = hostnames[0] } else { o.Warn("Probing for FQDN as no server name was provided") sockConfig.ServerName = o.ProbeHostname() } } // ask the client to authenticate sockConfig.ClientAuth = tls.RequireAndVerifyClientCert if *DontVerifyPeer { sockConfig.ClientAuth = tls.RequestClientCert } /* convert the bindAddress to a string suitable for the Listen call */ var laddr string if bindAddr == nil { laddr = fmt.Sprintf(":%d", o.DefaultMasterPort) } else { laddr = fmt.Sprintf("%s:%d", bindAddr.String(), o.DefaultMasterPort) } o.Info("Binding to %s...", laddr) listener, err := tls.Listen("tcp", laddr, &sockConfig) o.MightFail(err, "Couldn't bind TLS listener") for { o.Info("Waiting for connection...") c, err := listener.Accept() o.MightFail(err, "Couldn't accept TLS connection") o.Info("Connection received from %s", c.RemoteAddr().String()) HandleConnection(c) } }