| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 | package logicimport (	"encoding/base64"	"encoding/json"	"errors"	"math/rand"	"time"	"github.com/go-playground/validator/v10"	"github.com/gravitl/netmaker/database"	"github.com/gravitl/netmaker/logger"	"github.com/gravitl/netmaker/models"	"github.com/gravitl/netmaker/servercfg")const (	charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")// CreateAccessKey - create access keyfunc CreateAccessKey(accesskey models.AccessKey, network models.Network) (models.AccessKey, error) {	if accesskey.Name == "" {		accesskey.Name = genKeyName()	}	if accesskey.Value == "" {		accesskey.Value = genKey()	}	if accesskey.Uses == 0 {		accesskey.Uses = 1	}	checkkeys, err := GetKeys(network.NetID)	if err != nil {		return models.AccessKey{}, errors.New("could not retrieve network keys")	}	for _, key := range checkkeys {		if key.Name == accesskey.Name {			return models.AccessKey{}, errors.New("duplicate AccessKey Name")		}	}	privAddr := ""	if network.IsLocal != "" {		privAddr = network.LocalRange	}	netID := network.NetID	commsNetID, err := FetchCommsNetID()	if err != nil {		return models.AccessKey{}, errors.New("could not retrieve comms netid")	}	var accessToken models.AccessToken	s := servercfg.GetServerConfig()	servervals := models.ServerConfig{		GRPCConnString: s.GRPCConnString,		GRPCSSL:        s.GRPCSSL,		CommsNetwork:   commsNetID,	}	accessToken.ServerConfig = servervals	accessToken.ClientConfig.Network = netID	accessToken.ClientConfig.Key = accesskey.Value	accessToken.ClientConfig.LocalRange = privAddr	tokenjson, err := json.Marshal(accessToken)	if err != nil {		return accesskey, err	}	accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(tokenjson))	//validate accesskey	v := validator.New()	err = v.Struct(accesskey)	if err != nil {		for _, e := range err.(validator.ValidationErrors) {			logger.Log(1, "validator", e.Error())		}		return models.AccessKey{}, err	}	network.AccessKeys = append(network.AccessKeys, accesskey)	data, err := json.Marshal(&network)	if err != nil {		return models.AccessKey{}, err	}	if err = database.Insert(network.NetID, string(data), database.NETWORKS_TABLE_NAME); err != nil {		return models.AccessKey{}, err	}	return accesskey, nil}// DeleteKey - deletes a keyfunc DeleteKey(keyname, netname string) error {	network, err := GetParentNetwork(netname)	if err != nil {		return err	}	//basically, turn the list of access keys into the list of access keys before and after the item	//have not done any error handling for if there's like...1 item. I think it works? need to test.	found := false	var updatedKeys []models.AccessKey	for _, currentkey := range network.AccessKeys {		if currentkey.Name == keyname {			found = true		} else {			updatedKeys = append(updatedKeys, currentkey)		}	}	if !found {		return errors.New("key " + keyname + " does not exist")	}	network.AccessKeys = updatedKeys	data, err := json.Marshal(&network)	if err != nil {		return err	}	if err := database.Insert(network.NetID, string(data), database.NETWORKS_TABLE_NAME); err != nil {		return err	}	return nil}// GetKeys - fetches keys for networkfunc GetKeys(net string) ([]models.AccessKey, error) {	record, err := database.FetchRecord(database.NETWORKS_TABLE_NAME, net)	if err != nil {		return []models.AccessKey{}, err	}	network, err := ParseNetwork(record)	if err != nil {		return []models.AccessKey{}, err	}	return network.AccessKeys, nil}// DecrimentKey - decriments key usesfunc DecrimentKey(networkName string, keyvalue string) {	var network models.Network	network, err := GetParentNetwork(networkName)	if err != nil || network.IsComms == "yes" {		return	}	for i := len(network.AccessKeys) - 1; i >= 0; i-- {		currentkey := network.AccessKeys[i]		if currentkey.Value == keyvalue {			network.AccessKeys[i].Uses--			if network.AccessKeys[i].Uses < 1 {				network.AccessKeys = append(network.AccessKeys[:i],					network.AccessKeys[i+1:]...)				break			}		}	}	if newNetworkData, err := json.Marshal(&network); err != nil {		logger.Log(2, "failed to decrement key")		return	} else {		database.Insert(network.NetID, string(newNetworkData), database.NETWORKS_TABLE_NAME)	}}// IsKeyValid - check if key is validfunc IsKeyValid(networkname string, keyvalue string) bool {	network, err := GetParentNetwork(networkname)	if err != nil {		return false	}	accesskeys := network.AccessKeys	if network.IsComms == "yes" {		accesskeys = getAllAccessKeys()	}	var key models.AccessKey	foundkey := false	isvalid := false	for i := len(accesskeys) - 1; i >= 0; i-- {		currentkey := accesskeys[i]		if currentkey.Value == keyvalue {			key = currentkey			foundkey = true		}	}	if foundkey {		if key.Uses > 0 {			isvalid = true		}	}	return isvalid}// RemoveKeySensitiveInfo - remove sensitive key infofunc RemoveKeySensitiveInfo(keys []models.AccessKey) []models.AccessKey {	var returnKeys []models.AccessKey	for _, key := range keys {		key.Value = models.PLACEHOLDER_KEY_TEXT		key.AccessString = models.PLACEHOLDER_TOKEN_TEXT		returnKeys = append(returnKeys, key)	}	return returnKeys}// == private methods ==func genKeyName() string {	var seededRand *rand.Rand = rand.New(		rand.NewSource(time.Now().UnixNano()))	length := 5	b := make([]byte, length)	for i := range b {		b[i] = charset[seededRand.Intn(len(charset))]	}	return "key" + string(b)}func genKey() string {	var seededRand *rand.Rand = rand.New(		rand.NewSource(time.Now().UnixNano()))	length := 16	b := make([]byte, length)	for i := range b {		b[i] = charset[seededRand.Intn(len(charset))]	}	return string(b)}func getAllAccessKeys() []models.AccessKey {	var accesskeys = make([]models.AccessKey, 0)	networks, err := GetNetworks()	if err != nil {		return accesskeys	}	for i := range networks {		accesskeys = append(accesskeys, networks[i].AccessKeys...)	}	return accesskeys}
 |