Fix crash observed in OPA initialization (#7990)

Related to #7982, this PR refactors the code
such that we validate the OPA or JWKS in a
common place.

This is also a refactor which is already done
in the new config migration change. Attempt
to avoid any network I/O during Unmarshal of
JSON from disk, instead do it later when
updating the in-memory data structure.
master
Harshavardhana 5 years ago committed by kannappanr
parent 54eded2e6f
commit 8d47ef503c
  1. 30
      cmd/config-current.go
  2. 14
      pkg/iam/policy/opa.go
  3. 22
      pkg/iam/validator/jwt.go

@ -281,28 +281,27 @@ func (s *serverConfig) loadFromEnvs() {
} }
if jwksURL, ok := os.LookupEnv("MINIO_IAM_JWKS_URL"); ok { if jwksURL, ok := os.LookupEnv("MINIO_IAM_JWKS_URL"); ok {
if u, err := xnet.ParseURL(jwksURL); err == nil { u, err := xnet.ParseURL(jwksURL)
s.OpenID.JWKS.URL = u if err != nil {
logger.FatalIf(s.OpenID.JWKS.PopulatePublicKey(), "Unable to populate public key from JWKS URL")
} else {
logger.FatalIf(err, "Unable to parse MINIO_IAM_JWKS_URL %s", jwksURL) logger.FatalIf(err, "Unable to parse MINIO_IAM_JWKS_URL %s", jwksURL)
} }
s.OpenID.JWKS.URL = u
} }
if opaURL, ok := os.LookupEnv("MINIO_IAM_OPA_URL"); ok { if opaURL, ok := os.LookupEnv("MINIO_IAM_OPA_URL"); ok {
if u, err := xnet.ParseURL(opaURL); err == nil { u, err := xnet.ParseURL(opaURL)
if err != nil {
logger.FatalIf(err, "Unable to parse MINIO_IAM_OPA_URL %s", opaURL)
}
opaArgs := iampolicy.OpaArgs{ opaArgs := iampolicy.OpaArgs{
URL: u, URL: u,
AuthToken: os.Getenv("MINIO_IAM_OPA_AUTHTOKEN"), AuthToken: os.Getenv("MINIO_IAM_OPA_AUTHTOKEN"),
Transport: NewCustomHTTPTransport(), Transport: NewCustomHTTPTransport(),
CloseRespFn: xhttp.DrainBody, CloseRespFn: xhttp.DrainBody,
} }
logger.FatalIf(opaArgs.Validate(), "Unable to reach MINIO_IAM_OPA_URL %s", opaURL)
s.Policy.OPA.URL = opaArgs.URL s.Policy.OPA.URL = opaArgs.URL
s.Policy.OPA.AuthToken = opaArgs.AuthToken s.Policy.OPA.AuthToken = opaArgs.AuthToken
logger.FatalIf(opaArgs.Validate(), "Unable to reach MINIO_IAM_OPA_URL %s", opaURL)
} else {
logger.FatalIf(err, "Unable to parse MINIO_IAM_OPA_URL %s", opaURL)
}
} }
} }
@ -547,7 +546,7 @@ func (s *serverConfig) loadToCachedConfigs() {
globalCacheMaxUse = cacheConf.MaxUse globalCacheMaxUse = cacheConf.MaxUse
} }
if err := Environment.LookupKMSConfig(s.KMS); err != nil { if err := Environment.LookupKMSConfig(s.KMS); err != nil {
logger.FatalIf(err, "Unable to setup the KMS") logger.FatalIf(err, "Unable to setup the KMS %s", s.KMS.Vault.Endpoint)
} }
if !globalIsCompressionEnabled { if !globalIsCompressionEnabled {
@ -557,15 +556,22 @@ func (s *serverConfig) loadToCachedConfigs() {
globalIsCompressionEnabled = compressionConf.Enabled globalIsCompressionEnabled = compressionConf.Enabled
} }
if s.OpenID.JWKS.URL != nil && s.OpenID.JWKS.URL.String() != "" {
logger.FatalIf(s.OpenID.JWKS.PopulatePublicKey(),
"Unable to populate public key from JWKS URL %s", s.OpenID.JWKS.URL)
}
globalIAMValidators = getAuthValidators(s) globalIAMValidators = getAuthValidators(s)
if s.Policy.OPA.URL != nil && s.Policy.OPA.URL.String() != "" { if s.Policy.OPA.URL != nil && s.Policy.OPA.URL.String() != "" {
globalPolicyOPA = iampolicy.NewOpa(iampolicy.OpaArgs{ opaArgs := iampolicy.OpaArgs{
URL: s.Policy.OPA.URL, URL: s.Policy.OPA.URL,
AuthToken: s.Policy.OPA.AuthToken, AuthToken: s.Policy.OPA.AuthToken,
Transport: NewCustomHTTPTransport(), Transport: NewCustomHTTPTransport(),
CloseRespFn: xhttp.DrainBody, CloseRespFn: xhttp.DrainBody,
}) }
logger.FatalIf(opaArgs.Validate(), "Unable to reach OPA URL %s", s.Policy.OPA.URL)
globalPolicyOPA = iampolicy.NewOpa(opaArgs)
} }
} }

@ -22,7 +22,6 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os"
xnet "github.com/minio/minio/pkg/net" xnet "github.com/minio/minio/pkg/net"
) )
@ -63,18 +62,9 @@ func (a *OpaArgs) UnmarshalJSON(data []byte) error {
type subOpaArgs OpaArgs type subOpaArgs OpaArgs
var so subOpaArgs var so subOpaArgs
if opaURL, ok := os.LookupEnv("MINIO_IAM_OPA_URL"); ok {
u, err := xnet.ParseURL(opaURL)
if err != nil {
return err
}
so.URL = u
so.AuthToken = os.Getenv("MINIO_IAM_OPA_AUTHTOKEN")
} else {
if err := json.Unmarshal(data, &so); err != nil { if err := json.Unmarshal(data, &so); err != nil {
return err return err
} }
}
oa := OpaArgs(so) oa := OpaArgs(so)
if oa.URL == nil || oa.URL.String() == "" { if oa.URL == nil || oa.URL.String() == "" {
@ -82,10 +72,6 @@ func (a *OpaArgs) UnmarshalJSON(data []byte) error {
return nil return nil
} }
if err := oa.Validate(); err != nil {
return err
}
*a = oa *a = oa
return nil return nil
} }

@ -24,7 +24,6 @@ import (
"fmt" "fmt"
"net" "net"
"net/http" "net/http"
"os"
"strconv" "strconv"
"time" "time"
@ -38,11 +37,6 @@ type JWKSArgs struct {
publicKeys map[string]crypto.PublicKey publicKeys map[string]crypto.PublicKey
} }
// Validate JWT authentication target arguments
func (r *JWKSArgs) Validate() error {
return nil
}
// PopulatePublicKey - populates a new publickey from the JWKS URL. // PopulatePublicKey - populates a new publickey from the JWKS URL.
func (r *JWKSArgs) PopulatePublicKey() error { func (r *JWKSArgs) PopulatePublicKey() error {
insecureClient := &http.Client{Transport: newCustomHTTPTransport(true)} insecureClient := &http.Client{Transport: newCustomHTTPTransport(true)}
@ -83,31 +77,15 @@ func (r *JWKSArgs) UnmarshalJSON(data []byte) error {
type subJWKSArgs JWKSArgs type subJWKSArgs JWKSArgs
var sr subJWKSArgs var sr subJWKSArgs
// IAM related envs.
if jwksURL, ok := os.LookupEnv("MINIO_IAM_JWKS_URL"); ok {
u, err := xnet.ParseURL(jwksURL)
if err != nil {
return err
}
sr.URL = u
} else {
if err := json.Unmarshal(data, &sr); err != nil { if err := json.Unmarshal(data, &sr); err != nil {
return err return err
} }
}
ar := JWKSArgs(sr) ar := JWKSArgs(sr)
if ar.URL == nil || ar.URL.String() == "" { if ar.URL == nil || ar.URL.String() == "" {
*r = ar *r = ar
return nil return nil
} }
if err := ar.Validate(); err != nil {
return err
}
if err := ar.PopulatePublicKey(); err != nil {
return err
}
*r = ar *r = ar
return nil return nil

Loading…
Cancel
Save