<commit_before>package server

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/gorilla/mux"
	"github.com/libopenstorage/openstorage/api"
	"github.com/libopenstorage/openstorage/pkg/auth"
	"github.com/libopenstorage/openstorage/pkg/auth/secrets"
	osecrets "github.com/libopenstorage/openstorage/pkg/auth/secrets"
	"github.com/libopenstorage/openstorage/pkg/util"
	"github.com/libopenstorage/openstorage/volume"
	volumedrivers "github.com/libopenstorage/openstorage/volume/drivers"
	lsecrets "github.com/libopenstorage/secrets"
	"github.com/portworx/sched-ops/k8s/core"
	"github.com/sirupsen/logrus"
)

const (
	// PVCNameLabelKey is used for kubernetes auth provider indicating the name of PVC
	PVCNameLabelKey = "pvc"
	// PVCNamespaceLabelKey is used for kubernetes auth provider indicating the namespace of the PVC
	PVCNamespaceLabelKey = "namespace"
)

var (
	// OverrideSchedDriverName is set by osd program to override the schedule driver
	OverrideSchedDriverName = ""
)

// NewAuthMiddleware returns a negroni implementation of an http middleware
// which will intercept the management APIs
func NewAuthMiddleware() *authMiddleware {
	return &authMiddleware{}
}

type authMiddleware struct {
}

// newSecurityMiddleware based on auth configuration returns SecurityHandler or just
func newSecurityMiddleware(authenticators map[string]auth.Authenticator) func(next http.HandlerFunc) http.HandlerFunc {
	if auth.Enabled() {
		return func(next http.HandlerFunc) http.HandlerFunc {
			return SecurityHandler(authenticators, next)
		}
	}

	return func(next http.HandlerFunc) http.HandlerFunc {
		return next
	}
}

// SecurityHandler implements Authentication and Authorization check at the same time
// this functionality where not moved to separate functions because of simplicity
func SecurityHandler(authenticators map[string]auth.Authenticator, next http.HandlerFunc) http.HandlerFunc {
	if authenticators == nil {
		return next
	}

	return func(w http.ResponseWriter, r *http.Request) {

		tokenHeader := r.Header.Get("Authorization")
		tokens := strings.Split(tokenHeader, " ")

		if len(tokens) < 2 {
			w.WriteHeader(http.StatusUnauthorized)
			json.NewEncoder(w).Encode(&api.ClusterResponse{
				Error: fmt.Sprintf("Access denied, token is malformed"),
			})
			return
		}
		token := tokens[1]

		// Determine issuer
		issuer, err := auth.TokenIssuer(token)
		if err != nil {
			w.WriteHeader(http.StatusUnauthorized)
			json.NewEncoder(w).Encode(&api.ClusterResponse{
				Error: fmt.Sprintf("Access denied, %v", err),
			})
			return
		}

		// Use http.Request context for cancellation propagation
		ctx := r.Context()

		// Authenticate user
		var claims *auth.Claims
		if authenticator, exists := authenticators[issuer]; exists {
			claims, err = authenticator.AuthenticateToken(ctx, token)

			if err != nil {
				w.WriteHeader(http.StatusForbidden)
				json.NewEncoder(w).Encode(&api.ClusterResponse{
					Error: fmt.Sprintf("Access denied, %s", err.Error()),
				})
				return
			}
			if claims == nil {
				w.WriteHeader(http.StatusForbidden)
				json.NewEncoder(w).Encode(&api.ClusterResponse{
					Error: fmt.Sprintf("Access denied, wrong claims provided"),
				})
			}
		} else {
			w.WriteHeader(http.StatusUnauthorized)
			json.NewEncoder(w).Encode(&api.ClusterResponse{
				Error: fmt.Sprintf("Access denied, no authenticator for issuer %s", issuer),
			})
			return
		}
		// Check if user has admin role to access that endpoint
		isSystemAdmin := false

		for _, role := range claims.Roles {
			if role == "system.admin" {
				isSystemAdmin = true
				break
			}
		}

		if !isSystemAdmin {
			w.WriteHeader(http.StatusForbidden)
			json.NewEncoder(w).Encode(&api.ClusterResponse{
				Error: fmt.Sprintf("Access denied, user must have admin access"),
			})
			return
		}

		next.ServeHTTP(w, r)
	}
}

func (a *authMiddleware) createWithAuth(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	fn := "create"
	_, authRequired := a.isTokenProcessingRequired(r)
	if !authRequired {
		next(w, r)
		return
	}

	requestBody := a.getBody(r)
	var dcReq api.VolumeCreateRequest
	var dcRes api.VolumeCreateResponse
	if err := json.NewDecoder(requestBody).Decode(&dcReq); err != nil {
		next(w, r)
		return
	}
<commit_msg>Fix error message for empty token error<commit_after>package server

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/gorilla/mux"
	"github.com/libopenstorage/openstorage/api"
	"github.com/libopenstorage/openstorage/pkg/auth"
	"github.com/libopenstorage/openstorage/pkg/auth/secrets"
	osecrets "github.com/libopenstorage/openstorage/pkg/auth/secrets"
	"github.com/libopenstorage/openstorage/pkg/util"
	"github.com/libopenstorage/openstorage/volume"
	volumedrivers "github.com/libopenstorage/openstorage/volume/drivers"
	lsecrets "github.com/libopenstorage/secrets"
	"github.com/portworx/sched-ops/k8s/core"
	"github.com/sirupsen/logrus"
)

const (
	// PVCNameLabelKey is used for kubernetes auth provider indicating the name of PVC
	PVCNameLabelKey = "pvc"
	// PVCNamespaceLabelKey is used for kubernetes auth provider indicating the namespace of the PVC
	PVCNamespaceLabelKey = "namespace"
)

var (
	// OverrideSchedDriverName is set by osd program to override the schedule driver
	OverrideSchedDriverName = ""
)

// NewAuthMiddleware returns a negroni implementation of an http middleware
// which will intercept the management APIs
func NewAuthMiddleware() *authMiddleware {
	return &authMiddleware{}
}

type authMiddleware struct {
}

// newSecurityMiddleware based on auth configuration returns SecurityHandler or just
func newSecurityMiddleware(authenticators map[string]auth.Authenticator) func(next http.HandlerFunc) http.HandlerFunc {
	if auth.Enabled() {
		return func(next http.HandlerFunc) http.HandlerFunc {
			return SecurityHandler(authenticators, next)
		}
	}

	return func(next http.HandlerFunc) http.HandlerFunc {
		return next
	}
}

// SecurityHandler implements Authentication and Authorization check at the same time
// this functionality where not moved to separate functions because of simplicity
func SecurityHandler(authenticators map[string]auth.Authenticator, next http.HandlerFunc) http.HandlerFunc {
	if authenticators == nil {
		return next
	}

	return func(w http.ResponseWriter, r *http.Request) {
		tokenHeader := r.Header.Get("Authorization")
		tokens := strings.Split(tokenHeader, " ")

		if len(tokens) < 2 {
			w.WriteHeader(http.StatusUnauthorized)
			fmt.Fprintf(w, "Access denied token is empty")
			return
		}
		token := tokens[1]

		// Determine issuer
		issuer, err := auth.TokenIssuer(token)
		if err != nil {
			w.WriteHeader(http.StatusUnauthorized)
			fmt.Fprintf(w, "Access denied, %v", err)
			return
		}

		// Use http.Request context for cancellation propagation
		ctx := r.Context()

		// Authenticate user
		var claims *auth.Claims
		if authenticator, exists := authenticators[issuer]; exists {
			claims, err = authenticator.AuthenticateToken(ctx, token)

			if err != nil {
				w.WriteHeader(http.StatusForbidden)
				fmt.Fprintf(w, "Access denied, %v", err)
				return
			}
			if claims == nil {
				w.WriteHeader(http.StatusForbidden)
				fmt.Fprintf(w, "Access denied, wrong claims provided")
				return
			}
		} else {
			w.WriteHeader(http.StatusUnauthorized)
			fmt.Fprintf(w, "Access denied, no authenticator for issuer %s", issuer)
			return
		}
		// Check if user has admin role to access that endpoint
		isSystemAdmin := false

		for _, role := range claims.Roles {
			if role == "system.admin" {
				isSystemAdmin = true
				break
			}
		}

		if !isSystemAdmin {
			w.WriteHeader(http.StatusForbidden)
			fmt.Fprintf(w, "Access denied, user must have admin access")
			return
		}

		next.ServeHTTP(w, r)
	}
}

func (a *authMiddleware) createWithAuth(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	fn := "create"
	_, authRequired := a.isTokenProcessingRequired(r)
	if !authRequired {
		next(w, r)
		return
	}

	requestBody := a.getBody(r)
	var dcReq api.VolumeCreateRequest
	var dcRes api.VolumeCreateResponse
	if err := json.NewDecoder(requestBody).Decode(&dcReq); err != nil {
		next(w, r)
		return
	}

{'fraction_non_alphanumeric': 0.1073727681282643, 'fraction_numerical': 0.0007287744443094862, 'mean_word_length': 4.237913486005089, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2735177', 'n_tokens_mistral': 2858, 'n_tokens_neox': 2599, 'n_words': 639}