mirror of
https://github.com/netbirdio/netbird.git
synced 2025-02-19 19:50:54 +01:00
Hide setup key from non-admin users (#539)
This commit is contained in:
parent
2e0bf61e9a
commit
6aa7a2c5e1
@ -214,8 +214,9 @@ func isBuiltinModule(name string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// /proc/modules
|
// /proc/modules
|
||||||
// name | memory size | reference count | references | state: <Live|Loading|Unloading>
|
//
|
||||||
// macvlan 28672 1 macvtap, Live 0x0000000000000000
|
// name | memory size | reference count | references | state: <Live|Loading|Unloading>
|
||||||
|
// macvlan 28672 1 macvtap, Live 0x0000000000000000
|
||||||
func moduleStatus(name string) (status, error) {
|
func moduleStatus(name string) (status, error) {
|
||||||
state := unknown
|
state := unknown
|
||||||
f, err := os.Open("/proc/modules")
|
f, err := os.Open("/proc/modules")
|
||||||
|
@ -23,7 +23,7 @@ func APIHandler(accountManager s.AccountManager, authIssuer string, authAudience
|
|||||||
|
|
||||||
corsMiddleware := cors.AllowAll()
|
corsMiddleware := cors.AllowAll()
|
||||||
|
|
||||||
acMiddleware := middleware.NewAccessControll(
|
acMiddleware := middleware.NewAccessControl(
|
||||||
authAudience,
|
authAudience,
|
||||||
accountManager.IsUserAdmin)
|
accountManager.IsUserAdmin)
|
||||||
|
|
||||||
|
@ -1,32 +1,38 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
IsUserAdminProperty = "isAdminUser"
|
||||||
|
)
|
||||||
|
|
||||||
type IsUserAdminFunc func(claims jwtclaims.AuthorizationClaims) (bool, error)
|
type IsUserAdminFunc func(claims jwtclaims.AuthorizationClaims) (bool, error)
|
||||||
|
|
||||||
// AccessControll middleware to restrict to make POST/PUT/DELETE requests by admin only
|
// AccessControl middleware to restrict to make POST/PUT/DELETE requests by admin only
|
||||||
type AccessControll struct {
|
type AccessControl struct {
|
||||||
jwtExtractor jwtclaims.ClaimsExtractor
|
jwtExtractor jwtclaims.ClaimsExtractor
|
||||||
isUserAdmin IsUserAdminFunc
|
isUserAdmin IsUserAdminFunc
|
||||||
audience string
|
audience string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAccessControll instance constructor
|
// NewAccessControl instance constructor
|
||||||
func NewAccessControll(audience string, isUserAdmin IsUserAdminFunc) *AccessControll {
|
func NewAccessControl(audience string, isUserAdmin IsUserAdminFunc) *AccessControl {
|
||||||
return &AccessControll{
|
return &AccessControl{
|
||||||
isUserAdmin: isUserAdmin,
|
isUserAdmin: isUserAdmin,
|
||||||
audience: audience,
|
audience: audience,
|
||||||
jwtExtractor: *jwtclaims.NewClaimsExtractor(nil),
|
jwtExtractor: *jwtclaims.NewClaimsExtractor(nil),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler method of the middleware which forbinneds all modify requests for non admin users
|
// Handler method of the middleware which forbids all modify requests for non admin users
|
||||||
func (a *AccessControll) Handler(h http.Handler) http.Handler {
|
// It also adds
|
||||||
|
func (a *AccessControl) Handler(h http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
jwtClaims := a.jwtExtractor.ExtractClaimsFromRequestContext(r, a.audience)
|
jwtClaims := a.jwtExtractor.ExtractClaimsFromRequestContext(r, a.audience)
|
||||||
|
|
||||||
@ -34,7 +40,6 @@ func (a *AccessControll) Handler(h http.Handler) http.Handler {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, fmt.Sprintf("error get user from JWT: %v", err), http.StatusUnauthorized)
|
http.Error(w, fmt.Sprintf("error get user from JWT: %v", err), http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -45,6 +50,10 @@ func (a *AccessControll) Handler(h http.Handler) http.Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newRequest := r.Clone(context.WithValue(r.Context(), IsUserAdminProperty, ok)) //nolint
|
||||||
|
// Update the current request with the new context information.
|
||||||
|
*r = *newRequest
|
||||||
|
|
||||||
h.ServeHTTP(w, r)
|
h.ServeHTTP(w, r)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,15 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
|
"github.com/netbirdio/netbird/management/server/http/middleware"
|
||||||
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetupKeys is a handler that returns a list of setup keys of the account
|
// SetupKeys is a handler that returns a list of setup keys of the account
|
||||||
@ -107,6 +110,11 @@ func (h *SetupKeys) GetSetupKeyHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isUserAdmin, ok := r.Context().Value(middleware.IsUserAdminProperty).(bool)
|
||||||
|
if !ok || !isUserAdmin {
|
||||||
|
key = hideKey(key)
|
||||||
|
}
|
||||||
|
|
||||||
writeSuccess(w, key)
|
writeSuccess(w, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +183,11 @@ func (h *SetupKeys) GetAllSetupKeysHandler(w http.ResponseWriter, r *http.Reques
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isUserAdmin, ok := r.Context().Value(middleware.IsUserAdminProperty).(bool)
|
||||||
|
if !ok {
|
||||||
|
isUserAdmin = false
|
||||||
|
}
|
||||||
|
|
||||||
setupKeys, err := h.accountManager.ListSetupKeys(account.Id)
|
setupKeys, err := h.accountManager.ListSetupKeys(account.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
@ -183,12 +196,23 @@ func (h *SetupKeys) GetAllSetupKeysHandler(w http.ResponseWriter, r *http.Reques
|
|||||||
}
|
}
|
||||||
apiSetupKeys := make([]*api.SetupKey, 0)
|
apiSetupKeys := make([]*api.SetupKey, 0)
|
||||||
for _, key := range setupKeys {
|
for _, key := range setupKeys {
|
||||||
apiSetupKeys = append(apiSetupKeys, toResponseBody(key))
|
k := key.Copy()
|
||||||
|
if !isUserAdmin {
|
||||||
|
k = hideKey(key)
|
||||||
|
}
|
||||||
|
apiSetupKeys = append(apiSetupKeys, toResponseBody(k))
|
||||||
}
|
}
|
||||||
|
|
||||||
writeJSONObject(w, apiSetupKeys)
|
writeJSONObject(w, apiSetupKeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hideKey(key *server.SetupKey) *server.SetupKey {
|
||||||
|
k := key.Copy()
|
||||||
|
prefix := k.Key[0:5]
|
||||||
|
k.Key = prefix + strings.Repeat("*", utf8.RuneCountInString(key.Key)-len(prefix))
|
||||||
|
return k
|
||||||
|
}
|
||||||
|
|
||||||
func writeSuccess(w http.ResponseWriter, key *server.SetupKey) {
|
func writeSuccess(w http.ResponseWriter, key *server.SetupKey) {
|
||||||
w.WriteHeader(200)
|
w.WriteHeader(200)
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
@ -2,6 +2,7 @@ package http
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
@ -159,6 +160,7 @@ func TestSetupKeysHandlers(t *testing.T) {
|
|||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||||
|
req = req.Clone(context.WithValue(context.TODO(), "isAdminUser", true)) //nolint
|
||||||
|
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
router.HandleFunc("/api/setup-keys", handler.GetAllSetupKeysHandler).Methods("GET", "OPTIONS")
|
router.HandleFunc("/api/setup-keys", handler.GetAllSetupKeysHandler).Methods("GET", "OPTIONS")
|
||||||
|
Loading…
Reference in New Issue
Block a user