ssl: Set a global boolean to enable SSL across Minio (#3558)

We have been using `isSSL()` everywhere we can set
a global value once and re-use it again.
master
Harshavardhana 8 years ago committed by GitHub
parent 12a7a15daa
commit 08b6cfb082
  1. 2
      cmd/admin-rpc-client.go
  2. 2
      cmd/browser-peer-rpc.go
  3. 6
      cmd/globals.go
  4. 2
      cmd/lock-rpc-server.go
  5. 5
      cmd/main.go
  6. 2
      cmd/namespace-lock.go
  7. 6
      cmd/prepare-storage-msg.go
  8. 2
      cmd/s3-peer-client.go
  9. 78
      cmd/server-main.go
  10. 60
      cmd/server-main_test.go
  11. 2
      cmd/server-startup-msg.go
  12. 15
      cmd/server-startup-utils.go
  13. 2
      cmd/storage-rpc-client.go
  14. 6
      cmd/update-main.go
  15. 5
      cmd/version-main.go

@ -125,7 +125,7 @@ func makeAdminPeers(eps []*url.URL) adminPeers {
accessKey: serverCred.AccessKey, accessKey: serverCred.AccessKey,
secretKey: serverCred.SecretKey, secretKey: serverCred.SecretKey,
serverAddr: ep.Host, serverAddr: ep.Host,
secureConn: isSSL(), secureConn: globalIsSSL,
serviceEndpoint: path.Join(reservedBucket, adminPath), serviceEndpoint: path.Join(reservedBucket, adminPath),
serviceName: "Admin", serviceName: "Admin",
} }

@ -106,7 +106,7 @@ func updateCredsOnPeers(creds credential) map[string]error {
accessKey: serverCred.AccessKey, accessKey: serverCred.AccessKey,
secretKey: serverCred.SecretKey, secretKey: serverCred.SecretKey,
serverAddr: peers[ix], serverAddr: peers[ix],
secureConn: isSSL(), secureConn: globalIsSSL,
serviceEndpoint: path.Join(reservedBucket, browserPeerPath), serviceEndpoint: path.Join(reservedBucket, browserPeerPath),
serviceName: "Browser", serviceName: "Browser",
}) })

@ -90,6 +90,9 @@ var (
// CA root certificates, a nil value means system certs pool will be used // CA root certificates, a nil value means system certs pool will be used
globalRootCAs *x509.CertPool globalRootCAs *x509.CertPool
// IsSSL indicates if the server is configured with SSL.
globalIsSSL bool
// List of admin peers. // List of admin peers.
globalAdminPeers = adminPeers{} globalAdminPeers = adminPeers{}
@ -124,4 +127,7 @@ func setGlobalsFromContext(c *cli.Context) {
} }
// Set global quiet flag. // Set global quiet flag.
globalQuiet = c.Bool("quiet") || c.GlobalBool("quiet") globalQuiet = c.Bool("quiet") || c.GlobalBool("quiet")
// Is TLS configured?.
globalIsSSL = isSSL()
} }

@ -289,7 +289,7 @@ func (l *lockServer) lockMaintenance(interval time.Duration) {
secretKey: serverCred.SecretKey, secretKey: serverCred.SecretKey,
serverAddr: nlrip.lri.node, serverAddr: nlrip.lri.node,
serviceEndpoint: nlrip.lri.rpcPath, serviceEndpoint: nlrip.lri.rpcPath,
secureConn: isSSL(), secureConn: globalIsSSL,
serviceName: "Dsync", serviceName: "Dsync",
}) })

@ -164,7 +164,10 @@ func checkUpdate() {
} }
// Generic Minio initialization to create/load config, prepare loggers, etc.. // Generic Minio initialization to create/load config, prepare loggers, etc..
func minioInit() { func minioInit(ctx *cli.Context) {
// Set global variables after parsing passed arguments
setGlobalsFromContext(ctx)
// Sets new config directory. // Sets new config directory.
setGlobalConfigPath(globalConfigDir) setGlobalConfigPath(globalConfigDir)

@ -44,7 +44,7 @@ func initDsyncNodes(eps []*url.URL) error {
secretKey: cred.SecretKey, secretKey: cred.SecretKey,
serverAddr: ep.Host, serverAddr: ep.Host,
serviceEndpoint: pathutil.Join(lockRPCPath, getPath(ep)), serviceEndpoint: pathutil.Join(lockRPCPath, getPath(ep)),
secureConn: isSSL(), secureConn: globalIsSSL,
serviceName: "Dsync", serviceName: "Dsync",
}) })
if isLocalStorage(ep) && myNode == -1 { if isLocalStorage(ep) && myNode == -1 {

@ -99,11 +99,7 @@ func getHealEndpoint(tls bool, firstEndpoint *url.URL) (cEndpoint *url.URL) {
func getHealMsg(endpoints []*url.URL, storageDisks []StorageAPI) string { func getHealMsg(endpoints []*url.URL, storageDisks []StorageAPI) string {
msg := fmt.Sprintln("\nData volume requires HEALING. Healing is not implemented yet stay tuned:") msg := fmt.Sprintln("\nData volume requires HEALING. Healing is not implemented yet stay tuned:")
// FIXME: Enable this after we bring in healing. // FIXME: Enable this after we bring in healing.
// msg += "MINIO_ACCESS_KEY=%s " // msg := "mc admin heal myminio"
// msg += "MINIO_SECRET_KEY=%s "
// msg += "minio control heal %s"
// creds := serverConfig.GetCredential()
// msg = fmt.Sprintf(msg, creds.AccessKey, creds.SecretKey, getHealEndpoint(isSSL(), endpoints[0]))
disksInfo, _, _ := getDisksInfo(storageDisks) disksInfo, _, _ := getDisksInfo(storageDisks)
for i, info := range disksInfo { for i, info := range disksInfo {
if storageDisks[i] == nil { if storageDisks[i] == nil {

@ -67,7 +67,7 @@ func makeS3Peers(eps []*url.URL) s3Peers {
secretKey: serverCred.SecretKey, secretKey: serverCred.SecretKey,
serverAddr: ep.Host, serverAddr: ep.Host,
serviceEndpoint: path.Join(reservedBucket, s3Path), serviceEndpoint: path.Join(reservedBucket, s3Path),
secureConn: isSSL(), secureConn: globalIsSSL,
serviceName: "S3", serviceName: "S3",
} }

@ -17,12 +17,14 @@
package cmd package cmd
import ( import (
"errors"
"fmt" "fmt"
"net" "net"
"net/url" "net/url"
"os" "os"
"path" "path"
"sort" "sort"
"strconv"
"strings" "strings"
"runtime" "runtime"
@ -296,11 +298,10 @@ func checkServerSyntax(c *cli.Context) {
} }
} }
tls := isSSL()
for _, ep := range endpoints { for _, ep := range endpoints {
if ep.Scheme == "https" && !tls { if ep.Scheme == "https" && !globalIsSSL {
// Certificates should be provided for https configuration. // Certificates should be provided for https configuration.
fatalIf(errInvalidArgument, "Certificates not provided for https") fatalIf(errInvalidArgument, "Certificates not provided for secure configuration")
} }
} }
} }
@ -317,17 +318,47 @@ func isAnyEndpointLocal(eps []*url.URL) bool {
return anyLocalEp return anyLocalEp
} }
// Returned when there are no ports.
var errEmptyPort = errors.New("Port cannot be empty or '0', please use `--address` to pick a specific port")
// Convert an input address of form host:port into, host and port, returns if any.
func getHostPort(address string) (host, port string, err error) {
// Check if requested port is available.
host, port, err = net.SplitHostPort(address)
if err != nil {
return "", "", err
}
// Empty ports.
if port == "0" || port == "" {
// Port zero or empty means use requested to choose any freely available
// port. Avoid this since it won't work with any configured clients,
// can lead to serious loss of availability.
return "", "", errEmptyPort
}
// Parse port.
if _, err = strconv.Atoi(port); err != nil {
return "", "", err
}
// Check if port is available.
if err = checkPortAvailability(port); err != nil {
return "", "", err
}
// Success.
return host, port, nil
}
// serverMain handler called for 'minio server' command. // serverMain handler called for 'minio server' command.
func serverMain(c *cli.Context) { func serverMain(c *cli.Context) {
if !c.Args().Present() || c.Args().First() == "help" { if !c.Args().Present() || c.Args().First() == "help" {
cli.ShowCommandHelpAndExit(c, "server", 1) cli.ShowCommandHelpAndExit(c, "server", 1)
} }
// Set global variables after parsing passed arguments
setGlobalsFromContext(c)
// Initialization routine, such as config loading, enable logging, .. // Initialization routine, such as config loading, enable logging, ..
minioInit() minioInit(c)
// Check for minio updates from dl.minio.io // Check for minio updates from dl.minio.io
checkUpdate() checkUpdate()
@ -335,20 +366,9 @@ func serverMain(c *cli.Context) {
// Server address. // Server address.
serverAddr := c.String("address") serverAddr := c.String("address")
// Check if requested port is available. var err error
host, portStr, err := net.SplitHostPort(serverAddr) globalMinioHost, globalMinioPort, err = getHostPort(serverAddr)
fatalIf(err, "Unable to parse %s.", serverAddr) fatalIf(err, "Unable to extract host and port %s", serverAddr)
if portStr == "0" || portStr == "" {
// Port zero or empty means use requested to choose any freely available
// port. Avoid this since it won't work with any configured clients,
// can lead to serious loss of availability.
fatalIf(errInvalidArgument, "Invalid port `%s`, please use `--address` to pick a specific port", portStr)
}
globalMinioHost = host
// Check if requested port is available.
fatalIf(checkPortAvailability(portStr), "Port unavailable %s", portStr)
globalMinioPort = portStr
// Check server syntax and exit in case of errors. // Check server syntax and exit in case of errors.
// Done after globalMinioHost and globalMinioPort is set as parseStorageEndpoints() // Done after globalMinioHost and globalMinioPort is set as parseStorageEndpoints()
@ -365,9 +385,6 @@ func serverMain(c *cli.Context) {
fatalIf(errInvalidArgument, "None of the disks passed as command line args are local to this server.") fatalIf(errInvalidArgument, "None of the disks passed as command line args are local to this server.")
} }
// Is TLS configured?.
tls := isSSL()
// Sort endpoints for consistent ordering across multiple // Sort endpoints for consistent ordering across multiple
// nodes in a distributed setup. This is to avoid format.json // nodes in a distributed setup. This is to avoid format.json
// corruption if the disks aren't supplied in the same order // corruption if the disks aren't supplied in the same order
@ -415,7 +432,8 @@ func serverMain(c *cli.Context) {
globalMinioAddr = getLocalAddress(srvConfig) globalMinioAddr = getLocalAddress(srvConfig)
// Determine API endpoints where we are going to serve the S3 API from. // Determine API endpoints where we are going to serve the S3 API from.
apiEndPoints := finalizeAPIEndpoints(tls, apiServer.Server) apiEndPoints, err := finalizeAPIEndpoints(apiServer.Server)
fatalIf(err, "Unable to finalize API endpoints for %s", apiServer.Server.Addr)
// Set the global API endpoints value. // Set the global API endpoints value.
globalAPIEndpoints = apiEndPoints globalAPIEndpoints = apiEndPoints
@ -427,15 +445,13 @@ func serverMain(c *cli.Context) {
initGlobalAdminPeers(endpoints) initGlobalAdminPeers(endpoints)
// Start server, automatically configures TLS if certs are available. // Start server, automatically configures TLS if certs are available.
go func(tls bool) { go func() {
var lerr error
cert, key := "", "" cert, key := "", ""
if tls { if globalIsSSL {
cert, key = mustGetCertFile(), mustGetKeyFile() cert, key = mustGetCertFile(), mustGetKeyFile()
} }
lerr = apiServer.ListenAndServe(cert, key) fatalIf(apiServer.ListenAndServe(cert, key), "Failed to start minio server.")
fatalIf(lerr, "Failed to start minio server.") }()
}(tls)
// Wait for formatting of disks. // Wait for formatting of disks.
formattedDisks, err := waitForFormatDisks(firstDisk, endpoints, storageDisks) formattedDisks, err := waitForFormatDisks(firstDisk, endpoints, storageDisks)

@ -63,20 +63,66 @@ func TestGetListenIPs(t *testing.T) {
} }
} }
// Tests get host port.
func TestGetHostPort(t *testing.T) {
testCases := []struct {
addr string
err error
}{
// Test 1 - successful.
{
addr: ":" + getFreePort(),
err: nil,
},
// Test 2 port empty.
{
addr: ":0",
err: errEmptyPort,
},
// Test 3 port empty.
{
addr: ":",
err: errEmptyPort,
},
// Test 4 invalid port.
{
addr: "linux:linux",
err: errors.New("strconv.ParseInt: parsing \"linux\": invalid syntax"),
},
// Test 5 port not present.
{
addr: "hostname",
err: errors.New("missing port in address hostname"),
},
}
// Validate all tests.
for i, testCase := range testCases {
_, _, err := getHostPort(testCase.addr)
if err != nil {
if err.Error() != testCase.err.Error() {
t.Fatalf("Test %d: Error: %s", i+1, err)
}
}
}
}
// Tests finalize api endpoints.
func TestFinalizeAPIEndpoints(t *testing.T) { func TestFinalizeAPIEndpoints(t *testing.T) {
testCases := []struct { testCases := []struct {
tls bool
addr string addr string
}{ }{
{false, ":80"}, {":80"},
{true, ":80"}, {":80"},
{false, "localhost:80"}, {"localhost:80"},
{true, "localhost:80"}, {"localhost:80"},
} }
for i, test := range testCases { for i, test := range testCases {
endPoints := finalizeAPIEndpoints(test.tls, &http.Server{Addr: test.addr}) endPoints, err := finalizeAPIEndpoints(&http.Server{
if len(endPoints) <= 0 { Addr: test.addr,
})
if err != nil && len(endPoints) <= 0 {
t.Errorf("Test case %d returned with no API end points for %s", t.Errorf("Test case %d returned with no API end points for %s",
i+1, test.addr) i+1, test.addr)
} }

@ -67,7 +67,7 @@ func printStartupMessage(apiEndPoints []string) {
// SSL is configured reads certification chain, prints // SSL is configured reads certification chain, prints
// authority and expiry. // authority and expiry.
if isSSL() { if globalIsSSL {
certs, err := readCertificateChain() certs, err := readCertificateChain()
fatalIf(err, "Unable to read certificate chain.") fatalIf(err, "Unable to read certificate chain.")
printCertificateMsg(certs) printCertificateMsg(certs)

@ -40,22 +40,27 @@ func getListenIPs(serverAddr string) (hosts []string, port string, err error) {
} }
return hosts, port, nil return hosts, port, nil
} // if host != "" { } // if host != "" {
// Proceed to append itself, since user requested a specific endpoint. // Proceed to append itself, since user requested a specific endpoint.
hosts = append(hosts, host) hosts = append(hosts, host)
// Success.
return hosts, port, nil return hosts, port, nil
} }
// Finalizes the API endpoints based on the host list and port. // Finalizes the API endpoints based on the host list and port.
func finalizeAPIEndpoints(tls bool, apiServer *http.Server) (endPoints []string) { func finalizeAPIEndpoints(apiServer *http.Server) (endPoints []string, err error) {
// Verify current scheme. // Verify current scheme.
scheme := "http" scheme := "http"
if tls { if globalIsSSL {
scheme = "https" scheme = "https"
} }
// Get list of listen ips and port. // Get list of listen ips and port.
hosts, port, err := getListenIPs(apiServer.Addr) hosts, port, err1 := getListenIPs(apiServer.Addr)
fatalIf(err, "Unable to get list of ips to listen on") if err1 != nil {
return nil, err1
}
// Construct proper endpoints. // Construct proper endpoints.
for _, host := range hosts { for _, host := range hosts {
@ -63,5 +68,5 @@ func finalizeAPIEndpoints(tls bool, apiServer *http.Server) (endPoints []string)
} }
// Success. // Success.
return endPoints return endPoints, nil
} }

@ -121,7 +121,7 @@ func newStorageRPC(ep *url.URL) (StorageAPI, error) {
secretKey: secretKey, secretKey: secretKey,
serverAddr: rpcAddr, serverAddr: rpcAddr,
serviceEndpoint: rpcPath, serviceEndpoint: rpcPath,
secureConn: isSSL(), secureConn: globalIsSSL,
serviceName: "Storage", serviceName: "Storage",
disableReconnect: true, disableReconnect: true,
}), }),

@ -265,12 +265,8 @@ func getReleaseUpdate(updateURL string, duration time.Duration) (updateMsg updat
// main entry point for update command. // main entry point for update command.
func mainUpdate(ctx *cli.Context) { func mainUpdate(ctx *cli.Context) {
// Set global variables after parsing passed arguments
setGlobalsFromContext(ctx)
// Initialization routine, such as config loading, enable logging, .. // Initialization routine, such as config loading, enable logging, ..
minioInit() minioInit(ctx)
if globalQuiet { if globalQuiet {
return return

@ -44,11 +44,8 @@ func mainVersion(ctx *cli.Context) {
cli.ShowCommandHelpAndExit(ctx, "version", 1) cli.ShowCommandHelpAndExit(ctx, "version", 1)
} }
// Set global variables after parsing passed arguments
setGlobalsFromContext(ctx)
// Initialization routine, such as config loading, enable logging, .. // Initialization routine, such as config loading, enable logging, ..
minioInit() minioInit(ctx)
if globalQuiet { if globalQuiet {
return return

Loading…
Cancel
Save