Skip to content

Commit 56dbef5

Browse files
author
Anis Elleuch
committed
Skip TLS verification for requests to local address
If CONSOLE_MINIO_URL is pointing to 127.0.0.1, skip the TLS verificatin
1 parent 413870e commit 56dbef5

File tree

8 files changed

+81
-34
lines changed

8 files changed

+81
-34
lines changed

operatorapi/login.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func getLoginDetailsResponse(params authApi.LoginDetailParams) (*models.LoginDet
106106
if oauth2.IsIDPEnabled() {
107107
loginStrategy = models.LoginDetailsLoginStrategyRedirectDashServiceDashAccount
108108
// initialize new oauth2 client
109-
oauth2Client, err := oauth2.NewOauth2ProviderClient(nil, r, restapi.GetConsoleHTTPClient())
109+
oauth2Client, err := oauth2.NewOauth2ProviderClient(nil, r, restapi.GetConsoleHTTPClient(""))
110110
if err != nil {
111111
return nil, restapi.ErrorWithContext(ctx, err)
112112
}
@@ -144,7 +144,7 @@ func getLoginOauth2AuthResponse(params authApi.LoginOauth2AuthParams) (*models.L
144144

145145
if oauth2.IsIDPEnabled() {
146146
// initialize new oauth2 client
147-
oauth2Client, err := oauth2.NewOauth2ProviderClient(nil, r, restapi.GetConsoleHTTPClient())
147+
oauth2Client, err := oauth2.NewOauth2ProviderClient(nil, r, restapi.GetConsoleHTTPClient(""))
148148
if err != nil {
149149
return nil, restapi.ErrorWithContext(ctx, err)
150150
}

operatorapi/operator_subnet.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ func getOperatorSubnetLoginResponse(session *models.Principal, params operator_a
8888
if username == "" || password == "" {
8989
return nil, restapi.ErrorWithContext(ctx, errors.New("empty credentials"))
9090
}
91-
subnetHTTPClient := &xhttp.Client{Client: restapi.GetConsoleHTTPClient()}
91+
subnetHTTPClient := &xhttp.Client{Client: restapi.GetConsoleHTTPClient("")}
9292
token, mfa, err := restapi.SubnetLogin(subnetHTTPClient, username, password)
9393
if err != nil {
9494
return nil, restapi.ErrorWithContext(ctx, err)
@@ -102,7 +102,7 @@ func getOperatorSubnetLoginResponse(session *models.Principal, params operator_a
102102
func getOperatorSubnetLoginMFAResponse(session *models.Principal, params operator_api.OperatorSubnetLoginMFAParams) (*models.OperatorSubnetLoginResponse, *models.Error) {
103103
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
104104
defer cancel()
105-
subnetHTTPClient := &xhttp.Client{Client: restapi.GetConsoleHTTPClient()}
105+
subnetHTTPClient := &xhttp.Client{Client: restapi.GetConsoleHTTPClient("")}
106106
res, err := subnet.LoginWithMFA(subnetHTTPClient, *params.Body.Username, *params.Body.MfaToken, *params.Body.Otp)
107107
if err != nil {
108108
return nil, restapi.ErrorWithContext(ctx, err)
@@ -115,7 +115,7 @@ func getOperatorSubnetLoginMFAResponse(session *models.Principal, params operato
115115
func getOperatorSubnetAPIKeyResponse(session *models.Principal, params operator_api.OperatorSubnetAPIKeyParams) (*models.OperatorSubnetAPIKey, *models.Error) {
116116
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
117117
defer cancel()
118-
subnetHTTPClient := &xhttp.Client{Client: restapi.GetConsoleHTTPClient()}
118+
subnetHTTPClient := &xhttp.Client{Client: restapi.GetConsoleHTTPClient("")}
119119
token := params.HTTPRequest.URL.Query().Get("token")
120120
apiKey, err := subnet.GetAPIKey(subnetHTTPClient, token)
121121
if err != nil {

restapi/admin_info.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,7 @@ func getUsageWidgetsForDeployment(ctx context.Context, prometheusURL string, mAd
937937
}
938938

939939
func unmarshalPrometheus(ctx context.Context, endpoint string, data interface{}) bool {
940-
httpClnt := GetConsoleHTTPClient()
940+
httpClnt := GetConsoleHTTPClient(endpoint)
941941
resp, err := httpClnt.Get(endpoint)
942942
if err != nil {
943943
ErrorWithContext(ctx, fmt.Errorf("Unable to fetch labels from prometheus (%s)", resp.Status))
@@ -964,7 +964,7 @@ func testPrometheusURL(ctx context.Context, url string) bool {
964964
ErrorWithContext(ctx, fmt.Errorf("error Building Request: (%v)", err))
965965
return false
966966
}
967-
response, err := GetConsoleHTTPClient().Do(req)
967+
response, err := GetConsoleHTTPClient(url).Do(req)
968968
if err != nil {
969969
ErrorWithContext(ctx, fmt.Errorf("default Prometheus URL not reachable, trying root testing: (%v)", err))
970970
newTestURL := req.URL.Scheme + "://" + req.URL.Host + "/-/healthy"
@@ -973,7 +973,7 @@ func testPrometheusURL(ctx context.Context, url string) bool {
973973
ErrorWithContext(ctx, fmt.Errorf("error Building Root Request: (%v)", err))
974974
return false
975975
}
976-
rootResponse, err := GetConsoleHTTPClient().Do(req2)
976+
rootResponse, err := GetConsoleHTTPClient(newTestURL).Do(req2)
977977
if err != nil {
978978
// URL & Root tests didn't work. Prometheus not reachable
979979
ErrorWithContext(ctx, fmt.Errorf("root Prometheus URL not reachable: (%v)", err))

restapi/admin_subnet.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ func SubnetRegisterWithAPIKey(ctx context.Context, minioClient MinioAdmin, apiKe
9191
if err != nil {
9292
return false, err
9393
}
94-
registerResult, err := subnet.Register(GetConsoleHTTPClient(), serverInfo, apiKey, "", "")
94+
registerResult, err := subnet.Register(GetConsoleHTTPClient(""), serverInfo, apiKey, "", "")
9595
if err != nil {
9696
return false, err
9797
}
@@ -213,7 +213,7 @@ func GetSubnetHTTPClient(ctx context.Context, minioClient MinioAdmin) (*xhttp.Cl
213213
}
214214
subnetHTTPClient.Transport.(*http.Transport).Proxy = http.ProxyURL(subnetProxyURL)
215215
} else {
216-
subnetHTTPClient = GetConsoleHTTPClient()
216+
subnetHTTPClient = GetConsoleHTTPClient("")
217217
}
218218
clientI := &xhttp.Client{
219219
Client: subnetHTTPClient,
@@ -309,7 +309,7 @@ func GetSubnetInfoResponse(session *models.Principal, params subnetApi.SubnetInf
309309
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
310310
defer cancel()
311311
client := &xhttp.Client{
312-
Client: GetConsoleHTTPClient(),
312+
Client: GetConsoleHTTPClient(""),
313313
}
314314

315315
licenseInfo, err := subnet.ParseLicense(client, os.Getenv("CONSOLE_SUBNET_LICENSE"))

restapi/client-admin.go

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ import (
2121
"context"
2222
"encoding/json"
2323
"io"
24+
"net"
2425
"net/http"
26+
"net/url"
27+
"sync"
2528
"time"
2629

2730
"github.com/minio/console/models"
@@ -458,7 +461,7 @@ func newAdminFromClaims(claims *models.Principal) (*madmin.AdminClient, error) {
458461
if err != nil {
459462
return nil, err
460463
}
461-
adminClient.SetCustomTransport(GetConsoleHTTPClient().Transport)
464+
adminClient.SetCustomTransport(GetConsoleHTTPClient(getMinIOServer()).Transport)
462465
return adminClient, nil
463466
}
464467

@@ -477,17 +480,54 @@ func newAdminFromCreds(accessKey, secretKey, endpoint string, tlsEnabled bool) (
477480

478481
// httpClient is a custom http client, this client should not be called directly and instead be
479482
// called using GetConsoleHTTPClient() to ensure is initialized and the certificates are loaded correctly
480-
var httpClient *http.Client
481-
482-
// GetConsoleHTTPClient will initialize the console HTTP Client with fully populated custom TLS
483-
// Transport that with loads certs at
484-
// - ${HOME}/.console/certs/CAs
485-
// - ${HOME}/.minio/certs/CAs
486-
func GetConsoleHTTPClient() *http.Client {
487-
if httpClient == nil {
488-
httpClient = PrepareConsoleHTTPClient(false)
483+
var httpClients = struct {
484+
sync.Mutex
485+
m map[string]*http.Client
486+
}{
487+
m: make(map[string]*http.Client),
488+
}
489+
490+
// isLocalAddress returns true if the url contains an IPv4/IPv6 hostname
491+
// that points to the local machine - FQDN are not supported
492+
func isLocalIPEndpoint(addr string) bool {
493+
u, err := url.Parse(addr)
494+
if err != nil {
495+
return false
496+
}
497+
return isLocalIPAddress(u.Hostname())
498+
}
499+
500+
// isLocalAddress returns true if the url contains an IPv4/IPv6 hostname
501+
// that points to the local machine - FQDN are not supported
502+
func isLocalIPAddress(ipAddr string) bool {
503+
if ipAddr == "" {
504+
return false
489505
}
490-
return httpClient
506+
ip := net.ParseIP(ipAddr)
507+
return ip.IsLoopback()
508+
}
509+
510+
// GetConsoleHTTPClient caches different http clients depending on the target endpoint while taking
511+
// in consideration CA certs stored in ${HOME}/.console/certs/CAs and ${HOME}/.minio/certs/CAs
512+
// If the target endpoint points to a loopback device, skip the TLS verification.
513+
func GetConsoleHTTPClient(address string) *http.Client {
514+
u, err := url.Parse(address)
515+
if err == nil {
516+
address = u.Hostname()
517+
}
518+
519+
httpClients.Lock()
520+
client, ok := httpClients.m[address]
521+
httpClients.Unlock()
522+
if ok {
523+
return client
524+
}
525+
526+
client = PrepareConsoleHTTPClient(isLocalIPAddress(address))
527+
httpClients.Lock()
528+
httpClients.m[address] = client
529+
httpClients.Unlock()
530+
return client
491531
}
492532

493533
func (ac AdminClient) speedtest(ctx context.Context, opts madmin.SpeedtestOpts) (chan madmin.SpeedTestResult, error) {

restapi/client.go

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -330,12 +330,14 @@ func (s consoleSTSAssumeRole) IsExpired() bool {
330330
}
331331

332332
func NewConsoleCredentials(accessKey, secretKey, location string) (*credentials.Credentials, error) {
333+
minioURL := getMinIOServer()
334+
333335
// Future authentication methods can be added under this switch statement
334336
switch {
335337
// LDAP authentication for Console
336338
case ldap.GetLDAPEnabled():
337339
{
338-
creds, err := auth.GetCredentialsFromLDAP(GetConsoleHTTPClient(), getMinIOServer(), accessKey, secretKey)
340+
creds, err := auth.GetCredentialsFromLDAP(GetConsoleHTTPClient(minioURL), minioURL, accessKey, secretKey)
339341
if err != nil {
340342
return nil, err
341343
}
@@ -354,8 +356,8 @@ func NewConsoleCredentials(accessKey, secretKey, location string) (*credentials.
354356
DurationSeconds: int(xjwt.GetConsoleSTSDuration().Seconds()),
355357
}
356358
stsAssumeRole := &credentials.STSAssumeRole{
357-
Client: GetConsoleHTTPClient(),
358-
STSEndpoint: getMinIOServer(),
359+
Client: GetConsoleHTTPClient(minioURL),
360+
STSEndpoint: minioURL,
359361
Options: opts,
360362
}
361363
consoleSTSWrapper := consoleSTSAssumeRole{stsAssumeRole: stsAssumeRole}
@@ -374,10 +376,12 @@ func getConsoleCredentialsFromSession(claims *models.Principal) *credentials.Cre
374376
// from the provided session token
375377
func newMinioClient(claims *models.Principal) (*minio.Client, error) {
376378
creds := getConsoleCredentialsFromSession(claims)
377-
minioClient, err := minio.New(getMinIOEndpoint(), &minio.Options{
379+
endpoint := getMinIOEndpoint()
380+
secure := getMinIOEndpointIsSecure()
381+
minioClient, err := minio.New(endpoint, &minio.Options{
378382
Creds: creds,
379-
Secure: getMinIOEndpointIsSecure(),
380-
Transport: GetConsoleHTTPClient().Transport,
383+
Secure: secure,
384+
Transport: GetConsoleHTTPClient(getMinIOServer()).Transport,
381385
})
382386
if err != nil {
383387
return nil, err
@@ -414,7 +418,7 @@ func newS3BucketClient(claims *models.Principal, bucketName string, prefix strin
414418
if err != nil {
415419
return nil, fmt.Errorf("the provided endpoint is invalid")
416420
}
417-
s3Config := newS3Config(objectURL, claims.STSAccessKeyID, claims.STSSecretAccessKey, claims.STSSessionToken, false)
421+
s3Config := newS3Config(objectURL, claims.STSAccessKeyID, claims.STSSecretAccessKey, claims.STSSessionToken)
418422
client, pErr := mc.S3New(s3Config)
419423
if pErr != nil {
420424
return nil, pErr.Cause
@@ -438,21 +442,24 @@ func pathJoinFinalSlash(elem ...string) string {
438442

439443
// newS3Config simply creates a new Config struct using the passed
440444
// parameters.
441-
func newS3Config(endpoint, accessKey, secretKey, sessionToken string, insecure bool) *mc.Config {
445+
func newS3Config(endpoint, accessKey, secretKey, sessionToken string) *mc.Config {
442446
// We have a valid alias and hostConfig. We populate the/
443447
// consoleCredentials from the match found in the config file.
444448
s3Config := new(mc.Config)
445449

446450
s3Config.AppName = globalAppName
447451
s3Config.AppVersion = pkg.Version
448452
s3Config.Debug = false
449-
s3Config.Insecure = insecure
450453

451454
s3Config.HostURL = endpoint
452455
s3Config.AccessKey = accessKey
453456
s3Config.SecretKey = secretKey
454457
s3Config.SessionToken = sessionToken
455458
s3Config.Signature = "S3v4"
459+
460+
insecure := isLocalIPEndpoint(endpoint)
461+
462+
s3Config.Insecure = insecure
456463
s3Config.Transport = PrepareSTSClientTransport(insecure)
457464

458465
return s3Config

restapi/user_log_search.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ func getLogSearchResponse(session *models.Principal, params logApi.LogSearchPara
9191
}
9292

9393
func logSearch(endpoint string) (*models.LogSearchResponse, error) {
94-
httpClnt := GetConsoleHTTPClient()
94+
httpClnt := GetConsoleHTTPClient(endpoint)
9595
resp, err := httpClnt.Get(endpoint)
9696
if err != nil {
9797
return nil, fmt.Errorf("the Log Search API cannot be reached. Please review the URL and try again %v", err)

restapi/user_login.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ func getLoginDetailsResponse(params authApi.LoginDetailParams, openIDProviders o
157157
loginStrategy = models.LoginDetailsLoginStrategyRedirect
158158
for name, provider := range openIDProviders {
159159
// initialize new oauth2 client
160-
oauth2Client, err := openIDProviders.NewOauth2ProviderClient(name, nil, r, GetConsoleHTTPClient())
160+
oauth2Client, err := openIDProviders.NewOauth2ProviderClient(name, nil, r, GetConsoleHTTPClient(""))
161161
if err != nil {
162162
return nil, ErrorWithContext(ctx, err, ErrOauth2Provider)
163163
}
@@ -199,7 +199,7 @@ func getLoginOauth2AuthResponse(params authApi.LoginOauth2AuthParams, openIDProv
199199
lr := params.Body
200200
if openIDProviders != nil {
201201
// initialize new oauth2 client
202-
oauth2Client, err := openIDProviders.NewOauth2ProviderClient(idpName, nil, r, GetConsoleHTTPClient())
202+
oauth2Client, err := openIDProviders.NewOauth2ProviderClient(idpName, nil, r, GetConsoleHTTPClient(""))
203203
if err != nil {
204204
return nil, ErrorWithContext(ctx, err)
205205
}

0 commit comments

Comments
 (0)