Add TLS encryption capability to RPC clients (#2789)

master
Anis Elleuch 8 years ago committed by Harshavardhana
parent 1e6afac3bd
commit 9fb1c89f81
  1. 3
      cmd/auth-rpc-client.go
  2. 1
      cmd/control-heal-main.go
  3. 1
      cmd/control-lock-main.go
  4. 1
      cmd/control-shutdown-main.go
  5. 2
      cmd/lock-rpc-server.go
  6. 3
      cmd/namespace-lock.go
  7. 50
      cmd/net-rpc-client.go
  8. 1
      cmd/storage-rpc-client.go

@ -83,6 +83,7 @@ func isRPCTokenValid(tokenStr string) bool {
type authConfig struct {
accessKey string // Username for the server.
secretKey string // Password for the server.
secureConn bool // Ask for a secured connection
address string // Network address path of RPC server.
path string // Network path for HTTP dial.
loginMethod string // RPC service name for authenticating using JWT
@ -104,7 +105,7 @@ func newAuthClient(cfg *authConfig) *AuthRPCClient {
// Save the config.
config: cfg,
// Initialize a new reconnectable rpc client.
rpc: newClient(cfg.address, cfg.path),
rpc: newClient(cfg.address, cfg.path, cfg.secureConn),
// Allocated auth client not logged in yet.
isLoggedIn: false,
}

@ -87,6 +87,7 @@ func healControl(ctx *cli.Context) {
authCfg := &authConfig{
accessKey: serverConfig.GetCredential().AccessKeyID,
secretKey: serverConfig.GetCredential().SecretAccessKey,
secureConn: parsedURL.Scheme == "https",
address: parsedURL.Host,
path: path.Join(reservedBucket, controlPath),
loginMethod: "Controller.LoginHandler",

@ -126,6 +126,7 @@ func lockControl(c *cli.Context) {
authCfg := &authConfig{
accessKey: serverConfig.GetCredential().AccessKeyID,
secretKey: serverConfig.GetCredential().SecretAccessKey,
secureConn: parsedURL.Scheme == "https",
address: parsedURL.Host,
path: path.Join(reservedBucket, controlPath),
loginMethod: "Controller.LoginHandler",

@ -66,6 +66,7 @@ func shutdownControl(c *cli.Context) {
authCfg := &authConfig{
accessKey: serverConfig.GetCredential().AccessKeyID,
secretKey: serverConfig.GetCredential().SecretAccessKey,
secureConn: parsedURL.Scheme == "https",
address: parsedURL.Host,
path: path.Join(reservedBucket, controlPath),
loginMethod: "Controller.LoginHandler",

@ -294,7 +294,7 @@ func (l *lockServer) lockMaintenance(interval time.Duration) {
// Validate if long lived locks are indeed clean.
for _, nlrip := range nlripLongLived {
// Initialize client based on the long live locks.
c := newClient(nlrip.lri.node, nlrip.lri.rpcPath)
c := newClient(nlrip.lri.node, nlrip.lri.rpcPath, isSSL())
var expired bool

@ -45,7 +45,8 @@ func initDsyncNodes(disks []string, port int) error {
accessKey: cred.AccessKeyID,
secretKey: cred.SecretAccessKey,
// Construct a new dsync server addr.
address: disk[:idx] + ":" + serverPort,
secureConn: isSSL(),
address: disk[:idx] + ":" + serverPort,
// Construct a new rpc path for the disk.
path: pathutil.Join(lockRPCPath, disk[idx+1:]),
loginMethod: "Dsync.LoginHandler",

@ -17,7 +17,12 @@
package cmd
import (
"bufio"
"crypto/tls"
"errors"
"io"
"net"
"net/http"
"net/rpc"
"sync"
)
@ -28,15 +33,17 @@ type RPCClient struct {
rpcPrivate *rpc.Client
node string
rpcPath string
secureConn bool
}
// newClient constructs a RPCClient object with node and rpcPath initialized.
// It _doesn't_ connect to the remote endpoint. See Call method to see when the
// connect happens.
func newClient(node, rpcPath string) *RPCClient {
func newClient(node, rpcPath string, secureConn bool) *RPCClient {
return &RPCClient{
node: node,
rpcPath: rpcPath,
node: node,
rpcPath: rpcPath,
secureConn: secureConn,
}
}
@ -63,14 +70,41 @@ func (rpcClient *RPCClient) dialRPCClient() (*rpc.Client, error) {
if rpcClient.rpcPrivate != nil {
return rpcClient.rpcPrivate, nil
}
rpc, err := rpc.DialHTTPPath("tcp", rpcClient.node, rpcClient.rpcPath)
var err error
var conn net.Conn
if rpcClient.secureConn {
conn, err = tls.Dial("tcp", rpcClient.node, &tls.Config{})
} else {
conn, err = net.Dial("tcp", rpcClient.node)
}
if err != nil {
return nil, err
} else if rpc == nil {
return nil, errors.New("No valid RPC Client created after dial")
}
rpcClient.rpcPrivate = rpc
return rpcClient.rpcPrivate, nil
io.WriteString(conn, "CONNECT "+rpcClient.rpcPath+" HTTP/1.0\n\n")
// Require successful HTTP response
// before switching to RPC protocol.
resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"})
if err == nil && resp.Status == "200 Connected to Go RPC" {
rpc := rpc.NewClient(conn)
if rpc == nil {
return nil, errors.New("No valid RPC Client created after dial")
}
rpcClient.rpcPrivate = rpc
return rpc, nil
}
if err == nil {
err = errors.New("unexpected HTTP response: " + resp.Status)
}
conn.Close()
return nil, &net.OpError{
Op: "dial-http",
Net: rpcClient.node + " " + rpcClient.rpcPath,
Addr: nil,
Err: err,
}
}
// Call makes a RPC call to the remote endpoint using the default codec, namely encoding/gob.

@ -107,6 +107,7 @@ func newRPCClient(networkPath string) (StorageAPI, error) {
rpcClient := newAuthClient(&authConfig{
accessKey: cred.AccessKeyID,
secretKey: cred.SecretAccessKey,
secureConn: isSSL(),
address: rpcAddr,
path: rpcPath,
loginMethod: "Storage.LoginHandler",

Loading…
Cancel
Save