|
|
@ -3,12 +3,10 @@ package main
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
import (
|
|
|
|
"crypto/tls"
|
|
|
|
"crypto/tls"
|
|
|
|
"crypto/x509"
|
|
|
|
|
|
|
|
"encoding/json"
|
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
|
|
|
|
"net/http"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"net/url"
|
|
|
|
"os"
|
|
|
|
"os"
|
|
|
@ -22,6 +20,7 @@ import (
|
|
|
|
"github.com/rqlite/rqlite/cmd"
|
|
|
|
"github.com/rqlite/rqlite/cmd"
|
|
|
|
"github.com/rqlite/rqlite/cmd/rqlite/history"
|
|
|
|
"github.com/rqlite/rqlite/cmd/rqlite/history"
|
|
|
|
httpcl "github.com/rqlite/rqlite/cmd/rqlite/http"
|
|
|
|
httpcl "github.com/rqlite/rqlite/cmd/rqlite/http"
|
|
|
|
|
|
|
|
"github.com/rqlite/rqlite/rtls"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
const maxRedirect = 21
|
|
|
|
const maxRedirect = 21
|
|
|
@ -42,6 +41,8 @@ type argT struct {
|
|
|
|
Prefix string `cli:"P,prefix" usage:"rqlited HTTP URL prefix" dft:"/"`
|
|
|
|
Prefix string `cli:"P,prefix" usage:"rqlited HTTP URL prefix" dft:"/"`
|
|
|
|
Insecure bool `cli:"i,insecure" usage:"do not verify rqlited HTTPS certificate" dft:"false"`
|
|
|
|
Insecure bool `cli:"i,insecure" usage:"do not verify rqlited HTTPS certificate" dft:"false"`
|
|
|
|
CACert string `cli:"c,ca-cert" usage:"path to trusted X.509 root CA certificate"`
|
|
|
|
CACert string `cli:"c,ca-cert" usage:"path to trusted X.509 root CA certificate"`
|
|
|
|
|
|
|
|
ClientCert string `cli:"d,client-cert" usage:"path to client X.509 certificate for mTLS"`
|
|
|
|
|
|
|
|
ClientKey string `cli:"k,client-key" usage:"path to client X.509 key for mTLS"`
|
|
|
|
Credentials string `cli:"u,user" usage:"set basic auth credentials in form username:password"`
|
|
|
|
Credentials string `cli:"u,user" usage:"set basic auth credentials in form username:password"`
|
|
|
|
Version bool `cli:"v,version" usage:"display CLI version"`
|
|
|
|
Version bool `cli:"v,version" usage:"display CLI version"`
|
|
|
|
HTTPTimeout clix.Duration `cli:"t,http-timeout" usage:"set timeout on HTTP requests" dft:"30s"`
|
|
|
|
HTTPTimeout clix.Duration `cli:"t,http-timeout" usage:"set timeout on HTTP requests" dft:"30s"`
|
|
|
@ -365,7 +366,7 @@ func getNodes(client *http.Client, argv *argT) (Nodes, error) {
|
|
|
|
return nil, err
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
response, err := ioutil.ReadAll(resp.Body)
|
|
|
|
response, err := io.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -380,25 +381,15 @@ func getNodes(client *http.Client, argv *argT) (Nodes, error) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func getHTTPClient(argv *argT) (*http.Client, error) {
|
|
|
|
func getHTTPClient(argv *argT) (*http.Client, error) {
|
|
|
|
var rootCAs *x509.CertPool
|
|
|
|
tlsConfig, err := rtls.CreateClientConfig(argv.ClientCert, argv.ClientKey, argv.CACert, argv.Insecure)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if argv.CACert != "" {
|
|
|
|
return nil, err
|
|
|
|
pemCerts, err := ioutil.ReadFile(argv.CACert)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rootCAs = x509.NewCertPool()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ok := rootCAs.AppendCertsFromPEM(pemCerts)
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("failed to parse root CA certificate(s)")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tlsConfig.NextProtos = nil // CLI refuses to connect otherwise.
|
|
|
|
|
|
|
|
|
|
|
|
client := http.Client{
|
|
|
|
client := http.Client{
|
|
|
|
Transport: &http.Transport{
|
|
|
|
Transport: &http.Transport{
|
|
|
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: argv.Insecure, RootCAs: rootCAs},
|
|
|
|
TLSClientConfig: tlsConfig,
|
|
|
|
Proxy: http.ProxyFromEnvironment,
|
|
|
|
Proxy: http.ProxyFromEnvironment,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Timeout: argv.HTTPTimeout.Duration,
|
|
|
|
Timeout: argv.HTTPTimeout.Duration,
|
|
|
@ -446,24 +437,13 @@ func getVersionWithClient(client *http.Client, argv *argT) (string, error) {
|
|
|
|
|
|
|
|
|
|
|
|
func sendRequest(ctx *cli.Context, makeNewRequest func(string) (*http.Request, error), urlStr string, argv *argT) (*[]byte, error) {
|
|
|
|
func sendRequest(ctx *cli.Context, makeNewRequest func(string) (*http.Request, error), urlStr string, argv *argT) (*[]byte, error) {
|
|
|
|
url := urlStr
|
|
|
|
url := urlStr
|
|
|
|
var rootCAs *x509.CertPool
|
|
|
|
tlsConfig, err := rtls.CreateClientConfig(argv.ClientCert, argv.ClientKey, argv.CACert, argv.Insecure)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if argv.CACert != "" {
|
|
|
|
return nil, err
|
|
|
|
pemCerts, err := ioutil.ReadFile(argv.CACert)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rootCAs = x509.NewCertPool()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ok := rootCAs.AppendCertsFromPEM(pemCerts)
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("failed to parse root CA certificate(s)")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tlsConfig.NextProtos = nil // CLI refuses to connect otherwise.
|
|
|
|
client := http.Client{Transport: &http.Transport{
|
|
|
|
client := http.Client{Transport: &http.Transport{
|
|
|
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: argv.Insecure, RootCAs: rootCAs},
|
|
|
|
TLSClientConfig: tlsConfig,
|
|
|
|
Proxy: http.ProxyFromEnvironment,
|
|
|
|
Proxy: http.ProxyFromEnvironment,
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
|
|
|
|
|
|
|
@ -491,7 +471,7 @@ func sendRequest(ctx *cli.Context, makeNewRequest func(string) (*http.Request, e
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
response, err := ioutil.ReadAll(resp.Body)
|
|
|
|
response, err := io.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -577,7 +557,7 @@ func cliJSON(ctx *cli.Context, cmd, line, url string, argv *argT) error {
|
|
|
|
return fmt.Errorf("unauthorized")
|
|
|
|
return fmt.Errorf("unauthorized")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -634,7 +614,7 @@ func urlsToWriter(client *http.Client, urls []string, w io.Writer, argv *argT) e
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|