From 1284ea502b589f2aa518d7bcaf260abc3495da0c Mon Sep 17 00:00:00 2001 From: ale <ale@incal.net> Date: Sun, 15 Dec 2019 21:53:35 +0000 Subject: [PATCH] Add script to run a local server for UI testing purposes --- server/scripts/localserver.go | 159 ++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 server/scripts/localserver.go diff --git a/server/scripts/localserver.go b/server/scripts/localserver.go new file mode 100644 index 0000000..651ff05 --- /dev/null +++ b/server/scripts/localserver.go @@ -0,0 +1,159 @@ +// +build ignore + +package main + +import ( + "context" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "flag" + "io/ioutil" + "log" + "math/big" + "net/http" + "os" + "path/filepath" + "strings" + "time" + + "github.com/gorilla/securecookie" + "golang.org/x/crypto/ed25519" + + "git.autistici.org/id/auth" + "git.autistici.org/id/go-sso/server" +) + +var ( + addr = flag.String("addr", ":4872", "address to listen on") +) + +type fakeAuthClient struct{} + +func (c *fakeAuthClient) Authenticate(_ context.Context, req *auth.Request) (*auth.Response, error) { + log.Printf("authenticate(%+v)", req) + + p := string(req.Password) + info := &auth.UserInfo{Shard: "shard1"} + switch { + case req.Username == "testuser" && p == "password": + return &auth.Response{Status: auth.StatusOK, UserInfo: info}, nil + case req.Username == "test2fa" && p == "password" && req.OTP == "123456": + return &auth.Response{Status: auth.StatusOK, UserInfo: info}, nil + case req.Username == "test2fa" && p == "password": + return &auth.Response{ + Status: auth.StatusInsufficientCredentials, + TFAMethods: []auth.TFAMethod{auth.TFAMethodOTP}, + }, nil + } + + return &auth.Response{Status: auth.StatusError}, nil +} + +func generateSSLCert(tmpdir string) (string, string) { + priv, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + panic(err) + } + + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + panic(err) + } + + now := time.Now() + notBefore := now.Add(-1 * time.Hour) + notAfter := now.Add(1000 * time.Hour) + template := x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + Organization: []string{"Acme Co"}, + }, + NotBefore: notBefore, + NotAfter: notAfter, + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + DNSNames: []string{"localhost"}, + } + + derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) + if err != nil { + panic(err) + } + + certPath := filepath.Join(tmpdir, "cert.pem") + certOut, err := os.Create(certPath) + if err != nil { + panic(err) + } + if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil { + panic(err) + } + certOut.Close() + + keyPath := filepath.Join(tmpdir, "privkey.pem") + keyOut, err := os.Create(keyPath) + if err != nil { + panic(err) + } + privBytes, err := x509.MarshalPKCS8PrivateKey(priv) + if err != nil { + panic(err) + } + if err := pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil { + panic(err) + } + + keyOut.Close() + + return certPath, keyPath +} + +func main() { + flag.Parse() + + tmpdir, err := ioutil.TempDir("", "") + if err != nil { + log.Fatal(err) + } + defer os.RemoveAll(tmpdir) + + pub, priv, err := ed25519.GenerateKey(nil) + if err != nil { + log.Fatal(err) + } + secretPath := filepath.Join(tmpdir, "secret") + publicPath := filepath.Join(tmpdir, "public") + ioutil.WriteFile(secretPath, priv, 0600) // nolint + ioutil.WriteFile(publicPath, pub, 0600) // nolint + + config := &server.Config{ + SecretKeyFile: secretPath, + PublicKeyFile: publicPath, + Domain: "example.com", + AuthService: "test", + AllowedServices: []string{"service.example.com/"}, + CSRFSecret: string(securecookie.GenerateRandomKey(32)), + } + if err := config.Compile(); err != nil { + log.Fatalf("config error: %v", err) + } + + svc, err := server.NewLoginService(config) + if err != nil { + log.Fatalf("server.NewLoginService(): %v", err) + } + + srv, err := server.New(svc, &fakeAuthClient{}, config) + if err != nil { + log.Fatalf("server.New(): %v", err) + } + + certPath, keyPath := generateSSLCert(tmpdir) + log.Printf("serving on https://localhost:%s/", strings.Split(*addr, ":")[1]) + http.ListenAndServeTLS(*addr, certPath, keyPath, srv.Handler()) +} -- GitLab