added comments

This commit is contained in:
Abhishek Kondur 2022-09-29 23:59:18 +05:30
parent b2df99e2c0
commit 677d9fcc8d
6 changed files with 160 additions and 135 deletions

View file

@ -443,19 +443,18 @@ func deleteNetwork(w http.ResponseWriter, r *http.Request) {
return
}
// Deletes the network role from MQ
event := mq.DynSecAction{
Payload: mq.MqDynsecPayload{
Commands: []mq.MqDynSecCmd{
{
Command: mq.DeleteRoleCmd,
RoleName: network,
},
event := mq.MqDynsecPayload{
Commands: []mq.MqDynSecCmd{
{
Command: mq.DeleteRoleCmd,
RoleName: network,
},
},
}
if err := mq.PublishEventToDynSecTopic(event); err != nil {
logger.Log(0, fmt.Sprintf("failed to send DynSec command [%v]: %v",
event.Payload.Commands, err.Error()))
event.Commands, err.Error()))
}
logger.Log(1, r.Header.Get("user"), "deleted network", network)
w.WriteHeader(http.StatusOK)
@ -504,21 +503,20 @@ func createNetwork(w http.ResponseWriter, r *http.Request) {
return
}
// Create Role with acls for the network
event := mq.DynSecAction{
Payload: mq.MqDynsecPayload{
Commands: []mq.MqDynSecCmd{
{
Command: mq.CreateRoleCmd,
RoleName: network.NetID,
Textname: "Network wide role with Acls for nodes",
Acls: mq.FetchNetworkAcls(network.NetID),
},
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.Payload.Commands, err.Error()))
event.Commands, err.Error()))
}
if servercfg.IsClientMode() != "off" {

View file

@ -100,46 +100,46 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
logic.ReturnErrorResponse(response, request, errorResponse)
return
}
event := mq.DynSecAction{
Payload: mq.MqDynsecPayload{
Commands: []mq.MqDynSecCmd{
// creates network role, node 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.CreateRoleCmd,
RoleName: result.Network,
Textname: "Network wide role with Acls for nodes",
Acls: mq.FetchNetworkAcls(result.Network),
},
{
Command: mq.CreateRoleCmd,
RoleName: fmt.Sprintf("%s-%s", "Node", result.ID),
Acls: mq.FetchNodeAcls(result.ID),
Textname: "Role for node " + result.Name,
},
{
Command: mq.CreateClientCmd,
Username: result.ID,
Password: authRequest.Password,
Textname: result.Name,
Roles: []mq.MqDynSecRole{
{
Rolename: fmt.Sprintf("%s-%s", "Node", result.ID),
Priority: -1,
},
{
Rolename: result.Network,
Priority: -1,
},
{
Command: mq.CreateRoleCmd,
RoleName: fmt.Sprintf("%s-%s", "Node", result.ID),
Acls: mq.FetchNodeAcls(result.ID),
Textname: "Role for node " + result.Name,
},
{
Command: mq.CreateClientCmd,
Username: result.ID,
Password: authRequest.Password,
Textname: result.Name,
Roles: []mq.MqDynSecRole{
{
Rolename: fmt.Sprintf("%s-%s", "Node", result.ID),
Priority: -1,
},
{
Rolename: result.Network,
Priority: -1,
},
Groups: make([]mq.MqDynSecGroup, 0),
},
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.Payload.Commands, err.Error()))
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
@ -662,53 +662,51 @@ func createNode(w http.ResponseWriter, r *http.Request) {
return
}
// Delete Any Existing Client with this ID.
event := mq.DynSecAction{
Payload: mq.MqDynsecPayload{
Commands: []mq.MqDynSecCmd{
{
Command: mq.DeleteClientCmd,
Username: node.ID,
},
event := mq.MqDynsecPayload{
Commands: []mq.MqDynSecCmd{
{
Command: mq.DeleteClientCmd,
Username: node.ID,
},
},
}
if err := mq.PublishEventToDynSecTopic(event); err != nil {
logger.Log(0, fmt.Sprintf("failed to send DynSec command [%v]: %v",
event.Payload.Commands, err.Error()))
event.Commands, err.Error()))
}
// Create client for this node in Mq
event = mq.DynSecAction{
Payload: mq.MqDynsecPayload{
Commands: []mq.MqDynSecCmd{
{
Command: mq.CreateRoleCmd,
RoleName: fmt.Sprintf("%s-%s", "Node", node.ID),
Acls: mq.FetchNodeAcls(node.ID),
Textname: "Role for node " + node.Name,
},
{
Command: mq.CreateClientCmd,
Username: node.ID,
Password: nodePassword,
Textname: node.Name,
Roles: []mq.MqDynSecRole{
{
Rolename: fmt.Sprintf("%s-%s", "Node", node.ID),
Priority: -1,
},
{
Rolename: node.Network,
Priority: -1,
},
event = mq.MqDynsecPayload{
Commands: []mq.MqDynSecCmd{
{
Command: mq.CreateRoleCmd,
RoleName: fmt.Sprintf("%s-%s", "Node", node.ID),
Acls: mq.FetchNodeAcls(node.ID),
Textname: "Role for node " + node.Name,
},
{
Command: mq.CreateClientCmd,
Username: node.ID,
Password: nodePassword,
Textname: node.Name,
Roles: []mq.MqDynSecRole{
{
Rolename: fmt.Sprintf("%s-%s", "Node", node.ID),
Priority: -1,
},
{
Rolename: node.Network,
Priority: -1,
},
Groups: make([]mq.MqDynSecGroup, 0),
},
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.Payload.Commands, err.Error()))
event.Commands, err.Error()))
}
response := models.NodeGet{
@ -1046,24 +1044,23 @@ func deleteNode(w http.ResponseWriter, r *http.Request) {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
event := mq.DynSecAction{
Payload: mq.MqDynsecPayload{
Commands: []mq.MqDynSecCmd{
{
Command: mq.DeleteRoleCmd,
RoleName: fmt.Sprintf("%s-%s", "Node", nodeid),
},
{
Command: mq.DeleteClientCmd,
Username: nodeid,
},
// deletes node related role and client
event := mq.MqDynsecPayload{
Commands: []mq.MqDynSecCmd{
{
Command: mq.DeleteRoleCmd,
RoleName: fmt.Sprintf("%s-%s", "Node", nodeid),
},
{
Command: mq.DeleteClientCmd,
Username: nodeid,
},
},
}
if err := mq.PublishEventToDynSecTopic(event); err != nil {
logger.Log(0, fmt.Sprintf("failed to send DynSec command [%v]: %v",
event.Payload.Commands, err.Error()))
event.Commands, err.Error()))
}
logic.ReturnSuccessResponse(w, r, nodeid+" deleted.")
logger.Log(1, r.Header.Get("user"), "Deleted node", nodeid, "from network", params["network"])

View file

@ -18,38 +18,53 @@ import (
"golang.org/x/crypto/pbkdf2"
)
const DynamicSecSubTopic = "$CONTROL/dynamic-security/#"
const DynamicSecPubTopic = "$CONTROL/dynamic-security/v1"
// DynamicSecSubTopic - constant for dynamic security subscription topic
const dynamicSecSubTopic = "$CONTROL/dynamic-security/#"
// DynamicSecPubTopic - constant for dynamic security subscription topic
const dynamicSecPubTopic = "$CONTROL/dynamic-security/v1"
// mq client for admin
var mqAdminClient mqtt.Client
var (
CreateClientCmd = "createClient"
const (
// constant for client command
CreateClientCmd = "createClient"
// constant for disable command
DisableClientCmd = "disableClient"
DeleteClientCmd = "deleteClient"
ModifyClientCmd = "modifyClient"
)
// constant for delete client command
DeleteClientCmd = "deleteClient"
// constant for modify client command
ModifyClientCmd = "modifyClient"
var (
// constant for create role command
CreateRoleCmd = "createRole"
// constant for delete role command
DeleteRoleCmd = "deleteRole"
)
const (
// constant for admin user name
mqAdminUserName = "Netmaker-Admin"
// constant for server user name
mqNetmakerServerUserName = "Netmaker-Server"
// constant for exporter user name
mqExporterUserName = "Netmaker-Exporter"
)
// struct for dynamic security file
type dynJSON struct {
Clients []client `json:"clients"`
Roles []role `json:"roles"`
DefaultAcl defaultAccessAcl `json:"defaultACLAccess"`
}
var (
mqAdminUserName string = "Netmaker-Admin"
mqNetmakerServerUserName string = "Netmaker-Server"
mqExporterUserName string = "Netmaker-Exporter"
)
// struct for client role
type clientRole struct {
Rolename string `json:"rolename"`
}
// struct for MQ client
type client struct {
Username string `json:"username"`
TextName string `json:"textName"`
@ -59,11 +74,13 @@ type client struct {
Roles []clientRole `json:"roles"`
}
// struct for MQ role
type role struct {
Rolename string `json:"rolename"`
Acls []Acl `json:"acls"`
}
// struct for default acls
type defaultAccessAcl struct {
PublishClientSend bool `json:"publishClientSend"`
PublishClientReceive bool `json:"publishClientReceive"`
@ -71,22 +88,19 @@ type defaultAccessAcl struct {
Unsubscribe bool `json:"unsubscribe"`
}
type dynCnf struct {
Clients []client `json:"clients"`
Roles []role `json:"roles"`
DefaultACLAccess defaultAccessAcl `json:"defaultACLAccess"`
}
// MqDynSecGroup - struct for MQ client group
type MqDynSecGroup struct {
Groupname string `json:"groupname"`
Priority int `json:"priority"`
}
// MqDynSecRole - struct for MQ client role
type MqDynSecRole struct {
Rolename string `json:"rolename"`
Priority int `json:"priority"`
}
// Acl - struct for MQ acls
type Acl struct {
AclType string `json:"acltype"`
Topic string `json:"topic"`
@ -94,6 +108,7 @@ type Acl struct {
Allow bool `json:"allow"`
}
// MqDynSecCmd - struct for MQ dynamic security command
type MqDynSecCmd struct {
Command string `json:"command"`
Username string `json:"username"`
@ -107,19 +122,18 @@ type MqDynSecCmd struct {
Roles []MqDynSecRole `json:"roles"`
}
type DynSecAction struct {
Payload MqDynsecPayload
}
// MqDynsecPayload - struct for dynamic security command payload
type MqDynsecPayload struct {
Commands []MqDynSecCmd `json:"commands"`
}
// encodePasswordToPBKDF2 - encodes the given password with PBKDF2 hashing for MQ
func encodePasswordToPBKDF2(password string, salt string, iterations int, keyLength int) string {
binaryEncoded := pbkdf2.Key([]byte(password), []byte(salt), iterations, keyLength, sha512.New)
return base64.StdEncoding.EncodeToString(binaryEncoded)
}
// Configure - configures the dynamic initial configuration for MQ
func Configure() error {
if servercfg.Is_EE {
dynConfig.Clients = append(dynConfig.Clients, exporterMQClient)
@ -155,14 +169,15 @@ func Configure() error {
return os.WriteFile(path, data, 0755)
}
func PublishEventToDynSecTopic(event DynSecAction) error {
// PublishEventToDynSecTopic - publishes the message to dynamic security topic
func PublishEventToDynSecTopic(payload MqDynsecPayload) error {
d, err := json.Marshal(event.Payload)
d, err := json.Marshal(payload)
if err != nil {
return err
}
var connecterr error
if token := mqAdminClient.Publish(DynamicSecPubTopic, 2, false, d); !token.WaitTimeout(MQ_TIMEOUT*time.Second) || token.Error() != nil {
if token := mqAdminClient.Publish(dynamicSecPubTopic, 2, false, d); !token.WaitTimeout(MQ_TIMEOUT*time.Second) || token.Error() != nil {
if token.Error() == nil {
connecterr = errors.New("connect timeout")
} else {
@ -172,6 +187,7 @@ func PublishEventToDynSecTopic(event DynSecAction) error {
return connecterr
}
// watchDynSecTopic - message handler for dynamic security responses
func watchDynSecTopic(client mqtt.Client, msg mqtt.Message) {
logger.Log(1, fmt.Sprintf("----->WatchDynSecTopic Message: %+v", string(msg.Payload())))

View file

@ -10,15 +10,21 @@ import (
"github.com/gravitl/netmaker/servercfg"
)
var (
AdminRole string = "admin"
ServerRole string = "server"
ExporterRole string = "exporter"
const (
// constant for admin role
adminRole = "admin"
// constant for server role
serverRole = "server"
// constant for exporter role
exporterRole = "exporter"
// const for dynamic security file
dynamicSecurityFile = "dynamic-security.json"
)
var (
dynamicSecurityFile = "dynamic-security.json"
dynConfig = dynJSON{
// default configuration of dynamic security
dynConfig = dynJSON{
Clients: []client{
{
Username: mqAdminUserName,
@ -28,7 +34,7 @@ var (
Iterations: 0,
Roles: []clientRole{
{
Rolename: AdminRole,
Rolename: adminRole,
},
},
},
@ -40,14 +46,14 @@ var (
Iterations: 0,
Roles: []clientRole{
{
Rolename: ServerRole,
Rolename: serverRole,
},
},
},
},
Roles: []role{
{
Rolename: AdminRole,
Rolename: adminRole,
Acls: []Acl{
{
AclType: "publishClientSend",
@ -106,7 +112,7 @@ var (
},
},
{
Rolename: ServerRole,
Rolename: serverRole,
Acls: []Acl{
{
AclType: "publishClientSend",
@ -169,12 +175,12 @@ var (
Iterations: 101,
Roles: []clientRole{
{
Rolename: ExporterRole,
Rolename: exporterRole,
},
},
}
exporterMQRole = role{
Rolename: ExporterRole,
Rolename: exporterRole,
Acls: []Acl{
{
AclType: "publishClientReceive",
@ -186,6 +192,7 @@ var (
}
)
// DynListCLientsCmdResp - struct for list clients response from MQ
type DynListCLientsCmdResp struct {
Responses []struct {
Command string `json:"command"`
@ -194,11 +201,13 @@ type DynListCLientsCmdResp struct {
} `json:"responses"`
}
// ListClientsData - struct for list clients data
type ListClientsData struct {
Clients []string `json:"clients"`
TotalCount int `json:"totalCount"`
}
// GetAdminClient - fetches admin client of the MQ
func GetAdminClient() (mqtt.Client, error) {
opts := mqtt.NewClientOptions()
setMqOptions(mqAdminUserName, servercfg.GetMqAdminPassword(), opts)
@ -214,6 +223,7 @@ func GetAdminClient() (mqtt.Client, error) {
return mqclient, connecterr
}
// ListClients - to list all clients in the MQ
func ListClients(client mqtt.Client) (ListClientsData, error) {
respChan := make(chan mqtt.Message, 10)
defer close(respChan)
@ -254,6 +264,7 @@ func ListClients(client mqtt.Client) (ListClientsData, error) {
return resp, errors.New("resp not found")
}
// FetchNetworkAcls - fetches network acls
func FetchNetworkAcls(network string) []Acl {
return []Acl{
{
@ -269,6 +280,7 @@ func FetchNetworkAcls(network string) []Acl {
}
}
// FetchNodeAcls -fetches node acls
func FetchNodeAcls(nodeID string) []Acl {
return []Acl{

View file

@ -22,12 +22,13 @@ var peer_force_send = 0
var mqclient mqtt.Client
// SetUpAdminClient - sets up admin client for the MQ
func SetUpAdminClient() {
opts := mqtt.NewClientOptions()
setMqOptions(mqAdminUserName, servercfg.GetMqAdminPassword(), opts)
mqAdminClient = mqtt.NewClient(opts)
opts.SetOnConnectHandler(func(client mqtt.Client) {
if token := client.Subscribe(DynamicSecSubTopic, 0, mqtt.MessageHandler(watchDynSecTopic)); token.WaitTimeout(MQ_TIMEOUT*time.Second) && token.Error() != nil {
if token := client.Subscribe(dynamicSecSubTopic, 0, mqtt.MessageHandler(watchDynSecTopic)); token.WaitTimeout(MQ_TIMEOUT*time.Second) && token.Error() != nil {
client.Disconnect(240)
logger.Log(0, "Dynamic security client subscription failed")
}

View file

@ -622,6 +622,7 @@ func GetMQServerPort() string {
return port
}
// GetMqAdminPassword - fetches the MQ Admin password
func GetMqAdminPassword() string {
password := ""
if os.Getenv("MQ_ADMIN_PASSWORD") != "" {