added tokenization + detokenization

This commit is contained in:
0xdcarns 2023-02-15 16:32:16 -05:00
parent 0e5e34ef0c
commit 71ce2caabd
4 changed files with 159 additions and 8 deletions

View file

@ -29,6 +29,7 @@ var HttpHandlers = []interface{}{
ipHandlers,
loggerHandlers,
hostHandlers,
enrollmentKeyHandlers,
}
// HandleRESTRequests - handles the rest requests

View file

@ -0,0 +1,96 @@
package controller
import (
"encoding/json"
"net/http"
"github.com/gorilla/mux"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/servercfg"
)
func enrollmentKeyHandlers(r *mux.Router) {
r.HandleFunc("/api/v1/enrollment-keys", logic.SecurityCheck(true, http.HandlerFunc(getEnrollmentKeys))).Methods(http.MethodGet)
r.HandleFunc("/api/v1/enrollment-keys/{keyID}", logic.SecurityCheck(true, http.HandlerFunc(deleteEnrollmentKey))).Methods(http.MethodDelete)
r.HandleFunc("/api/v1/host/register", logic.SecurityCheck(true, http.HandlerFunc(handleHostRegister))).Methods(http.MethodPost)
}
// swagger:route GET /api/v1/enrollment-keys enrollmentKeys getEnrollmentKeys
//
// Lists all hosts.
//
// Schemes: https
//
// Security:
// oauth
//
// Responses:
// 200: getEnrollmentKeysSlice
func getEnrollmentKeys(w http.ResponseWriter, r *http.Request) {
currentKeys, err := logic.GetAllEnrollmentKeys()
if err != nil {
logger.Log(0, r.Header.Get("user"), "failed to fetch enrollment keys: ", err.Error())
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
for i := range currentKeys {
if err = logic.Tokenize(currentKeys[i], servercfg.GetServer()); err != nil {
logger.Log(0, r.Header.Get("user"), "failed to get token values for keys:", err.Error())
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
}
// return JSON/API formatted hosts
logger.Log(2, r.Header.Get("user"), "fetched enrollment keys")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(currentKeys)
}
// swagger:route DELETE /api/v1/enrollment-keys/{keyID} enrollmentKeys deleteEnrollmentKey
//
// Deletes a Netclient host from Netmaker server.
//
// Schemes: https
//
// Security:
// oauth
//
// Responses:
// 200: deleteEnrollmentKeyResponse
func deleteEnrollmentKey(w http.ResponseWriter, r *http.Request) {
var params = mux.Vars(r)
keyID := params["keyID"]
err := logic.DeleteEnrollmentKey(keyID)
if err != nil {
logger.Log(0, r.Header.Get("user"), "failed to remove enrollment key: ", err.Error())
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
logger.Log(2, r.Header.Get("user"), "deleted enrollment key", keyID)
w.WriteHeader(http.StatusOK)
}
// swagger:route DELETE /api/v1/enrollment-keys/{keyID} enrollmentKeys deleteEnrollmentKey
//
// Deletes a Netclient host from Netmaker server.
//
// Schemes: https
//
// Security:
// oauth
//
// Responses:
// 200: hostRegisterResponse
func handleHostRegister(w http.ResponseWriter, r *http.Request) {
var params = mux.Vars(r)
keyID := params["keyID"]
err := logic.DeleteEnrollmentKey(keyID)
if err != nil {
logger.Log(0, r.Header.Get("user"), "failed to remove enrollment key: ", err.Error())
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
logger.Log(2, r.Header.Get("user"), "deleted enrollment key", keyID)
w.WriteHeader(http.StatusOK)
}

View file

@ -1,6 +1,7 @@
package logic
import (
b64 "encoding/base64"
"encoding/json"
"errors"
"fmt"
@ -13,15 +14,19 @@ import (
// EnrollmentKeyErrors - struct for holding EnrollmentKey error messages
var EnrollmentKeyErrors = struct {
InvalidCreate error
NoKeyFound error
InvalidKey error
NoUsesRemaining error
InvalidCreate error
NoKeyFound error
InvalidKey error
NoUsesRemaining error
FailedToTokenize error
FailedToDeTokenize error
}{
InvalidCreate: fmt.Errorf("invalid enrollment key created"),
NoKeyFound: fmt.Errorf("no enrollmentkey found"),
InvalidKey: fmt.Errorf("invalid key provided"),
NoUsesRemaining: fmt.Errorf("no uses remaining"),
InvalidCreate: fmt.Errorf("invalid enrollment key created"),
NoKeyFound: fmt.Errorf("no enrollmentkey found"),
InvalidKey: fmt.Errorf("invalid key provided"),
NoUsesRemaining: fmt.Errorf("no uses remaining"),
FailedToTokenize: fmt.Errorf("failed to tokenize"),
FailedToDeTokenize: fmt.Errorf("failed to detokenize"),
}
// CreateEnrollmentKey - creates a new enrollment key in db
@ -109,6 +114,47 @@ func TryToUseEnrollmentKey(k *models.EnrollmentKey) bool {
return false
}
// Tokenize - tokenizes an enrollment key to be used via registration
// and attaches it to the Token field on the struct
func Tokenize(k *models.EnrollmentKey, serverAddr string) error {
if len(serverAddr) == 0 {
return EnrollmentKeyErrors.FailedToTokenize
}
newToken := models.EnrollmentToken{
Server: serverAddr,
Value: k.Value,
}
data, err := json.Marshal(&newToken)
if err != nil {
return err
}
k.Token = b64.StdEncoding.EncodeToString([]byte(data))
return nil
}
// DeTokenize - detokenizes a base64 encoded string
// and finds the associated enrollment key
func DeTokenize(b64Token string) (*models.EnrollmentKey, error) {
if len(b64Token) == 0 {
return nil, EnrollmentKeyErrors.FailedToDeTokenize
}
tokenData, err := b64.StdEncoding.DecodeString(b64Token)
if err != nil {
return nil, err
}
var newToken models.EnrollmentToken
err = json.Unmarshal(tokenData, &newToken)
if err != nil {
return nil, err
}
k, err := GetEnrollmentKey(newToken.Value)
if err != nil {
return nil, err
}
return k, nil
}
// == private ==
// decrementEnrollmentKey - decrements the uses on a key if above 0 remaining

View file

@ -4,6 +4,13 @@ import (
"time"
)
// EnrollmentToken - the tokenized version of an enrollmentkey;
// to be used for host registration
type EnrollmentToken struct {
Server string `json:"value"`
Value string `json:"value"`
}
// EnrollmentKeyLength - the length of an enrollment key
const EnrollmentKeyLength = 32
@ -15,6 +22,7 @@ type EnrollmentKey struct {
Networks []string `json:"networks"`
Unlimited bool `json:"unlimited"`
Tags []string `json:"tags"`
Token string `json:"token,omitempty"` // B64 value of EnrollmentToken
}
// EnrollmentKey.IsValid - checks if the key is still valid to use