Add mcs admin trace api (#82)

Trace Api uses websocket to send trace information, a
valid jwt token needs to be sent either on the header
or as a cookie of the ws request to start.
Three goroutines are needed to ensure communication
if read hearbeat fails all trace should stop by cancelling
the context. WaitGroups are needed to ensure all
goroutines finish gracefully.
This commit is contained in:
César Nieto
2020-04-30 10:50:51 -07:00
committed by GitHub
parent 9df9309c66
commit 8e9bd8728a
17 changed files with 732 additions and 408 deletions

56
pkg/ws/websocket.go Normal file
View File

@@ -0,0 +1,56 @@
// This file is part of MinIO Console Server
// Copyright (c) 2020 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Package ws contains websocket utils for mcs project
package ws
import (
"net/http"
"strings"
"github.com/go-openapi/errors"
"github.com/minio/mcs/pkg/auth"
)
// Authenticate validates websocket header and returns mcs jwt claims
//
// Authorization Header needs to be like "Authorization Bearer <jwt_token>"
func Authenticate(r *http.Request) (*auth.DecryptedClaims, error) {
// Get Auth token
var reqToken string
// Token might come either as a Cookie or as a Header
// if not set in cookie, check if it is set on Header.
tokenCookie, err := r.Cookie("token")
if err != nil {
headerToken := r.Header.Get("Authorization")
// reqToken should come as "Bearer <token>"
splitHeaderToken := strings.Split(headerToken, "Bearer")
if len(splitHeaderToken) <= 1 {
return nil, errors.New(http.StatusBadRequest, "Authentication not valid")
}
reqToken = strings.TrimSpace(splitHeaderToken[1])
} else {
reqToken = strings.TrimSpace(tokenCookie.Value)
}
// Perform authentication before upgrading to a Websocket Connection
claims, err := auth.JWTAuthenticate(reqToken)
if err != nil {
return nil, errors.New(http.StatusUnauthorized, err.Error())
}
return claims, nil
}