1
0
Fork 0
mirror of https://github.com/postmannen/ctrl.git synced 2024-12-14 12:37:31 +00:00

initial acl distribution works

This commit is contained in:
postmannen 2022-05-26 07:13:34 +02:00
parent e7ae3d893b
commit 9d71f11145
4 changed files with 122 additions and 15 deletions

View file

@ -4,8 +4,10 @@ import (
"crypto/sha256"
"encoding/json"
"fmt"
"io"
"log"
"os"
"path/filepath"
"sort"
"strings"
"sync"
@ -42,13 +44,17 @@ type accessLists struct {
func newAccessLists(errorKernel *errorKernel, configuration *Configuration) *accessLists {
a := accessLists{
schemaMain: newSchemaMain(),
schemaMain: newSchemaMain(configuration),
schemaGenerated: newSchemaGenerated(),
validator: validator.New(),
errorKernel: errorKernel,
configuration: configuration,
}
// The main acl map gets loaded from disk in the newSchemaMain function, but since that
// function do not have access to the generated map we have to generate it here.
a.generateACLsForAllNodes()
return &a
}
@ -60,17 +66,52 @@ type commandGroup string
// schemaMain is the structure that holds the user editable parts for creating ACL's.
type schemaMain struct {
ACLMap map[Node]map[Node]map[command]struct{}
ACLMapFilePath string
NodeGroupMap map[nodeGroup]map[Node]struct{}
CommandGroupMap map[commandGroup]map[command]struct{}
mu sync.Mutex
}
func newSchemaMain() *schemaMain {
func newSchemaMain(configuration *Configuration) *schemaMain {
s := schemaMain{
ACLMap: make(map[Node]map[Node]map[command]struct{}),
ACLMapFilePath: filepath.Join(configuration.DatabaseFolder, "central_aclmap.txt"),
NodeGroupMap: make(map[nodeGroup]map[Node]struct{}),
CommandGroupMap: make(map[commandGroup]map[command]struct{}),
}
// Load ACLMap from disk if present.
func() {
if _, err := os.Stat(s.ACLMapFilePath); os.IsNotExist(err) {
er := fmt.Errorf("error: newSchemaMain: no file for ACLMap found %v: %v", s.ACLMapFilePath, err)
log.Printf("%v\n", er)
// If no aclmap is present on disk we just return from this
// function without loading any values.
return
}
fh, err := os.Open(s.ACLMapFilePath)
if err != nil {
er := fmt.Errorf("error: newSchemaMain: failed to open file for reading %v: %v", s.ACLMapFilePath, err)
log.Printf("%v\n", er)
}
b, err := io.ReadAll(fh)
if err != nil {
er := fmt.Errorf("error: newSchemaMain: failed to ReadAll file %v: %v", s.ACLMapFilePath, err)
log.Printf("%v\n", er)
}
// Unmarshal the data read from disk.
err = json.Unmarshal(b, &s.ACLMap)
if err != nil {
er := fmt.Errorf("error: newSchemaMain: failed to unmarshal content from file %v: %v", s.ACLMapFilePath, err)
log.Printf("%v\n", er)
}
// Generate the aclGenerated map happens in the function where this function is called.
}()
return &s
}
@ -242,6 +283,27 @@ func (a *accessLists) aclDeleteSource(host Node, source Node) error {
// nodes.
// The result will be written to the schemaGenerated.ACLsToConvert map.
func (a *accessLists) generateACLsForAllNodes() error {
// We first one to save the current main ACLMap.
func() {
fh, err := os.OpenFile(a.schemaMain.ACLMapFilePath, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0600)
if err != nil {
er := fmt.Errorf("error: generateACLsForAllNodes: opening file for writing: %v, err: %v", a.schemaMain.ACLMapFilePath, err)
log.Printf("%v\n", er)
return
}
defer fh.Close()
// a.schemaMain.mu.Lock()
// defer a.schemaMain.mu.Unlock()
enc := json.NewEncoder(fh)
enc.Encode(a.schemaMain.ACLMap)
if err != nil {
er := fmt.Errorf("error: generateACLsForAllNodes: encoding json to file failed: %v, err: %v", a.schemaMain.ACLMapFilePath, err)
log.Printf("%v\n", er)
return
}
}()
a.schemaGenerated.mu.Lock()
defer a.schemaGenerated.mu.Unlock()

View file

@ -178,6 +178,7 @@ func (p *processes) Start(proc process) {
// TODO: Putting the acl publisher here.
// Maybe we should also change the name of the configuration flag to something auth related ?
proc.startup.pubREQAclRequestUpdate(proc)
proc.startup.subREQAclDeliverUpdate(proc)
}
if proc.configuration.IsCentralAuth {
@ -342,7 +343,7 @@ func (s startup) pubREQKeysRequestUpdate(p process) {
// and update with new keys back.
proc.nodeAuth.publicKeys.mu.Lock()
fmt.Printf("\n ----> REQKeysRequestUpdate: sending our current hash: %v\n\n", []byte(proc.nodeAuth.publicKeys.keysAndHash.Hash[:]))
fmt.Printf("\n ----> publisher REQKeysRequestUpdate: sending our current hash: %v\n\n", []byte(proc.nodeAuth.publicKeys.keysAndHash.Hash[:]))
m := Message{
FileName: "publickeysget.log",
@ -397,7 +398,7 @@ func (s startup) pubREQAclRequestUpdate(p process) {
// and update with new keys back.
proc.nodeAuth.nodeAcl.mu.Lock()
fmt.Printf("\n ----> REQKeysRequestUpdate: sending our current hash: %v\n\n", []byte(proc.nodeAuth.nodeAcl.aclAndHash.Hash[:]))
fmt.Printf("\n ----> publisher REQAclRequestUpdate: sending our current hash: %v\n\n", []byte(proc.nodeAuth.nodeAcl.aclAndHash.Hash[:]))
m := Message{
FileName: "aclRequestUpdate.log",
@ -461,6 +462,13 @@ func (s startup) subREQAclRequestUpdate(p process) {
go proc.spawnWorker()
}
func (s startup) subREQAclDeliverUpdate(p process) {
log.Printf("Starting Acl deliver update subscriber: %#v\n", p.node)
sub := newSubject(REQAclDeliverUpdate, string(p.node))
proc := newProcess(p.ctx, s.server, sub, processKindSubscriber, nil)
go proc.spawnWorker()
}
// HERE!
func (s startup) subREQAclAddCommand(p process) {

View file

@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"log"
"github.com/fxamacker/cbor/v2"
)
@ -20,6 +21,11 @@ func (m methodREQAclRequestUpdate) getKind() Event {
// Handler to get all acl's from a central server.
func (m methodREQAclRequestUpdate) handler(proc process, message Message, node string) ([]byte, error) {
inf := fmt.Errorf("<--- subscriber methodREQAclRequestUpdate received from: %v, and the data which is the nodes current acl hash containing: %v", message.FromNode, message.MethodArgs)
proc.errorKernel.logConsoleOnlyIfDebug(inf, proc.configuration)
fmt.Printf("\n --- subscriber methodREQAclRequestUpdate: the message brought to handler : %+v\n", message)
// Get a context with the timeout specified in message.MethodTimeout.
ctx, _ := getContextForMethodTimeout(proc.ctx, message)
@ -47,27 +53,47 @@ func (m methodREQAclRequestUpdate) handler(proc process, message Message, node s
proc.centralAuth.accessLists.schemaGenerated.mu.Lock()
defer proc.centralAuth.accessLists.schemaGenerated.mu.Unlock()
fmt.Printf(" <---- methodREQAclRequestUpdate: received acl hash from NODE=%v, HASH=%v\n", message.FromNode, message.Data)
// DEBUGGING:
{
proc.centralAuth.accessLists.schemaMain.mu.Lock()
fmt.Printf("\n --- DEBUGGING: subscriber methodREQAclRequestUpdate: schemaGenerated contains: %v\n\n", proc.centralAuth.accessLists.schemaGenerated)
fmt.Printf("\n --- DEBUGGING: subscriber methodREQAclRequestUpdate: schemaMain contains: %v\n\n", proc.centralAuth.accessLists.schemaMain)
proc.centralAuth.accessLists.schemaMain.mu.Unlock()
// TODO: PROBLEM: The existing generated acl's are not loaded when starting, or not stored at all.
}
fmt.Printf(" ---- subscriber methodREQAclRequestUpdate: got acl hash from NODE=%v, HASH=%v\n", message.FromNode, message.Data)
// Check if the received hash is the same as the one currently active,
// If it is the same we exit the handler immediately.
hash32 := proc.centralAuth.accessLists.schemaGenerated.GeneratedACLsMap[message.FromNode].Hash
hash := hash32[:]
fmt.Printf("\n ---- subscriber methodREQAclRequestUpdate: on central hash32=%v\n\n", hash32)
if bytes.Equal(hash, message.Data) {
fmt.Printf("\n ------------ NODE AND CENTRAL HAVE EQUAL ACL HASH, NOTHING TO DO, EXITING HANDLER\n\n")
fmt.Printf("\n ---- subscriber methodREQAclRequestUpdate: NODE AND CENTRAL HAVE EQUAL ACL HASH, NOTHING TO DO, EXITING HANDLER\n\n")
return
}
fmt.Printf("\n ------------ NODE AND CENTRAL HAD NOT EQUAL ACL, PREPARING TO SEND NEW VERSION OF Acl\n\n")
fmt.Printf("\n ---- subscriber methodREQAclRequestUpdate: NODE AND CENTRAL HAD NOT EQUAL ACL, PREPARING TO SEND NEW VERSION OF Acl\n\n")
fmt.Printf("\n ----> methodREQAclRequestUpdate: SENDING ACL'S TO NODE=%v\n", message.FromNode)
// Generate JSON for Message.Data
js, err := json.Marshal(proc.centralAuth.accessLists.schemaGenerated.GeneratedACLsMap[message.FromNode])
hdh := HostACLsSerializedWithHash{}
hdh.Data = proc.centralAuth.accessLists.schemaGenerated.GeneratedACLsMap[message.FromNode].Data
fmt.Printf("\n * DEBUGGING: before marshalling, hdh.Data=%v\n", hdh.Data)
hdh.Hash = proc.centralAuth.accessLists.schemaGenerated.GeneratedACLsMap[message.FromNode].Hash
fmt.Printf("\n * DEBUGGING: before marshalling, hdh.Hash=%v\n\n", hdh.Hash)
js, err := json.Marshal(hdh)
if err != nil {
er := fmt.Errorf("error: REQAclRequestUpdate : json marshal failed: %v, message: %v", err, message)
proc.errorKernel.errSend(proc, message, er)
log.Fatalf("%v\n", er)
}
fmt.Printf("\n ----> subscriber methodREQAclRequestUpdate: SENDING ACL'S TO NODE=%v, serializedAndHash=%+v\n", message.FromNode, hdh)
newReplyMessage(proc, message, js)
}()
}
@ -89,6 +115,11 @@ func (m methodREQAclDeliverUpdate) getKind() Event {
// Handler to receive the acls from a central server.
func (m methodREQAclDeliverUpdate) handler(proc process, message Message, node string) ([]byte, error) {
inf := fmt.Errorf("<--- subscriber methodREQAclDeliverUpdate received from: %v, containing: %v", message.FromNode, message.Data)
proc.errorKernel.logConsoleOnlyIfDebug(inf, proc.configuration)
fmt.Printf("\n --- subscriber methodREQAclRequestUpdate: the message received on handler : %+v\n\n", message)
// Get a context with the timeout specified in message.MethodTimeout.
ctx, _ := getContextForMethodTimeout(proc.ctx, message)
@ -120,27 +151,30 @@ func (m methodREQAclDeliverUpdate) handler(proc process, message Message, node s
err := json.Unmarshal(message.Data, &hdh)
if err != nil {
er := fmt.Errorf("error: REQAclDeliverUpdate : json unmarshal failed: %v, message: %v", err, message)
er := fmt.Errorf("error: subscriber REQAclDeliverUpdate : json unmarshal failed: %v, message: %v", err, message)
proc.errorKernel.errSend(proc, message, er)
log.Fatalf("\n * DEBUG: ER: %v\n", er)
}
mapOfFromNodeCommands := make(map[Node]map[command]struct{})
err = cbor.Unmarshal(hdh.Data, &mapOfFromNodeCommands)
if err != nil {
er := fmt.Errorf("error: REQAclDeliverUpdate : json unmarshal failed: %v, message: %v", err, message)
er := fmt.Errorf("error: subscriber REQAclDeliverUpdate : json unmarshal failed: %v, message: %v", err, message)
proc.errorKernel.errSend(proc, message, er)
log.Fatalf("\n * DEBUG: ER: %v\n", er)
}
proc.nodeAuth.nodeAcl.aclAndHash.Hash = hdh.Hash
proc.nodeAuth.nodeAcl.aclAndHash.Acl = mapOfFromNodeCommands
fmt.Printf("\n <---- REQAclDeliverUpdate: after unmarshal, nodeAuth aclAndhash contains: %+v\n\n", proc.nodeAuth.nodeAcl.aclAndHash)
fmt.Printf("\n <---- subscriber REQAclDeliverUpdate: after unmarshal, nodeAuth aclAndhash contains: %+v\n\n", proc.nodeAuth.nodeAcl.aclAndHash)
proc.nodeAuth.nodeAcl.mu.Unlock()
err = proc.nodeAuth.nodeAcl.saveToFile()
if err != nil {
er := fmt.Errorf("error: REQAclDeliverUpdate : save to file failed: %v, message: %v", err, message)
er := fmt.Errorf("error: subscriber REQAclDeliverUpdate : save to file failed: %v, message: %v", err, message)
proc.errorKernel.errSend(proc, message, er)
}
@ -842,6 +876,9 @@ func (m methodREQAclExport) handler(proc process, message Message, node string)
// ---
// TODO: IMPORTANT: We also need to add importing and exporting of the groups to the
// import and export methods.
type methodREQAclImport struct {
event Event
}

View file

@ -117,11 +117,11 @@ func (m methodREQKeysRequestUpdate) handler(proc process, message Message, node
// Check if the received hash is the same as the one currently active,
if bytes.Equal(proc.centralAuth.pki.nodesAcked.keysAndHash.Hash[:], message.Data) {
fmt.Printf("\n ------------ NODE AND CENTRAL HAVE EQUAL KEYS, NOTHING TO DO, EXITING HANDLER\n\n")
fmt.Printf("\n --- methodREQKeysRequestUpdate: NODE AND CENTRAL HAVE EQUAL KEYS, NOTHING TO DO, EXITING HANDLER\n\n")
return
}
fmt.Printf("\n ------------ NODE AND CENTRAL HAD NOT EQUAL KEYS, PREPARING TO SEND NEW VERSION OF KEYS\n\n")
fmt.Printf("\n ------------methodREQKeysRequestUpdate: NODE AND CENTRAL HAD NOT EQUAL KEYS, PREPARING TO SEND NEW VERSION OF KEYS\n\n")
fmt.Printf(" * methodREQKeysRequestUpdate: marshalling new keys and hash to send: map=%v, hash=%v\n\n", proc.centralAuth.pki.nodesAcked.keysAndHash.Keys, proc.centralAuth.pki.nodesAcked.keysAndHash.Hash)