aboutsummaryrefslogtreecommitdiff
path: root/server/server.go
diff options
context:
space:
mode:
Diffstat (limited to 'server/server.go')
-rw-r--r--server/server.go117
1 files changed, 117 insertions, 0 deletions
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())
+}