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

added hash of public keys to central auth store

This commit is contained in:
postmannen 2022-05-12 06:22:11 +02:00
parent c67acad1e0
commit e9b1829f56
3 changed files with 76 additions and 40 deletions

View file

@ -29,7 +29,7 @@ func newCentralAuth(configuration *Configuration, errorKernel *errorKernel) *cen
} }
type keys struct { type keys struct {
nodePublicKeys *nodePublicKeys NodePublicKeys *nodePublicKeys
nodeNotAckedPublicKeys *nodeNotAckedPublicKeys nodeNotAckedPublicKeys *nodeNotAckedPublicKeys
configuration *Configuration configuration *Configuration
db *bolt.DB db *bolt.DB
@ -41,7 +41,7 @@ type keys struct {
func newKeys(configuration *Configuration, errorKernel *errorKernel) *keys { func newKeys(configuration *Configuration, errorKernel *errorKernel) *keys {
c := keys{ c := keys{
// schema: make(map[Node]map[argsString]signatureBase32), // schema: make(map[Node]map[argsString]signatureBase32),
nodePublicKeys: newNodePublicKeys(configuration), NodePublicKeys: newNodePublicKeys(configuration),
nodeNotAckedPublicKeys: newNodeNotAckedPublicKeys(configuration), nodeNotAckedPublicKeys: newNodeNotAckedPublicKeys(configuration),
configuration: configuration, configuration: configuration,
bucketNamePublicKeys: "publicKeys", bucketNamePublicKeys: "publicKeys",
@ -67,7 +67,7 @@ func newKeys(configuration *Configuration, errorKernel *errorKernel) *keys {
// Only assign from storage to in memory map if the storage contained any values. // Only assign from storage to in memory map if the storage contained any values.
if keys != nil { if keys != nil {
c.nodePublicKeys.KeyMap = keys c.NodePublicKeys.KeyMap = keys
for k, v := range keys { for k, v := range keys {
log.Printf("info: public keys db contains: %v, %v\n", k, []byte(v)) log.Printf("info: public keys db contains: %v, %v\n", k, []byte(v))
} }
@ -90,9 +90,9 @@ func (c *keys) addPublicKey(proc process, msg Message) {
// key for a host. // key for a host.
// Check if a key for the current node already exists in the map. // Check if a key for the current node already exists in the map.
c.nodePublicKeys.mu.Lock() c.NodePublicKeys.mu.Lock()
existingKey, ok := c.nodePublicKeys.KeyMap[msg.FromNode] existingKey, ok := c.NodePublicKeys.KeyMap[msg.FromNode]
c.nodePublicKeys.mu.Unlock() c.NodePublicKeys.mu.Unlock()
if ok && bytes.Equal(existingKey, msg.Data) { if ok && bytes.Equal(existingKey, msg.Data) {
fmt.Printf(" * \nkey value for REGISTERED node %v is the same, doing nothing\n\n", msg.FromNode) fmt.Printf(" * \nkey value for REGISTERED node %v is the same, doing nothing\n\n", msg.FromNode)
@ -116,30 +116,6 @@ func (c *keys) addPublicKey(proc process, msg Message) {
er := fmt.Errorf("info: detected new public key for node: %v. This key will need to be authorized by operator to be allowed into the system", msg.FromNode) er := fmt.Errorf("info: detected new public key for node: %v. This key will need to be authorized by operator to be allowed into the system", msg.FromNode)
fmt.Printf(" * %v\n", er) fmt.Printf(" * %v\n", er)
c.errorKernel.infoSend(proc, msg, er) c.errorKernel.infoSend(proc, msg, er)
// TODO: The below commented code should put used within the REQ handler instead to
// store the real keys into the allowed public keys map.
// Here we should only add new keys to the NotAcked map.
// // New key
// c.nodePublicKeys.KeyMap[msg.FromNode] = msg.Data
// c.nodePublicKeys.mu.Unlock()
//
// // Add key to persistent storage.
// c.dbUpdatePublicKey(string(msg.FromNode), msg.Data)
//
// if ok {
// er := fmt.Errorf("info: updated with new public key for node: %v", msg.FromNode)
// fmt.Printf(" * %v\n", er)
// c.errorKernel.infoSend(proc, msg, er)
// }
// if !ok {
// er := fmt.Errorf("info: added public key for new node: %v", msg.FromNode)
// fmt.Printf(" * %v\n", er)
// c.errorKernel.infoSend(proc, msg, er)
// }
//c.dbDump(c.bucketPublicKeys)
} }
// // dbGetPublicKey will look up and return a specific value if it exists for a key in a bucket in a DB. // // dbGetPublicKey will look up and return a specific value if it exists for a key in a bucket in a DB.
@ -238,6 +214,11 @@ func (c *keys) dbDumpPublicKey() (map[Node][]byte, error) {
type nodePublicKeys struct { type nodePublicKeys struct {
mu sync.RWMutex mu sync.RWMutex
KeyMap map[Node][]byte KeyMap map[Node][]byte
// TODO TOMOROW: implement sorting of KeyMap,
// Hash it and store the result into hash,
// marshal and send the whole nodePublicKeys to the end node.
// We should update the hash when a node is added with the allow key method.
Hash [32]byte
} }
// newNodePublicKeys will return a prepared type of nodePublicKeys. // newNodePublicKeys will return a prepared type of nodePublicKeys.

View file

@ -449,9 +449,9 @@ func (s startup) subREQHello(p process) {
// update the prometheus metrics // update the prometheus metrics
s.server.centralAuth.keys.nodePublicKeys.mu.Lock() s.server.centralAuth.keys.NodePublicKeys.mu.Lock()
mapLen := len(s.server.centralAuth.keys.nodePublicKeys.KeyMap) mapLen := len(s.server.centralAuth.keys.NodePublicKeys.KeyMap)
s.server.centralAuth.keys.nodePublicKeys.mu.Unlock() s.server.centralAuth.keys.NodePublicKeys.mu.Unlock()
s.metrics.promHelloNodesTotal.Set(float64(mapLen)) s.metrics.promHelloNodesTotal.Set(float64(mapLen))
s.metrics.promHelloNodesContactLast.With(prometheus.Labels{"nodeName": string(m.FromNode)}).SetToCurrentTime() s.metrics.promHelloNodesContactLast.With(prometheus.Labels{"nodeName": string(m.FromNode)}).SetToCurrentTime()

View file

@ -36,19 +36,23 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"context" "context"
"crypto/sha256"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"log"
"net/http" "net/http"
"os" "os"
"os/exec" "os/exec"
"path" "path"
"path/filepath" "path/filepath"
"sort"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/fxamacker/cbor/v2"
"github.com/hpcloud/tail" "github.com/hpcloud/tail"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
@ -2060,14 +2064,14 @@ func (m methodREQPublicKeysGet) handler(proc process, message Message, node stri
case <-ctx.Done(): case <-ctx.Done():
// case out := <-outCh: // case out := <-outCh:
case <-outCh: case <-outCh:
proc.centralAuth.keys.nodePublicKeys.mu.Lock() proc.centralAuth.keys.NodePublicKeys.mu.Lock()
// TODO: We should probably create a hash of the current map content, // TODO: We should probably create a hash of the current map content,
// store it alongside the KeyMap, and send both the KeyMap and hash // store it alongside the KeyMap, and send both the KeyMap and hash
// back. We can then later send that hash when asking for keys, compare // back. We can then later send that hash when asking for keys, compare
// it with the current one for the KeyMap, and know if we need to send // it with the current one for the KeyMap, and know if we need to send
// and update back to the node who published the request to here. // and update back to the node who published the request to here.
b, err := json.Marshal(proc.centralAuth.keys.nodePublicKeys.KeyMap) b, err := json.Marshal(proc.centralAuth.keys.NodePublicKeys.KeyMap)
proc.centralAuth.keys.nodePublicKeys.mu.Unlock() proc.centralAuth.keys.NodePublicKeys.mu.Unlock()
if err != nil { if err != nil {
er := fmt.Errorf("error: REQPublicKeysGet, failed to marshal keys map: %v", err) er := fmt.Errorf("error: REQPublicKeysGet, failed to marshal keys map: %v", err)
proc.errorKernel.errSend(proc, message, er) proc.errorKernel.errSend(proc, message, er)
@ -2192,13 +2196,19 @@ func (m methodREQPublicKeysAllow) handler(proc process, message Message, node st
proc.centralAuth.keys.nodeNotAckedPublicKeys.mu.Lock() proc.centralAuth.keys.nodeNotAckedPublicKeys.mu.Lock()
defer proc.centralAuth.keys.nodeNotAckedPublicKeys.mu.Unlock() defer proc.centralAuth.keys.nodeNotAckedPublicKeys.mu.Unlock()
// Range over all the MethodArgs, where each element represents a node to allow,
// and move the node from the notAcked map to the allowed map.
for _, n := range message.MethodArgs { for _, n := range message.MethodArgs {
key, ok := proc.centralAuth.keys.nodeNotAckedPublicKeys.KeyMap[Node(n)] key, ok := proc.centralAuth.keys.nodeNotAckedPublicKeys.KeyMap[Node(n)]
if ok { if ok {
// Store/update the node and public key on the allowed pubKey map.
proc.centralAuth.keys.nodePublicKeys.mu.Lock() func() {
proc.centralAuth.keys.nodePublicKeys.KeyMap[Node(n)] = key proc.centralAuth.keys.NodePublicKeys.mu.Lock()
proc.centralAuth.keys.nodePublicKeys.mu.Unlock() defer proc.centralAuth.keys.NodePublicKeys.mu.Unlock()
// Store/update the node and public key on the allowed pubKey map.
proc.centralAuth.keys.NodePublicKeys.KeyMap[Node(n)] = key
}()
// Add key to persistent storage. // Add key to persistent storage.
proc.centralAuth.keys.dbUpdatePublicKey(string(n), key) proc.centralAuth.keys.dbUpdatePublicKey(string(n), key)
@ -2211,6 +2221,51 @@ func (m methodREQPublicKeysAllow) handler(proc process, message Message, node st
} }
} }
// All new elements are now added, and we can create a new hash
// representing the current keys in the allowed map.
func() {
proc.centralAuth.keys.NodePublicKeys.mu.Lock()
defer proc.centralAuth.keys.NodePublicKeys.mu.Unlock()
type NodesAndKeys struct {
Node Node
Key []byte
}
// Create a slice of all the map keys, and its value.
sortedNodesAndKeys := []NodesAndKeys{}
// Range the map, and add each k/v to the sorted slice, to be sorted later.
for k, v := range proc.centralAuth.keys.NodePublicKeys.KeyMap {
nk := NodesAndKeys{
Node: k,
Key: v,
}
sortedNodesAndKeys = append(sortedNodesAndKeys, nk)
}
// sort the slice based on the node name.
// Sort all the commands.
sort.SliceStable(sortedNodesAndKeys, func(i, j int) bool {
return sortedNodesAndKeys[i].Node < sortedNodesAndKeys[j].Node
})
// Then create a hash based on the sorted slice.
b, err := cbor.Marshal(sortedNodesAndKeys)
if err != nil {
er := fmt.Errorf("error: methodREQPublicKeysAllow, failed to marshal slice, and will not update hash for public keys: %v", err)
proc.errorKernel.errSend(proc, message, er)
log.Printf(" * DEBUG: %v\n", err)
return
}
proc.centralAuth.keys.NodePublicKeys.Hash = sha256.Sum256(b)
}()
} }
}() }()