diff --git a/.pending/breaking/gaiacli/Remove-REST-server-s b/.pending/breaking/gaiacli/Remove-REST-server-s new file mode 100644 index 000000000000..e30851113355 --- /dev/null +++ b/.pending/breaking/gaiacli/Remove-REST-server-s @@ -0,0 +1 @@ +#3938 Remove REST server's SSL support altogether. diff --git a/client/flags.go b/client/flags.go index 24a4206ca9b0..3847e5ed6c27 100644 --- a/client/flags.go +++ b/client/flags.go @@ -40,10 +40,6 @@ const ( FlagListenAddr = "laddr" FlagCORS = "cors" FlagMaxOpenConnections = "max-open" - FlagTLS = "tls" - FlagSSLHosts = "ssl-hosts" - FlagSSLCertFile = "ssl-certfile" - FlagSSLKeyFile = "ssl-keyfile" FlagOutputDocument = "output-document" // inspired by wget -O FlagSkipConfirmation = "yes" ) @@ -110,10 +106,6 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { func RegisterRestServerFlags(cmd *cobra.Command) *cobra.Command { cmd = GetCommands(cmd)[0] cmd.Flags().String(FlagListenAddr, "tcp://localhost:1317", "The address for the server to listen on") - cmd.Flags().Bool(FlagTLS, false, "Enable SSL/TLS layer") - cmd.Flags().String(FlagSSLHosts, "", "Comma-separated hostnames and IPs to generate a certificate for") - cmd.Flags().String(FlagSSLCertFile, "", "Path to a SSL certificate file. If not supplied, a self-signed certificate will be generated.") - cmd.Flags().String(FlagSSLKeyFile, "", "Path to a key file; ignored if a certificate file is not supplied.") cmd.Flags().String(FlagCORS, "", "Set the domains that can make CORS requests (* for all)") cmd.Flags().Int(FlagMaxOpenConnections, 1000, "The number of maximum open connections") diff --git a/client/lcd/certificates.go b/client/lcd/certificates.go deleted file mode 100644 index 3260ebfc2dff..000000000000 --- a/client/lcd/certificates.go +++ /dev/null @@ -1,177 +0,0 @@ -package lcd - -import ( - "bytes" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/sha256" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "errors" - "fmt" - "io/ioutil" - "math/big" - "net" - "os" - "strings" - "time" -) - -// default: 30 days -const defaultValidFor = 30 * 24 * time.Hour - -func generateSelfSignedCert(host string) (certBytes []byte, priv *ecdsa.PrivateKey, err error) { - priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - notBefore := time.Now() - notAfter := notBefore.Add(defaultValidFor) - serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) - serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) - if err != nil { - err = fmt.Errorf("failed to generate serial number: %s", err) - return - } - - template := x509.Certificate{ - SerialNumber: serialNumber, - Subject: pkix.Name{ - Organization: []string{"Gaia Lite"}, - }, - DNSNames: []string{"localhost"}, - NotBefore: notBefore, - NotAfter: notAfter, - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - BasicConstraintsValid: true, - IsCA: true, - } - hosts := strings.Split(host, ",") - for _, h := range hosts { - if ip := net.ParseIP(h); ip != nil { - template.IPAddresses = append(template.IPAddresses, ip) - } else { - template.DNSNames = append(template.DNSNames, h) - } - } - - certBytes, err = x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) - if err != nil { - err = fmt.Errorf("couldn't create certificate: %s", err) - return - } - return -} - -func writeCertAndPrivKey(certBytes []byte, priv *ecdsa.PrivateKey) (certFile string, keyFile string, err error) { - if priv == nil { - err = errors.New("private key is nil") - return - } - certFile, err = writeCertificateFile(certBytes) - if err != nil { - return - } - keyFile, err = writeKeyFile(priv) - return -} - -func writeCertificateFile(certBytes []byte) (filename string, err error) { - f, err := ioutil.TempFile("", "cert_") - if err != nil { - return - } - defer f.Close() - filename = f.Name() - if err := pem.Encode(f, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes}); err != nil { - return filename, fmt.Errorf("failed to write data to %s: %s", filename, err) - } - return -} - -func writeKeyFile(priv *ecdsa.PrivateKey) (filename string, err error) { - f, err := ioutil.TempFile("", "key_") - if err != nil { - return - } - defer f.Close() - filename = f.Name() - block, err := pemBlockForKey(priv) - if err != nil { - return - } - if err := pem.Encode(f, block); err != nil { - return filename, fmt.Errorf("failed to write data to %s: %s", filename, err) - } - return -} - -func pemBlockForKey(priv *ecdsa.PrivateKey) (*pem.Block, error) { - b, err := x509.MarshalECPrivateKey(priv) - if err != nil { - return nil, fmt.Errorf("unable to marshal ECDSA private key: %v", err) - } - return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}, nil - -} - -func genCertKeyFilesAndReturnFingerprint(sslHosts string) (certFile, keyFile string, fingerprint string, err error) { - certBytes, priv, err := generateSelfSignedCert(sslHosts) - if err != nil { - return - } - certFile, keyFile, err = writeCertAndPrivKey(certBytes, priv) - cleanupFunc := func() { - os.Remove(certFile) - os.Remove(keyFile) - } - // Either of the files could have been written already, - // thus clean up regardless of the error. - if err != nil { - defer cleanupFunc() - return - } - fingerprint, err = fingerprintForCertificate(certBytes) - if err != nil { - defer cleanupFunc() - return - } - return -} - -func fingerprintForCertificate(certBytes []byte) (string, error) { - cert, err := x509.ParseCertificate(certBytes) - if err != nil { - return "", err - } - h := sha256.New() - if _, err := h.Write(cert.Raw); err != nil { - return "", err - } - fingerprintBytes := h.Sum(nil) - var buf bytes.Buffer - for i, b := range fingerprintBytes { - if i > 0 { - fmt.Fprintf(&buf, ":") - } - fmt.Fprintf(&buf, "%02X", b) - } - return fmt.Sprintf("SHA256 Fingerprint=%s", buf.String()), nil -} - -func fingerprintFromFile(certFile string) (string, error) { - f, err := os.Open(certFile) - if err != nil { - return "", err - } - defer f.Close() - data, err := ioutil.ReadAll(f) - if err != nil { - return "", err - } - block, _ := pem.Decode(data) - if block == nil { - return "", fmt.Errorf("couldn't find PEM data in %s", certFile) - } - return fingerprintForCertificate(block.Bytes) -} diff --git a/client/lcd/certificates_test.go b/client/lcd/certificates_test.go deleted file mode 100644 index 3f48c194c252..000000000000 --- a/client/lcd/certificates_test.go +++ /dev/null @@ -1,93 +0,0 @@ -package lcd - -import ( - "crypto/ecdsa" - "crypto/x509" - "io/ioutil" - "os" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestGenerateSelfSignedCert(t *testing.T) { - host := "127.0.0.1,localhost,::1" - certBytes, _, err := generateSelfSignedCert(host) - require.Nil(t, err) - cert, err := x509.ParseCertificate(certBytes) - require.Nil(t, err) - require.Equal(t, 2, len(cert.IPAddresses)) - require.Equal(t, 2, len(cert.DNSNames)) - require.True(t, cert.IsCA) -} - -func TestWriteCertAndPrivKey(t *testing.T) { - expectedPerm := "-rw-------" - derBytes, priv, err := generateSelfSignedCert("localhost") - require.Nil(t, err) - type args struct { - certBytes []byte - priv *ecdsa.PrivateKey - } - tests := []struct { - name string - args args - wantErr bool - }{ - {"valid certificate", args{derBytes, priv}, false}, - {"garbage", args{[]byte("some garbage"), nil}, true}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - gotCertFile, gotKeyFile, err := writeCertAndPrivKey(tt.args.certBytes, tt.args.priv) - defer os.Remove(gotCertFile) - defer os.Remove(gotKeyFile) - if tt.wantErr { - require.NotNil(t, err) - return - } - require.Nil(t, err) - info, err := os.Stat(gotCertFile) - require.Nil(t, err) - require.True(t, info.Mode().IsRegular()) - require.Equal(t, expectedPerm, info.Mode().String()) - info, err = os.Stat(gotKeyFile) - require.Nil(t, err) - require.True(t, info.Mode().IsRegular()) - require.Equal(t, expectedPerm, info.Mode().String()) - }) - } -} - -func TestFingerprintFromFile(t *testing.T) { - cert := `-----BEGIN CERTIFICATE----- -MIIBbDCCARGgAwIBAgIQSuFKYv/22v+cxtVgMUrQADAKBggqhkjOPQQDAjASMRAw -DgYDVQQKEwdBY21lIENvMB4XDTE4MDkyMDIzNDQyNloXDTE5MDkyMDIzNDQyNlow -EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDIo -ujAesRczcPVAWiLhpeV1B7hS/RI2LJaGj3QjyJ8hiUthJTPIamr8m7LuS/U5fS0o -hY297YeTIGo9YkxClICjSTBHMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr -BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MA8GA1UdEQQIMAaHBH8AAAEwCgYIKoZI -zj0EAwIDSQAwRgIhAKnwbhX9FrGG1otCVLwhClQ3RaLxnNpCgIGTqSimb34cAiEA -stMN+IqMCKWlZyGqxGIiyksMLMEU3lRqKNQn2EoAZJY= ------END CERTIFICATE-----` - wantFingerprint := `SHA256 Fingerprint=0B:ED:9A:AA:A2:D1:7E:B2:53:56:F6:FC:C0:E6:1A:69:70:21:A2:B0:90:FC:AF:BB:EF:AE:2C:78:52:AB:68:40` - certFile, err := ioutil.TempFile("", "test_cert_") - require.Nil(t, err) - _, err = certFile.Write([]byte(cert)) - require.Nil(t, err) - err = certFile.Close() - require.Nil(t, err) - defer os.Remove(certFile.Name()) - fingerprint, err := fingerprintFromFile(certFile.Name()) - require.Nil(t, err) - require.Equal(t, wantFingerprint, fingerprint) - - // test failure - emptyFile, err := ioutil.TempFile("", "test_cert_") - require.Nil(t, err) - err = emptyFile.Close() - require.Nil(t, err) - defer os.Remove(emptyFile.Name()) - _, err = fingerprintFromFile(emptyFile.Name()) - require.NotNil(t, err) -} diff --git a/client/lcd/root.go b/client/lcd/root.go index 0f6fb120aadd..e875c926426e 100644 --- a/client/lcd/root.go +++ b/client/lcd/root.go @@ -52,9 +52,7 @@ func NewRestServer(cdc *codec.Codec) *RestServer { } // Start starts the rest server -func (rs *RestServer) Start(listenAddr string, sslHosts string, - certFile string, keyFile string, maxOpen int, secure bool) (err error) { - +func (rs *RestServer) Start(listenAddr string, maxOpen int) (err error) { server.TrapSignal(func() { err := rs.listener.Close() rs.log.Error("error closing listener", "err", err) @@ -70,43 +68,7 @@ func (rs *RestServer) Start(listenAddr string, sslHosts string, rs.log.Info(fmt.Sprintf("Starting Gaia Lite REST service (chain-id: %q)...", viper.GetString(client.FlagChainID))) - // launch rest-server in insecure mode - if !secure { - return rpcserver.StartHTTPServer(rs.listener, rs.Mux, rs.log) - } - - // handle certificates - if certFile != "" { - // validateCertKeyFiles() is needed to work around tendermint/tendermint#2460 - if err := validateCertKeyFiles(certFile, keyFile); err != nil { - return err - } - - // cert/key pair is provided, read the fingerprint - rs.fingerprint, err = fingerprintFromFile(certFile) - if err != nil { - return err - } - } else { - // if certificate is not supplied, generate a self-signed one - certFile, keyFile, rs.fingerprint, err = genCertKeyFilesAndReturnFingerprint(sslHosts) - if err != nil { - return err - } - - defer func() { - os.Remove(certFile) - os.Remove(keyFile) - }() - } - - rs.log.Info(rs.fingerprint) - return rpcserver.StartHTTPAndTLSServer( - rs.listener, - rs.Mux, - certFile, keyFile, - rs.log, - ) + return rpcserver.StartHTTPServer(rs.listener, rs.Mux, rs.log) } // ServeCommand will start a Gaia Lite REST service as a blocking process. It @@ -122,13 +84,8 @@ func ServeCommand(cdc *codec.Codec, registerRoutesFn func(*RestServer)) *cobra.C registerRoutesFn(rs) // Start the rest server and return error if one exists - err = rs.Start( - viper.GetString(client.FlagListenAddr), - viper.GetString(client.FlagSSLHosts), - viper.GetString(client.FlagSSLCertFile), - viper.GetString(client.FlagSSLKeyFile), - viper.GetInt(client.FlagMaxOpenConnections), - viper.GetBool(client.FlagTLS)) + err = rs.Start(viper.GetString(client.FlagListenAddr), + viper.GetInt(client.FlagMaxOpenConnections)) return err }, diff --git a/docs/clients/lite/getting_started.md b/docs/clients/lite/getting_started.md index 47ee16f9e0e9..7f5099402fad 100644 --- a/docs/clients/lite/getting_started.md +++ b/docs/clients/lite/getting_started.md @@ -19,18 +19,4 @@ gaiacli rest-server --chain-id=test \ --trust-node=false ``` -The server listens on HTTP by default. You can enable the secure layer by adding the `--tls` flag. -By default a self-signed certificate will be generated and its fingerprint printed out. You can -configure the server to use a SSL certificate by passing the certificate and key files via the -`--ssl-certfile` and `--ssl-keyfile` flags: - -```bash -gaiacli rest-server --chain-id=test \ - --laddr=tcp://localhost:1317 \ - --node tcp://localhost:26657 \ - --trust-node=false \ - --tls \ - --ssl-certfile=mycert.pem --ssl-keyfile=mykey.key -``` - For more information about the Gaia-Lite RPC, see the [swagger documentation](https://cosmos.network/rpc/) diff --git a/docs/translations/kr/clients/lite/getting_started.md b/docs/translations/kr/clients/lite/getting_started.md index bc5ba1bf3ba4..44ca6a628b9c 100755 --- a/docs/translations/kr/clients/lite/getting_started.md +++ b/docs/translations/kr/clients/lite/getting_started.md @@ -20,14 +20,4 @@ gaiacli rest-server --chain-id=test \ --trust-node=false ``` -서버는 기본적으로 HTTP를 확인합니다. 보안 계층을 사용하시려면 `--tls` 플래그를 추가해주세요. 기본적으로 자체 서명이 된 인증서가 생성되며, fingerprint가 프린트됩니다. 서버에 특정 SSL 인증서를 사용하기 ㅜ이해서는 `--ssl-certfile`과 `--ssl-keyfile` 플래그를 지정해주세요: - -```bash -gaiacli rest-server --chain-id=test \ - --laddr=tcp://localhost:1317 \ - --node tcp://localhost:26657 \ - --trust-node=false \ - --ssl-certfile=mycert.pem --ssl-keyfile=mykey.key -``` - Gaia-Lite RPC에 대한 추가적인 정보를 원하시면 [Swagger 문서](https://cosmos.network/rpc/)를 확인하세요.