mirror of
https://github.com/minio/minio.git
synced 2025-11-20 09:56:07 -05:00
147
cmd/browser-peer-rpc.go
Normal file
147
cmd/browser-peer-rpc.go
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"path"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Login handler implements JWT login token generator, which upon login request
|
||||
// along with username and password is generated.
|
||||
func (br *browserPeerAPIHandlers) LoginHandler(args *RPCLoginArgs, reply *RPCLoginReply) error {
|
||||
jwt, err := newJWT(defaultInterNodeJWTExpiry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = jwt.Authenticate(args.Username, args.Password); err != nil {
|
||||
return err
|
||||
}
|
||||
token, err := jwt.GenerateToken(args.Username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reply.Token = token
|
||||
reply.ServerVersion = Version
|
||||
reply.Timestamp = time.Now().UTC()
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetAuthPeerArgs - Arguments collection for SetAuth RPC call
|
||||
type SetAuthPeerArgs struct {
|
||||
// For Auth
|
||||
GenericArgs
|
||||
|
||||
// New credentials that receiving peer should update to.
|
||||
Creds credential
|
||||
}
|
||||
|
||||
// SetAuthPeer - Update to new credentials sent from a peer Minio
|
||||
// server. Since credentials are already validated on the sending
|
||||
// peer, here we just persist to file and update in-memory config. All
|
||||
// subsequently running isRPCTokenValid() calls will fail, and clients
|
||||
// will be forced to re-establish connections. Connections will be
|
||||
// re-established only when the sending client has also updated its
|
||||
// credentials.
|
||||
func (br *browserPeerAPIHandlers) SetAuthPeer(args SetAuthPeerArgs, reply *GenericReply) error {
|
||||
// Check auth
|
||||
if !isRPCTokenValid(args.Token) {
|
||||
return errInvalidToken
|
||||
}
|
||||
|
||||
// Update credentials in memory
|
||||
serverConfig.SetCredential(args.Creds)
|
||||
|
||||
// Save credentials to config file
|
||||
if err := serverConfig.Save(); err != nil {
|
||||
errorIf(err, "Error updating config file with new credentials sent from browser RPC.")
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sends SetAuthPeer RPCs to all peers in the Minio cluster
|
||||
func updateCredsOnPeers(creds credential) map[string]error {
|
||||
// Get list of peers (from globalS3Peers)
|
||||
peers := globalS3Peers.GetPeers()
|
||||
|
||||
// Array of errors for each peer
|
||||
errs := make([]error, len(peers))
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Launch go routines to send request to each peer in parallel.
|
||||
for ix := range peers {
|
||||
wg.Add(1)
|
||||
go func(ix int) {
|
||||
defer wg.Done()
|
||||
|
||||
// Exclude self to avoid race with
|
||||
// invalidating the RPC token.
|
||||
if peers[ix] == globalMinioAddr {
|
||||
errs[ix] = nil
|
||||
return
|
||||
}
|
||||
|
||||
// Initialize client
|
||||
client := newAuthClient(&authConfig{
|
||||
accessKey: serverConfig.GetCredential().AccessKeyID,
|
||||
secretKey: serverConfig.GetCredential().SecretAccessKey,
|
||||
address: peers[ix],
|
||||
secureConn: isSSL(),
|
||||
path: path.Join(reservedBucket, browserPeerPath),
|
||||
loginMethod: "Browser.LoginHandler",
|
||||
})
|
||||
|
||||
// Construct RPC call arguments.
|
||||
args := SetAuthPeerArgs{Creds: creds}
|
||||
|
||||
// Make RPC call - we only care about error
|
||||
// response and not the reply.
|
||||
err := client.Call("Browser.SetAuthPeer", &args, &GenericReply{})
|
||||
|
||||
// We try a bit hard (3 attempts with 1 second delay)
|
||||
// to set creds on peers in case of failure.
|
||||
if err != nil {
|
||||
for i := 0; i < 2; i++ {
|
||||
time.Sleep(1 * time.Second) // 1 second delay.
|
||||
err = client.Call("Browser.SetAuthPeer", &args, &GenericReply{})
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send result down the channel
|
||||
errs[ix] = err
|
||||
}(ix)
|
||||
}
|
||||
|
||||
// Wait for requests to complete.
|
||||
wg.Wait()
|
||||
|
||||
// Put errors into map.
|
||||
errsMap := make(map[string]error)
|
||||
for i, err := range errs {
|
||||
if err != nil {
|
||||
errsMap[peers[i]] = err
|
||||
}
|
||||
}
|
||||
|
||||
return errsMap
|
||||
}
|
||||
Reference in New Issue
Block a user