From fb830dc3531904be0a58e2c4dd4638b390bbdab2 Mon Sep 17 00:00:00 2001 From: Niall Sheridan Date: Sun, 19 Feb 2017 23:28:33 +0000 Subject: Split the servers out of main --- server/server.go | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 server/server.go (limited to 'server/server.go') diff --git a/server/server.go b/server/server.go new file mode 100644 index 0000000..676a61b --- /dev/null +++ b/server/server.go @@ -0,0 +1,117 @@ +package server + +import ( + "crypto/tls" + "fmt" + "log" + "net" + + "github.com/pkg/errors" + "github.com/soheilhy/cmux" + + "go4.org/wkfs" + "golang.org/x/crypto/acme/autocert" + + wkfscache "github.com/nsheridan/autocert-wkfs-cache" + "github.com/nsheridan/cashier/server/auth" + "github.com/nsheridan/cashier/server/auth/github" + "github.com/nsheridan/cashier/server/auth/gitlab" + "github.com/nsheridan/cashier/server/auth/google" + "github.com/nsheridan/cashier/server/config" + "github.com/nsheridan/cashier/server/metrics" + "github.com/nsheridan/cashier/server/signer" + "github.com/nsheridan/cashier/server/store" + "github.com/sid77/drop" +) + +var ( + authprovider auth.Provider + certstore store.CertStorer + keysigner *signer.KeySigner +) + +func loadCerts(certFile, keyFile string) (tls.Certificate, error) { + key, err := wkfs.ReadFile(keyFile) + if err != nil { + return tls.Certificate{}, errors.Wrap(err, "error reading TLS private key") + } + cert, err := wkfs.ReadFile(certFile) + if err != nil { + return tls.Certificate{}, errors.Wrap(err, "error reading TLS certificate") + } + return tls.X509KeyPair(cert, key) +} + +// Run the HTTP and RPC servers. +func Run(conf *config.Config) { + var err error + keysigner, err = signer.New(conf.SSH) + if err != nil { + log.Fatal(err) + } + + laddr := fmt.Sprintf("%s:%d", conf.Server.Addr, conf.Server.Port) + l, err := net.Listen("tcp", laddr) + if err != nil { + log.Fatal(errors.Wrapf(err, "unable to listen on %s:%d", conf.Server.Addr, conf.Server.Port)) + } + + tlsConfig := &tls.Config{} + if conf.Server.UseTLS { + if conf.Server.LetsEncryptServername != "" { + m := autocert.Manager{ + Prompt: autocert.AcceptTOS, + Cache: wkfscache.Cache(conf.Server.LetsEncryptCache), + HostPolicy: autocert.HostWhitelist(conf.Server.LetsEncryptServername), + } + tlsConfig.GetCertificate = m.GetCertificate + } else { + if conf.Server.TLSCert == "" || conf.Server.TLSKey == "" { + log.Fatal("TLS cert or key not specified in config") + } + tlsConfig.Certificates = make([]tls.Certificate, 1) + tlsConfig.Certificates[0], err = loadCerts(conf.Server.TLSCert, conf.Server.TLSKey) + if err != nil { + log.Fatal(errors.Wrap(err, "unable to create TLS listener")) + } + } + l = tls.NewListener(l, tlsConfig) + } + + if conf.Server.User != "" { + log.Print("Dropping privileges...") + if err := drop.DropPrivileges(conf.Server.User); err != nil { + log.Fatal(errors.Wrap(err, "unable to drop privileges")) + } + } + + // Unprivileged section + metrics.Register() + + switch conf.Auth.Provider { + case "google": + authprovider, err = google.New(conf.Auth) + case "github": + authprovider, err = github.New(conf.Auth) + case "gitlab": + authprovider, err = gitlab.New(conf.Auth) + default: + log.Fatalf("Unknown provider %s\n", conf.Auth.Provider) + } + if err != nil { + log.Fatal(errors.Wrapf(err, "unable to use provider '%s'", conf.Auth.Provider)) + } + + certstore, err = store.New(conf.Server.Database) + if err != nil { + log.Fatal(err) + } + + log.Printf("Starting server on %s", laddr) + cm := cmux.New(l) + httpl := cm.Match(cmux.HTTP1Fast()) + grpcl := cm.Match(cmux.HTTP2HeaderField("content-type", "application/grpc")) + go runHTTPServer(conf.Server, httpl) + go runGRPCServer(grpcl) + log.Fatal(cm.Serve()) +} -- cgit v1.2.3