netmaker/mq/dynsec_helper.go

498 lines
9.7 KiB
Go
Raw Normal View History

2022-09-30 01:24:41 +08:00
package mq
import (
"encoding/json"
"errors"
"fmt"
"time"
mqtt "github.com/eclipse/paho.mqtt.golang"
"github.com/gravitl/netmaker/servercfg"
)
2022-09-30 02:29:18 +08:00
const (
// constant for admin role
adminRole = "admin"
// constant for server role
serverRole = "server"
// constant for exporter role
exporterRole = "exporter"
2022-09-30 23:29:03 +08:00
// constant for node role
NodeRole = "node"
2023-01-04 12:35:05 +08:00
// HostGenericRole constant for host role
HostGenericRole = "host"
2022-09-30 02:29:18 +08:00
// const for dynamic security file
dynamicSecurityFile = "dynamic-security.json"
)
var (
2022-09-30 02:29:18 +08:00
// default configuration of dynamic security
dynConfigInI = dynJSON{
Clients: []client{
{
Username: mqAdminUserName,
TextName: "netmaker admin user",
Password: "",
Salt: "",
Iterations: 0,
Roles: []clientRole{
{
2022-09-30 02:29:18 +08:00
Rolename: adminRole,
},
},
},
{
Username: mqNetmakerServerUserName,
TextName: "netmaker server user",
Password: "",
Salt: "",
Iterations: 0,
Roles: []clientRole{
{
2022-09-30 02:29:18 +08:00
Rolename: serverRole,
},
},
},
2022-10-21 14:40:12 +08:00
exporterMQClient,
},
Roles: []role{
{
2022-09-30 02:29:18 +08:00
Rolename: adminRole,
2022-09-30 23:29:03 +08:00
Acls: fetchAdminAcls(),
},
{
2022-09-30 02:29:18 +08:00
Rolename: serverRole,
2022-09-30 23:29:03 +08:00
Acls: fetchServerAcls(),
},
{
2023-01-04 12:35:05 +08:00
Rolename: HostGenericRole,
2022-09-30 23:29:03 +08:00
Acls: fetchNodeAcls(),
},
2022-10-21 14:40:12 +08:00
exporterMQRole,
},
DefaultAcl: defaultAccessAcl{
PublishClientSend: false,
PublishClientReceive: true,
Subscribe: false,
Unsubscribe: true,
},
}
exporterMQClient = client{
Username: mqExporterUserName,
TextName: "netmaker metrics exporter",
Password: "",
Salt: "",
Iterations: 101,
Roles: []clientRole{
{
2022-09-30 02:29:18 +08:00
Rolename: exporterRole,
},
},
}
exporterMQRole = role{
2022-09-30 02:29:18 +08:00
Rolename: exporterRole,
2022-09-30 23:29:03 +08:00
Acls: fetchExporterAcls(),
}
)
2022-09-30 02:29:18 +08:00
// DynListCLientsCmdResp - struct for list clients response from MQ
2022-09-30 01:24:41 +08:00
type DynListCLientsCmdResp struct {
Responses []struct {
Command string `json:"command"`
Error string `json:"error"`
Data ListClientsData `json:"data"`
} `json:"responses"`
}
2022-09-30 02:29:18 +08:00
// ListClientsData - struct for list clients data
2022-09-30 01:24:41 +08:00
type ListClientsData struct {
Clients []string `json:"clients"`
TotalCount int `json:"totalCount"`
}
2022-09-30 02:29:18 +08:00
// GetAdminClient - fetches admin client of the MQ
2022-09-30 01:24:41 +08:00
func GetAdminClient() (mqtt.Client, error) {
opts := mqtt.NewClientOptions()
setMqOptions(mqAdminUserName, servercfg.GetMqAdminPassword(), opts)
mqclient := mqtt.NewClient(opts)
var connecterr error
if token := mqclient.Connect(); !token.WaitTimeout(MQ_TIMEOUT*time.Second) || token.Error() != nil {
if token.Error() == nil {
connecterr = errors.New("connect timeout")
} else {
connecterr = token.Error()
}
}
return mqclient, connecterr
}
2022-09-30 02:29:18 +08:00
// ListClients - to list all clients in the MQ
2022-09-30 01:24:41 +08:00
func ListClients(client mqtt.Client) (ListClientsData, error) {
respChan := make(chan mqtt.Message, 10)
defer close(respChan)
command := "listClients"
resp := ListClientsData{}
msg := MqDynsecPayload{
Commands: []MqDynSecCmd{
{
Command: command,
},
},
}
client.Subscribe("$CONTROL/dynamic-security/v1/response", 2, mqtt.MessageHandler(func(c mqtt.Client, m mqtt.Message) {
respChan <- m
}))
defer client.Unsubscribe()
d, _ := json.Marshal(msg)
token := client.Publish("$CONTROL/dynamic-security/v1", 2, true, d)
if !token.WaitTimeout(30) || token.Error() != nil {
var err error
if token.Error() == nil {
err = errors.New("connection timeout")
} else {
err = token.Error()
}
return resp, err
}
for m := range respChan {
msg := DynListCLientsCmdResp{}
json.Unmarshal(m.Payload(), &msg)
for _, mI := range msg.Responses {
if mI.Command == command {
return mI.Data, nil
}
}
}
return resp, errors.New("resp not found")
}
2023-01-04 12:35:05 +08:00
// fetches host related acls
func fetchHostAcls(hostID string) []Acl {
return []Acl{
{
AclType: "publishClientReceive",
Topic: fmt.Sprintf("peers/host/%s/#", hostID),
2023-01-04 12:35:05 +08:00
Priority: -1,
Allow: true,
},
{
AclType: "publishClientReceive",
2023-01-12 00:51:32 +08:00
Topic: fmt.Sprintf("host/update/%s", hostID),
Priority: -1,
Allow: true,
},
2023-01-04 12:35:05 +08:00
}
}
2022-09-30 02:29:18 +08:00
// FetchNetworkAcls - fetches network acls
2022-09-30 01:24:41 +08:00
func FetchNetworkAcls(network string) []Acl {
return []Acl{
{
AclType: "publishClientReceive",
Topic: fmt.Sprintf("update/%s/#", network),
Priority: -1,
Allow: true,
},
{
AclType: "publishClientReceive",
Topic: fmt.Sprintf("peers/%s/#", network),
Priority: -1,
Allow: true,
},
2022-11-18 13:18:28 +08:00
{
AclType: "publishClientReceive",
Topic: fmt.Sprintf("proxy/%s/#", network),
Priority: -1,
Allow: true,
},
{
AclType: "subscribePattern",
Topic: "#",
Priority: -1,
Allow: true,
2022-09-30 01:24:41 +08:00
},
{
AclType: "unsubscribePattern",
Topic: "#",
Priority: -1,
Allow: true,
2022-09-30 01:24:41 +08:00
},
}
}
// 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)
}
2023-01-04 12:37:29 +08:00
func deleteHostRole(hostID string) error {
// Deletes the hostID role from MQ
event := MqDynsecPayload{
Commands: []MqDynSecCmd{
{
Command: DeleteRoleCmd,
RoleName: getHostRoleName(hostID),
},
},
}
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)
}
2023-01-04 12:35:05 +08:00
// creates role for the host with ID.
func createHostRole(hostID string) error {
// Create Role with acls for the host
event := MqDynsecPayload{
Commands: []MqDynSecCmd{
{
Command: CreateRoleCmd,
RoleName: getHostRoleName(hostID),
2023-01-04 22:32:02 +08:00
Textname: "host role with Acls for hosts",
2023-01-04 12:35:05 +08:00
Acls: fetchHostAcls(hostID),
},
},
}
return publishEventToDynSecTopic(event)
}
func getHostRoleName(hostID string) string {
return fmt.Sprintf("host-%s", hostID)
}
2022-09-30 23:29:03 +08:00
// serverAcls - fetches server role related acls
func fetchServerAcls() []Acl {
return []Acl{
{
AclType: "publishClientSend",
Topic: "peers/#",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientSend",
2022-11-18 13:18:28 +08:00
Topic: "proxy/#",
Priority: -1,
Allow: true,
},
2023-01-04 12:35:05 +08:00
{
AclType: "publishClientSend",
Topic: "peers/host/#",
Priority: -1,
Allow: true,
},
2022-11-18 13:18:28 +08:00
{
AclType: "publishClientSend",
2022-09-30 23:29:03 +08:00
Topic: "update/#",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientSend",
Topic: "metrics_exporter",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientReceive",
Topic: "ping/#",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientReceive",
Topic: "update/#",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientReceive",
Topic: "signal/#",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientReceive",
Topic: "metrics/#",
Priority: -1,
Allow: true,
},
{
AclType: "subscribePattern",
Topic: "#",
Priority: -1,
Allow: true,
},
{
AclType: "unsubscribePattern",
Topic: "#",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientReceive",
Topic: "host/update/#",
Priority: -1,
Allow: true,
},
2022-09-30 23:29:03 +08:00
}
}
// fetchNodeAcls - fetches node related acls
func fetchNodeAcls() []Acl {
2022-09-30 22:25:18 +08:00
// keeping node acls generic as of now.
2022-09-30 01:24:41 +08:00
return []Acl{
{
2022-09-30 23:29:03 +08:00
AclType: "publishClientSend",
2022-09-30 22:25:18 +08:00
Topic: "signal/#",
Priority: -1,
Allow: true,
},
{
2022-09-30 23:29:03 +08:00
AclType: "publishClientSend",
2022-09-30 22:25:18 +08:00
Topic: "update/#",
Priority: -1,
Allow: true,
},
{
2022-09-30 23:29:03 +08:00
AclType: "publishClientSend",
2022-09-30 22:25:18 +08:00
Topic: "ping/#",
Priority: -1,
Allow: true,
2022-09-30 01:24:41 +08:00
},
{
2022-09-30 23:29:03 +08:00
AclType: "publishClientSend",
2022-09-30 22:25:18 +08:00
Topic: "metrics/#",
Priority: -1,
Allow: true,
2022-09-30 01:24:41 +08:00
},
{
AclType: "subscribePattern",
Topic: "#",
Priority: -1,
Allow: true,
2022-09-30 01:24:41 +08:00
},
{
AclType: "unsubscribePattern",
Topic: "#",
Priority: -1,
Allow: true,
2022-09-30 01:24:41 +08:00
},
}
}
2022-09-30 23:29:03 +08:00
// fetchExporterAcls - fetch exporter role related acls
func fetchExporterAcls() []Acl {
return []Acl{
{
AclType: "publishClientReceive",
Topic: "metrics_exporter",
Allow: true,
Priority: -1,
},
{
AclType: "subscribePattern",
Topic: "#",
Priority: -1,
Allow: true,
},
{
AclType: "unsubscribePattern",
Topic: "#",
Priority: -1,
Allow: true,
},
}
}
// fetchAdminAcls - fetches admin role related acls
func fetchAdminAcls() []Acl {
return []Acl{
{
AclType: "publishClientSend",
Topic: "$CONTROL/dynamic-security/#",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientReceive",
Topic: "$CONTROL/dynamic-security/#",
Priority: -1,
Allow: true,
},
{
AclType: "subscribePattern",
Topic: "$CONTROL/dynamic-security/#",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientReceive",
Topic: "$SYS/#",
Priority: -1,
Allow: true,
},
{
AclType: "subscribePattern",
Topic: "$SYS/#",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientReceive",
Topic: "#",
Priority: -1,
Allow: true,
},
{
AclType: "subscribePattern",
Topic: "#",
Priority: -1,
Allow: true,
},
{
AclType: "unsubscribePattern",
Topic: "#",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientSend",
Topic: "#",
Priority: -1,
Allow: true,
},
}
}