Browse Source

Added .gitignore, provided command line defaults, made errors more obvious, told users to check the log file after it is initialized when a fatal error occurs, require users to pass -very-insecure=true when not using TLS certificates

service_pr
zebambam 5 years ago
parent
commit
f1ac9c1337
  1. 6
      .gitignore
  2. 28
      README.md
  3. 67
      cmd/server/main.go

6
.gitignore

@ -0,0 +1,6 @@
*.conf
*.config
*.log
*.sqlite
*.pem
*.key

28
README.md

@ -95,7 +95,9 @@ To see the other command line options, run `go run cmd/server/main.go --help`.
**What should I watch out for?**
Not much! This is a very simple piece of software. Make sure you point it at the same storage as the ingester. See the "Production" section for some caveats.
x509 Certificates! This software relies on the confidentiality and integrity of a modern TLS connection between incoming clients and the front-end. Without an x509 certificate that incoming clients accurately authenticate, the security properties of this software are lost.
Otherwise, not much! This is a very simple piece of software. Make sure you point it at the same storage as the ingester. See the "Production" section for some caveats.
Support for users sending transactions will require the ability to make JSON-RPC calls to a zcashd instance. By default the frontend tries to pull RPC credentials from your zcashd.conf file, but you can specify other credentials via command line flag. In the future, it should be possible to do this with environment variables [(#2)](https://github.com/zcash-hackworks/lightwalletd/issues/2).
@ -117,6 +119,30 @@ sqlite is extremely reliable for what it is, but it isn't good at high concurren
⚠️ This is informational documentation about a piece of alpha software. It has not yet undergone audits or been subject to rigorous testing. It lacks some affordances necessary for production-level reliability. We do not recommend using it to handle customer funds at this time (March 2019).
**x509 Certificates**
You will need to supply an x509 certificate that connecting clients will have good reason to trust (hint: do not use a self-signed one, our SDK will reject those unless you distribute them to the client out-of-band). We suggest that you be sure to buy a reputable one from a supplier that uses a modern hashing algorithm (NOT md5 or sha1) and that uses Certificate Transparency (OID 1.3.6.1.4.1.11129.2.4.2 will be present in the certificate).
To check a given certificate's (cert.pem) hashing algorithm:
```
openssl x509 -text -in certificate.crt | grep "Signature Algorithm"
```
To check if a given certificate (cert.pem) contains a Certificate Transparency OID:
```
echo "1.3.6.1.4.1.11129.2.4.2 certTransparency Certificate Transparency" > oid.txt
openssl asn1parse -in cert.pem -oid ./oid.txt | grep 'Certificate Transparency'
```
To use Let's Encrypt to generate a free certificate for your frontend, one method is to:
1) Install certbot
2) Open port 80 to your host
3) Point some forward dns to that host (some.forward.dns.com)
4) Run
```
certbot certonly --standalone --preferred-challenges http -d some.forward.dns.com
```
5) Pass the resulting certificate and key to frontend using the -tls-cert and -tls-key options.
**Dependencies**
The first-order dependencies of this code are:

67
cmd/server/main.go

@ -5,7 +5,8 @@ import (
"flag"
"net"
"os"
"os/signal"
"fmt"
"os/signal"
"syscall"
"time"
@ -29,9 +30,15 @@ func init() {
DisableLevelTruncation: true,
})
onexit := func () {
fmt.Printf("Lightwalletd died with a Fatal error. Check logfile for details.\n")
}
log = logger.WithFields(logrus.Fields{
"app": "frontend-grpc",
})
logrus.RegisterExitHandler(onexit)
}
// TODO stream logging
@ -75,31 +82,55 @@ func loggerFromContext(ctx context.Context) *logrus.Entry {
}
type Options struct {
bindAddr string `json:"bind_address,omitempty"`
dbPath string `json:"db_path"`
tlsCertPath string `json:"tls_cert_path,omitempty"`
tlsKeyPath string `json:"tls_cert_key,omitempty"`
logLevel uint64 `json:"log_level,omitempty"`
logPath string `json:"log_file,omitempty"`
zcashConfPath string `json:"zcash_conf,omitempty"`
bindAddr string `json:"bind_address,omitempty"`
dbPath string `json:"db_path"`
tlsCertPath string `json:"tls_cert_path,omitempty"`
tlsKeyPath string `json:"tls_cert_key,omitempty"`
logLevel uint64 `json:"log_level,omitempty"`
logPath string `json:"log_file,omitempty"`
zcashConfPath string `json:"zcash_conf,omitempty"`
veryInsecure bool `json:"very_insecure,omitempty"`
}
func fileExists(filename string) bool {
info, err := os.Stat(filename)
if os.IsNotExist(err) {
return false
}
return !info.IsDir()
}
func main() {
opts := &Options{}
flag.StringVar(&opts.bindAddr, "bind-addr", "127.0.0.1:9067", "the address to listen on")
flag.StringVar(&opts.dbPath, "db-path", "", "the path to a sqlite database file")
flag.StringVar(&opts.tlsCertPath, "tls-cert", "", "the path to a TLS certificate (optional)")
flag.StringVar(&opts.tlsKeyPath, "tls-key", "", "the path to a TLS key file (optional)")
flag.StringVar(&opts.dbPath, "db-path", "./database.sqlite", "the path to a sqlite database file")
flag.StringVar(&opts.tlsCertPath, "tls-cert", "./cert.pem", "the path to a TLS certificate")
flag.StringVar(&opts.tlsKeyPath, "tls-key", "./cert.key", "the path to a TLS key file")
flag.Uint64Var(&opts.logLevel, "log-level", uint64(logrus.InfoLevel), "log level (logrus 1-7)")
flag.StringVar(&opts.logPath, "log-file", "", "log file to write to")
flag.StringVar(&opts.zcashConfPath, "conf-file", "", "conf file to pull RPC creds from")
flag.StringVar(&opts.logPath, "log-file", "./server.log", "log file to write to")
flag.StringVar(&opts.zcashConfPath, "conf-file", "./zcash.conf", "conf file to pull RPC creds from")
flag.BoolVar(&opts.veryInsecure, "very-insecure", false, "run without the required TLS certificate, only for debugging, DO NOT use in production")
// TODO prod metrics
// TODO support config from file and env vars
flag.Parse()
if opts.dbPath == "" || opts.zcashConfPath == "" {
flag.Usage()
os.Exit(1)
filesThatShouldExist := []string {
opts.dbPath,
opts.tlsCertPath,
opts.tlsKeyPath,
opts.logPath,
opts.zcashConfPath,
}
for _, filename := range filesThatShouldExist {
if (opts.veryInsecure && (filename == opts.tlsCertPath || filename == opts.tlsKeyPath)) {
continue
}
if !fileExists(filename) {
os.Stderr.WriteString(fmt.Sprintf("\n ** File does not exist: %s\n\n", filename))
flag.Usage()
os.Exit(1)
}
}
if opts.logPath != "" {
@ -132,7 +163,9 @@ func main() {
}
server = grpc.NewServer(grpc.Creds(transportCreds), LoggingInterceptor())
} else {
server = grpc.NewServer(LoggingInterceptor())
if (opts.veryInsecure) {
server = grpc.NewServer(LoggingInterceptor())
}
}
// Enable reflection for debugging

Loading…
Cancel
Save