You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
4.5 KiB

  1. // Copyright (c) 2015-2021 MinIO, Inc.
  2. //
  3. // This file is part of MinIO Object Storage stack
  4. //
  5. // This program is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU Affero General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU Affero General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU Affero General Public License
  16. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. package cmd
  18. import (
  19. "errors"
  20. "net/http"
  21. "time"
  22. jwtgo "github.com/golang-jwt/jwt/v4"
  23. jwtreq "github.com/golang-jwt/jwt/v4/request"
  24. "github.com/minio/minio/internal/auth"
  25. xjwt "github.com/minio/minio/internal/jwt"
  26. "github.com/minio/pkg/v3/policy"
  27. )
  28. const (
  29. jwtAlgorithm = "Bearer"
  30. // Default JWT token for web handlers is one day.
  31. defaultJWTExpiry = 24 * time.Hour
  32. // Inter-node JWT token expiry is 100 years approx.
  33. defaultInterNodeJWTExpiry = 100 * 365 * 24 * time.Hour
  34. )
  35. var (
  36. errInvalidAccessKeyID = errors.New("The access key ID you provided does not exist in our records")
  37. errAccessKeyDisabled = errors.New("The access key you provided is disabled")
  38. errAuthentication = errors.New("Authentication failed, check your access credentials")
  39. errNoAuthToken = errors.New("JWT token missing")
  40. errSkewedAuthTime = errors.New("Skewed authentication date/time")
  41. errMalformedAuth = errors.New("Malformed authentication input")
  42. )
  43. func authenticateNode(accessKey, secretKey string) (string, error) {
  44. claims := xjwt.NewStandardClaims()
  45. claims.SetExpiry(UTCNow().Add(defaultInterNodeJWTExpiry))
  46. claims.SetAccessKey(accessKey)
  47. jwt := jwtgo.NewWithClaims(jwtgo.SigningMethodHS512, claims)
  48. return jwt.SignedString([]byte(secretKey))
  49. }
  50. // Check if the request is authenticated.
  51. // Returns nil if the request is authenticated. errNoAuthToken if token missing.
  52. // Returns errAuthentication for all other errors.
  53. func metricsRequestAuthenticate(req *http.Request) (*xjwt.MapClaims, []string, bool, error) {
  54. token, err := jwtreq.AuthorizationHeaderExtractor.ExtractToken(req)
  55. if err != nil {
  56. if err == jwtreq.ErrNoTokenInRequest {
  57. return nil, nil, false, errNoAuthToken
  58. }
  59. return nil, nil, false, err
  60. }
  61. claims := xjwt.NewMapClaims()
  62. if err := xjwt.ParseWithClaims(token, claims, func(claims *xjwt.MapClaims) ([]byte, error) {
  63. if claims.AccessKey != globalActiveCred.AccessKey {
  64. u, ok := globalIAMSys.GetUser(req.Context(), claims.AccessKey)
  65. if !ok {
  66. // Credentials will be invalid but for disabled
  67. // return a different error in such a scenario.
  68. if u.Credentials.Status == auth.AccountOff {
  69. return nil, errAccessKeyDisabled
  70. }
  71. return nil, errInvalidAccessKeyID
  72. }
  73. cred := u.Credentials
  74. // Expired credentials return error.
  75. if cred.IsTemp() && cred.IsExpired() {
  76. return nil, errInvalidAccessKeyID
  77. }
  78. return []byte(cred.SecretKey), nil
  79. } // this means claims.AccessKey == rootAccessKey
  80. if !globalAPIConfig.permitRootAccess() {
  81. // if root access is disabled, fail this request.
  82. return nil, errAccessKeyDisabled
  83. }
  84. return []byte(globalActiveCred.SecretKey), nil
  85. }); err != nil {
  86. return claims, nil, false, errAuthentication
  87. }
  88. owner := true
  89. var groups []string
  90. if globalActiveCred.AccessKey != claims.AccessKey {
  91. // Check if the access key is part of users credentials.
  92. u, ok := globalIAMSys.GetUser(req.Context(), claims.AccessKey)
  93. if !ok {
  94. return nil, nil, false, errInvalidAccessKeyID
  95. }
  96. ucred := u.Credentials
  97. // get embedded claims
  98. eclaims, s3Err := checkClaimsFromToken(req, ucred)
  99. if s3Err != ErrNone {
  100. return nil, nil, false, errAuthentication
  101. }
  102. for k, v := range eclaims {
  103. claims.MapClaims[k] = v
  104. }
  105. // if root access is disabled, disable all its service accounts and temporary credentials.
  106. if ucred.ParentUser == globalActiveCred.AccessKey && !globalAPIConfig.permitRootAccess() {
  107. return nil, nil, false, errAccessKeyDisabled
  108. }
  109. // Now check if we have a sessionPolicy.
  110. if _, ok = eclaims[policy.SessionPolicyName]; ok {
  111. owner = false
  112. } else {
  113. owner = globalActiveCred.AccessKey == ucred.ParentUser
  114. }
  115. groups = ucred.Groups
  116. }
  117. return claims, groups, owner, nil
  118. }
  119. // newCachedAuthToken returns the cached token.
  120. func newCachedAuthToken() func() string {
  121. return func() string {
  122. return globalNodeAuthToken
  123. }
  124. }