Merge pull request #1881 from gravitl/story/GRA-842

made mq functions a little easier to read and re-use
This commit is contained in:
dcarns 2022-12-29 00:22:15 -05:00 committed by GitHub
commit eb40a8c262
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 197 additions and 122 deletions

View file

@ -8,6 +8,7 @@ import (
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/mq"
"github.com/gravitl/netmaker/servercfg"
)
@ -84,6 +85,17 @@ func updateHost(w http.ResponseWriter, r *http.Request) {
return
}
newNetworks := logic.GetHostNetworks(newHost.ID.String())
if len(newNetworks) > 0 {
if err = mq.ModifyClient(&mq.MqClient{
ID: currHost.ID.String(),
Text: currHost.Name,
Networks: newNetworks,
}); err != nil {
logger.Log(0, r.Header.Get("user"), "failed to update host networks roles in DynSec:", err.Error())
}
}
apiHostData := newHost.ConvertNMHostToAPI()
logger.Log(2, r.Header.Get("user"), "updated host", newHost.ID.String())
w.WriteHeader(http.StatusOK)
@ -154,12 +166,20 @@ func updateHostNetworks(w http.ResponseWriter, r *http.Request) {
return
}
if err = logic.UpdateHostNetworks(currHost, servercfg.GetServer(), payload.Networks); err != nil {
if err = logic.UpdateHostNetworks(currHost, servercfg.GetServer(), payload.Networks[:]); err != nil {
logger.Log(0, r.Header.Get("user"), "failed to update host networks:", err.Error())
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
if err = mq.ModifyClient(&mq.MqClient{
ID: currHost.ID.String(),
Text: currHost.Name,
Networks: payload.Networks,
}); err != nil {
logger.Log(0, r.Header.Get("user"), "failed to update host networks roles in DynSec:", err.Error())
}
logger.Log(2, r.Header.Get("user"), "updated host networks", currHost.Name)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(payload)

View file

@ -370,20 +370,11 @@ func deleteNetwork(w http.ResponseWriter, r *http.Request) {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, errtype))
return
}
// Deletes the network role from MQ
event := mq.MqDynsecPayload{
Commands: []mq.MqDynSecCmd{
{
Command: mq.DeleteRoleCmd,
RoleName: network,
},
},
if err := mq.DeleteNetworkRole(network); err != nil {
logger.Log(0, fmt.Sprintf("failed to remove network DynSec role: %v", err.Error()))
}
if err := mq.PublishEventToDynSecTopic(event); err != nil {
logger.Log(0, fmt.Sprintf("failed to send DynSec command [%v]: %v",
event.Commands, err.Error()))
}
logger.Log(1, r.Header.Get("user"), "deleted network", network)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode("success")
@ -430,21 +421,10 @@ func createNetwork(w http.ResponseWriter, r *http.Request) {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
// Create Role with acls for the network
event := mq.MqDynsecPayload{
Commands: []mq.MqDynSecCmd{
{
Command: mq.CreateRoleCmd,
RoleName: network.NetID,
Textname: "Network wide role with Acls for nodes",
Acls: mq.FetchNetworkAcls(network.NetID),
},
},
}
if err := mq.PublishEventToDynSecTopic(event); err != nil {
logger.Log(0, fmt.Sprintf("failed to send DynSec command [%v]: %v",
event.Commands, err.Error()))
if err = mq.CreateNetworkRole(network.NetID); err != nil {
logger.Log(0, r.Header.Get("user"), "failed to create network DynSec role:",
err.Error())
}
if err = logic.AddDefaultHostsToNetwork(network.NetID, servercfg.GetServer()); err != nil {

View file

@ -7,6 +7,7 @@ import (
"net/http"
"strings"
"github.com/google/uuid"
"github.com/gorilla/mux"
proxy_models "github.com/gravitl/netclient/nmproxy/models"
"github.com/gravitl/netmaker/database"
@ -113,43 +114,6 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
logic.ReturnErrorResponse(response, request, errorResponse)
return
}
// creates network role,node client (added here to resolve any missing configuration in MQ)
event := mq.MqDynsecPayload{
Commands: []mq.MqDynSecCmd{
{
Command: mq.CreateRoleCmd,
RoleName: result.Network,
Textname: "Network wide role with Acls for nodes",
Acls: mq.FetchNetworkAcls(result.Network),
},
{
Command: mq.CreateClientCmd,
Username: result.HostID.String(),
Password: authRequest.Password,
Textname: host.Name,
Roles: []mq.MqDynSecRole{
{
Rolename: mq.NodeRole,
Priority: -1,
},
{
Rolename: result.Network,
Priority: -1,
},
},
Groups: make([]mq.MqDynSecGroup, 0),
},
},
}
if err := mq.PublishEventToDynSecTopic(event); err != nil {
logger.Log(0, fmt.Sprintf("failed to send DynSec command [%v]: %v",
event.Commands, err.Error()))
errorResponse.Code = http.StatusInternalServerError
errorResponse.Message = fmt.Sprintf("could not create mq client for node [%s]: %v", result.ID, err)
return
}
tokenString, err := logic.CreateJWT(authRequest.ID, authRequest.MacAddress, result.Network)
if tokenString == "" {
@ -182,7 +146,6 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
response.WriteHeader(http.StatusOK)
response.Header().Set("Content-Type", "application/json")
response.Write(successJSONResponse)
}
// auth middleware for api calls from nodes where node is has not yet joined the server (register, join)
@ -606,7 +569,7 @@ func createNode(w http.ResponseWriter, r *http.Request) {
server := servercfg.GetServerInfo()
server.TrafficKey = key
// consume password before hashing for mq client creation
nodePassword := data.Host.HostPass
hostPassword := data.Host.HostPass
data.Node.Server = servercfg.GetServer()
if err := logic.CreateHost(&data.Host); err != nil {
if errors.Is(err, logic.ErrHostExists) {
@ -616,6 +579,18 @@ func createNode(w http.ResponseWriter, r *http.Request) {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
} else {
// Create client for this host in Mq
if err := mq.CreateMqClient(&mq.MqClient{
ID: data.Host.ID.String(),
Text: data.Host.Name,
Password: hostPassword,
Networks: []string{networkName},
}); err != nil {
logger.Log(0, fmt.Sprintf("failed to create DynSec client: %v", err.Error()))
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
}
host, err := logic.GetHost(data.Host.ID.String())
if err != nil {
@ -657,43 +632,6 @@ func createNode(w http.ResponseWriter, r *http.Request) {
return
}
data.Node.Peers = peerUpdate.Peers
// Create client for this host in Mq
event := mq.MqDynsecPayload{
Commands: []mq.MqDynSecCmd{
{ // delete if any client exists already
Command: mq.DeleteClientCmd,
Username: data.Host.ID.String(),
},
{
Command: mq.CreateRoleCmd,
RoleName: networkName,
Textname: "Network wide role with Acls for nodes",
Acls: mq.FetchNetworkAcls(networkName),
},
{
Command: mq.CreateClientCmd,
Username: data.Host.ID.String(),
Password: nodePassword,
Textname: data.Host.Name,
Roles: []mq.MqDynSecRole{
{
Rolename: mq.NodeRole,
Priority: -1,
},
{
Rolename: networkName,
Priority: -1,
},
},
Groups: make([]mq.MqDynSecGroup, 0),
},
},
}
if err := mq.PublishEventToDynSecTopic(event); err != nil {
logger.Log(0, fmt.Sprintf("failed to send DynSec command [%v]: %v",
event.Commands, err.Error()))
}
response := models.NodeJoinResponse{
Node: data.Node,
@ -1110,30 +1048,27 @@ func deleteNode(w http.ResponseWriter, r *http.Request) {
}, &node)
}
if fromNode {
//check if server should be removed from mq
found := false
// check if server should be removed from mq
// err is irrelevent
nodes, _ := logic.GetAllNodes()
var foundNode models.Node
for _, nodetocheck := range nodes {
if nodetocheck.HostID == node.HostID {
found = true
foundNode = nodetocheck
break
}
}
// TODO: Address how to remove host
if !found {
// deletes node related role and client
event := mq.MqDynsecPayload{
Commands: []mq.MqDynSecCmd{
{
Command: mq.DeleteClientCmd,
Username: node.HostID.String(),
},
},
if foundNode.HostID != uuid.Nil {
if err = logic.DissasociateNodeFromHost(&foundNode, host); err == nil {
currNets := logic.GetHostNetworks(host.ID.String())
if len(currNets) > 0 {
mq.ModifyClient(&mq.MqClient{
ID: host.ID.String(),
Text: host.Name,
Networks: currNets,
})
}
if err := mq.PublishEventToDynSecTopic(event); err != nil {
logger.Log(0, fmt.Sprintf("failed to send DynSec command [%v]: %v",
event.Commands, err.Error()))
}
}
}

View file

@ -278,3 +278,20 @@ func AddDefaultHostsToNetwork(network, server string) error {
}
return nil
}
// GetHostNetworks - fetches all the networks
func GetHostNetworks(hostID string) []string {
currHost, err := GetHost(hostID)
if err != nil {
return nil
}
nets := []string{}
for i := range currHost.Nodes {
n, err := GetNodeByID(currHost.Nodes[i])
if err != nil {
return nil
}
nets = append(nets, n.Network)
}
return nets
}

View file

@ -189,8 +189,8 @@ func Configure() error {
return os.WriteFile(path, data, 0755)
}
// PublishEventToDynSecTopic - publishes the message to dynamic security topic
func PublishEventToDynSecTopic(payload MqDynsecPayload) error {
// publishes the message to dynamic security topic
func publishEventToDynSecTopic(payload MqDynsecPayload) error {
d, err := json.Marshal(payload)
if err != nil {

89
mq/dynsec_clients.go Normal file
View file

@ -0,0 +1,89 @@
package mq
// MqClient - type for taking in an MQ client's data
type MqClient struct {
ID string
Text string
Password string
Networks []string
}
// ModifyClient - modifies an existing client's network roles
func ModifyClient(client *MqClient) error {
roles := []MqDynSecRole{
{
Rolename: HostRole,
Priority: -1,
},
}
for i := range client.Networks {
roles = append(roles, MqDynSecRole{
Rolename: client.Networks[i],
Priority: -1,
},
)
}
event := MqDynsecPayload{
Commands: []MqDynSecCmd{
{
Command: ModifyClientCmd,
Username: client.ID,
Textname: client.Text,
Roles: roles,
Groups: make([]MqDynSecGroup, 0),
},
},
}
return publishEventToDynSecTopic(event)
}
// DeleteMqClient - removes a client from the DynSec system
func DeleteMqClient(hostID string) error {
event := MqDynsecPayload{
Commands: []MqDynSecCmd{
{
Command: DeleteClientCmd,
Username: hostID,
},
},
}
return publishEventToDynSecTopic(event)
}
// CreateMqClient - creates an MQ DynSec client
func CreateMqClient(client *MqClient) error {
roles := []MqDynSecRole{
{
Rolename: HostRole,
Priority: -1,
},
}
for i := range client.Networks {
roles = append(roles, MqDynSecRole{
Rolename: client.Networks[i],
Priority: -1,
},
)
}
event := MqDynsecPayload{
Commands: []MqDynSecCmd{
{
Command: CreateClientCmd,
Username: client.ID,
Password: client.Password,
Textname: client.Text,
Roles: roles,
Groups: make([]MqDynSecGroup, 0),
},
},
}
return publishEventToDynSecTopic(event)
}

View file

@ -19,6 +19,8 @@ const (
exporterRole = "exporter"
// constant for node role
NodeRole = "node"
// HostRole constant for host role
HostRole = "host"
// const for dynamic security file
dynamicSecurityFile = "dynamic-security.json"
@ -64,7 +66,7 @@ var (
Acls: fetchServerAcls(),
},
{
Rolename: NodeRole,
Rolename: HostRole,
Acls: fetchNodeAcls(),
},
exporterMQRole,
@ -203,6 +205,38 @@ func FetchNetworkAcls(network string) []Acl {
}
}
// DeleteNetworkRole - deletes a network role from DynSec system
func DeleteNetworkRole(network string) error {
// Deletes the network role from MQ
event := MqDynsecPayload{
Commands: []MqDynSecCmd{
{
Command: DeleteRoleCmd,
RoleName: network,
},
},
}
return publishEventToDynSecTopic(event)
}
// CreateNetworkRole - createss a network role from DynSec system
func CreateNetworkRole(network string) error {
// Create Role with acls for the network
event := MqDynsecPayload{
Commands: []MqDynSecCmd{
{
Command: CreateRoleCmd,
RoleName: network,
Textname: "Network wide role with Acls for nodes",
Acls: FetchNetworkAcls(network),
},
},
}
return publishEventToDynSecTopic(event)
}
// serverAcls - fetches server role related acls
func fetchServerAcls() []Acl {
return []Acl{