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.

150 lines
4.0 KiB

  1. /*
  2. * Minio Cloud Storage, (C) 2016 Minio, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package cmd
  17. import (
  18. "path"
  19. "sync"
  20. "time"
  21. )
  22. // Login handler implements JWT login token generator, which upon login request
  23. // along with username and password is generated.
  24. func (br *browserPeerAPIHandlers) LoginHandler(args *RPCLoginArgs, reply *RPCLoginReply) error {
  25. jwt, err := newJWT(defaultInterNodeJWTExpiry)
  26. if err != nil {
  27. return err
  28. }
  29. if err = jwt.Authenticate(args.Username, args.Password); err != nil {
  30. return err
  31. }
  32. token, err := jwt.GenerateToken(args.Username)
  33. if err != nil {
  34. return err
  35. }
  36. reply.Token = token
  37. reply.ServerVersion = Version
  38. reply.Timestamp = time.Now().UTC()
  39. return nil
  40. }
  41. // SetAuthPeerArgs - Arguments collection for SetAuth RPC call
  42. type SetAuthPeerArgs struct {
  43. // For Auth
  44. GenericArgs
  45. // New credentials that receiving peer should update to.
  46. Creds credential
  47. }
  48. // SetAuthPeer - Update to new credentials sent from a peer Minio
  49. // server. Since credentials are already validated on the sending
  50. // peer, here we just persist to file and update in-memory config. All
  51. // subsequently running isRPCTokenValid() calls will fail, and clients
  52. // will be forced to re-establish connections. Connections will be
  53. // re-established only when the sending client has also updated its
  54. // credentials.
  55. func (br *browserPeerAPIHandlers) SetAuthPeer(args SetAuthPeerArgs, reply *GenericReply) error {
  56. // Check auth
  57. if !isRPCTokenValid(args.Token) {
  58. return errInvalidToken
  59. }
  60. // Update credentials in memory
  61. serverConfig.SetCredential(args.Creds)
  62. // Save credentials to config file
  63. if err := serverConfig.Save(); err != nil {
  64. errorIf(err, "Error updating config file with new credentials sent from browser RPC.")
  65. return err
  66. }
  67. return nil
  68. }
  69. // Sends SetAuthPeer RPCs to all peers in the Minio cluster
  70. func updateCredsOnPeers(creds credential) map[string]error {
  71. // Get list of peer addresses (from globalS3Peers)
  72. peers := []string{}
  73. for _, p := range globalS3Peers {
  74. peers = append(peers, p.addr)
  75. }
  76. // Array of errors for each peer
  77. errs := make([]error, len(peers))
  78. var wg sync.WaitGroup
  79. // Launch go routines to send request to each peer in parallel.
  80. for ix := range peers {
  81. wg.Add(1)
  82. go func(ix int) {
  83. defer wg.Done()
  84. // Exclude self to avoid race with
  85. // invalidating the RPC token.
  86. if peers[ix] == globalMinioAddr {
  87. errs[ix] = nil
  88. return
  89. }
  90. // Initialize client
  91. client := newAuthClient(&authConfig{
  92. accessKey: serverConfig.GetCredential().AccessKeyID,
  93. secretKey: serverConfig.GetCredential().SecretAccessKey,
  94. address: peers[ix],
  95. secureConn: isSSL(),
  96. path: path.Join(reservedBucket, browserPeerPath),
  97. loginMethod: "Browser.LoginHandler",
  98. })
  99. // Construct RPC call arguments.
  100. args := SetAuthPeerArgs{Creds: creds}
  101. // Make RPC call - we only care about error
  102. // response and not the reply.
  103. err := client.Call("Browser.SetAuthPeer", &args, &GenericReply{})
  104. // We try a bit hard (3 attempts with 1 second delay)
  105. // to set creds on peers in case of failure.
  106. if err != nil {
  107. for i := 0; i < 2; i++ {
  108. time.Sleep(1 * time.Second) // 1 second delay.
  109. err = client.Call("Browser.SetAuthPeer", &args, &GenericReply{})
  110. if err == nil {
  111. break
  112. }
  113. }
  114. }
  115. // Send result down the channel
  116. errs[ix] = err
  117. }(ix)
  118. }
  119. // Wait for requests to complete.
  120. wg.Wait()
  121. // Put errors into map.
  122. errsMap := make(map[string]error)
  123. for i, err := range errs {
  124. if err != nil {
  125. errsMap[peers[i]] = err
  126. }
  127. }
  128. return errsMap
  129. }