diff --git a/ekms/cmd/start.go b/ekms/cmd/start.go index 21b6842ec631e8bf8838b929fbad0cc8af7cd97c..3f2ee00d162a9e32263ed351504259fca0d29282 100644 --- a/ekms/cmd/start.go +++ b/ekms/cmd/start.go @@ -108,9 +108,9 @@ var startCmd = &cobra.Command{ handlers := []handler.PathHandler{ system.NewHostnameHandler(), system.NewMemoryHandler(), - system.NewMotdHandler(), system.NewStateHandler(), system.NewSystemHandler(), + danet.NewCreateRouteHandler(ekmsClient), danet.NewKmsHandler(ekmsClient), danet.NewPeerHandler(ekmsClient), danet.NewKeyRoutingSessionHandler(ekmsClient), diff --git a/ekms/etsiqkdnclient/etsi-qkdn-client.go b/ekms/etsiqkdnclient/etsi-qkdn-client.go index 9f4081fa8f157b4a3f249edf8b30ed330d1834c3..9c9e5c191eca9f22ca8b6fc828e6a45fd3553008 100644 --- a/ekms/etsiqkdnclient/etsi-qkdn-client.go +++ b/ekms/etsiqkdnclient/etsi-qkdn-client.go @@ -154,13 +154,13 @@ func NewEkmsClient(config *Config) (myInfo *ekmsInfo) { myInfo.KmsPeerUpdateChannel = make(chan string) log.Printf("%s in regular operations mode", config.Name) - myInfo.kms = emulatedKMS(config, ekmsId, myInfo.KmsPeerUpdateChannel) + myInfo.kms = emulatedKMS(config, ekmsId) return myInfo } // TODO: return an error. -func emulatedKMS(config *Config, id uuid.UUID, peerChannel chan string) *kms.EKMS { +func emulatedKMS(config *Config, id uuid.UUID) *kms.EKMS { // Attach to eKMS emuKMS := kms.NewEKMS(config.Name, id, os.Stdout, log.GetLevel(), false, config.InterComAddr, config.AkmsURL) diff --git a/ekms/handlers/danet/assignForwardingHandler.go b/ekms/handlers/danet/assignForwardingHandler.go index bc0b188101b4503c578ea8a8676062fbe191a6c8..09d74a5d189b5dc306a2e3663998072d0329eb5c 100644 --- a/ekms/handlers/danet/assignForwardingHandler.go +++ b/ekms/handlers/danet/assignForwardingHandler.go @@ -3,6 +3,7 @@ package danet import ( "fmt" + "code.fbi.h-da.de/danet/gnmi-target/handler" "code.fbi.h-da.de/danet/quant/ekms/etsiqkdnclient" "code.fbi.h-da.de/danet/quant/ekms/internal/kms" gnmitargetygot "code.fbi.h-da.de/danet/quant/ekms/model" @@ -13,32 +14,28 @@ import ( // AssignForwardingHandler is the implementation of a gnmitarget.PathHandler. type AssignForwardingHandler struct { - name string - paths map[string]struct{} + handler.DefaultPathHandler ekmsClient etsiqkdnclient.EkmsClient } func NewAssignForwardingHandler(client etsiqkdnclient.EkmsClient) *AssignForwardingHandler { return &AssignForwardingHandler{ - name: "assign-forwarding-handler", - paths: map[string]struct{}{ - "/assign-forwarding": {}, + DefaultPathHandler: handler.DefaultPathHandler{ + Name: "kms-assign-forwarding-handler", + Paths: map[string]struct{}{ + "/assign-forwarding": {}, + }, }, ekmsClient: client, } } -func (yh *AssignForwardingHandler) Name() string { - return yh.name -} - -func (yh *AssignForwardingHandler) Paths() map[string]struct{} { - return yh.paths -} - -func (yh *AssignForwardingHandler) Init(c ygot.ValidatedGoStruct) error { +func (yh *AssignForwardingHandler) Init(config *handler.Config, publishToSubsFunc func([]*gnmi.Notification) error) error { // A initialization is not needed for this handler. The default startup has // no assign forwarding applied. + yh.Config = config + yh.PublishToSubs = publishToSubsFunc + return nil } diff --git a/ekms/handlers/danet/createRouteHandler.go b/ekms/handlers/danet/createRouteHandler.go new file mode 100644 index 0000000000000000000000000000000000000000..2dbf42b7df2cb049d1602b6ee90e87335fac49f3 --- /dev/null +++ b/ekms/handlers/danet/createRouteHandler.go @@ -0,0 +1,133 @@ +package danet + +import ( + "fmt" + + "code.fbi.h-da.de/danet/gnmi-target/handler" + "code.fbi.h-da.de/danet/quant/ekms/etsiqkdnclient" + "code.fbi.h-da.de/danet/quant/ekms/internal/kms/event" + gnmitargetygot "code.fbi.h-da.de/danet/quant/ekms/model" + "github.com/openconfig/gnmi/proto/gnmi" + "github.com/openconfig/ygot/ygot" + log "github.com/sirupsen/logrus" +) + +type CreateRouteHandler struct { + handler.DefaultPathHandler + ekmsClient etsiqkdnclient.EkmsClient + events <-chan event.Event +} + +func NewCreateRouteHandler(client etsiqkdnclient.EkmsClient) *CreateRouteHandler { + return &CreateRouteHandler{ + DefaultPathHandler: handler.DefaultPathHandler{ + Name: "kms-create-route-handler", + Paths: map[string]struct{}{ + "/create-route-requests": {}, + }, + }, + ekmsClient: client, + } +} + +func (yh *CreateRouteHandler) Init(config *handler.Config, publishToSubsFunc func([]*gnmi.Notification) error) error { + yh.Config = config + yh.PublishToSubs = publishToSubsFunc + + var err error + yh.events, err = yh.ekmsClient.Ekms().EventBus().Subscribe(event.CREATE_ROUTE) + if err != nil { + return err + } + + yh.Config.Lock() + defer yh.Config.Unlock() + + copyCurrentConfig, err := ygot.DeepCopy(yh.Config.Data) + if err != nil { + return err + } + + newConfig, ok := copyCurrentConfig.(*gnmitargetygot.Gnmitarget) + if !ok { + return fmt.Errorf("Wrong type, exptected: %T, got: %T", (*gnmitargetygot.OpenconfigInterfaces_Interfaces)(nil), copyCurrentConfig) + } + + newConfig.GetOrCreateCreateRouteRequests() + + //validate struct + if err := newConfig.Validate(); err != nil { + return err + } + + yh.Config.Data = newConfig + + // Start the go routine that takes care of any update from the kms + go func() { + for { + select { + case e := <-yh.events: + log.Println("Update for create route requests.") + + createRouteEvent, ok := e.(*event.CreateRouteEvent) + if !ok { + log.Errorf("Type assertion failed, expected: %T, got: %T", (*event.CreateRouteEvent)(nil), e) + break + } + diff, err := yh.createRouteRequest(createRouteEvent) + if err != nil { + log.Errorf("Error within interface subscription goroutine; %v", err) + break + } + if err := yh.PublishToSubs(diff); err != nil { + log.Errorf("Error within interface subscription goroutine; %v", err) + } + } + } + }() + + return nil +} + +func (yh *CreateRouteHandler) Update(c ygot.ValidatedGoStruct, jobs []*gnmi.Update) error { + return fmt.Errorf("Not implemented") +} + +func (yh *CreateRouteHandler) createRouteRequest(event *event.CreateRouteEvent) ([]*gnmi.Notification, error) { + yh.Config.Lock() + defer yh.Config.Unlock() + + copyCurrentConfig, err := ygot.DeepCopy(yh.Config.Data) + if err != nil { + return nil, err + } + + newConfig, ok := copyCurrentConfig.(*gnmitargetygot.Gnmitarget) + if !ok { + return nil, fmt.Errorf("Wrong type, exptected: %T, got: %T", (*gnmitargetygot.OpenconfigInterfaces_Interfaces)(nil), copyCurrentConfig) + } + + confCreateRouteRequests := newConfig.GetOrCreateCreateRouteRequests() + confCreateRouteRequest, err := confCreateRouteRequests.NewCreateRouteRequest(event.KmsPathId) + if err != nil { + return nil, err + } + + confCreateRouteRequest.KmsPathId = ygot.String(event.KmsPathId) + confCreateRouteRequest.RequestStatus = gnmitargetygot.Temp_CreateRouteRequests_CreateRouteRequest_RequestStatus_PENDING + confCreateRouteRequest.RemoteUkmsId = ygot.String(event.RemoteUkmsId) + + //validate struct + if err := newConfig.Validate(); err != nil { + return nil, err + } + + notifications, err := ygot.DiffWithAtomic(yh.Config.Data, newConfig) + if err != nil { + return nil, err + } + + yh.Config.Data = newConfig + + return notifications, nil +} diff --git a/ekms/handlers/danet/keyRoutingSessionsHandler.go b/ekms/handlers/danet/keyRoutingSessionsHandler.go index 68073274e2289324894cef705fa8a624ef53a815..bd08a217c0900a4abf5d92fd4e045eba7b2654eb 100644 --- a/ekms/handlers/danet/keyRoutingSessionsHandler.go +++ b/ekms/handlers/danet/keyRoutingSessionsHandler.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "code.fbi.h-da.de/danet/gnmi-target/handler" "code.fbi.h-da.de/danet/quant/ekms/etsiqkdnclient" "code.fbi.h-da.de/danet/quant/ekms/internal/kms" "code.fbi.h-da.de/danet/quant/ekms/internal/kms/event" @@ -13,42 +14,27 @@ import ( log "github.com/sirupsen/logrus" ) -type InitiatingKMS struct { - Id string - Address string -} - type KeyRoutingSessionHandler struct { - name string - paths map[string]struct{} + handler.DefaultPathHandler ekmsClient etsiqkdnclient.EkmsClient events <-chan event.Event } func NewKeyRoutingSessionHandler(client etsiqkdnclient.EkmsClient) *KeyRoutingSessionHandler { return &KeyRoutingSessionHandler{ - name: "kms-handler", - paths: map[string]struct{}{ - // TODO:change to right path - "/key-routing-sessions": {}, + DefaultPathHandler: handler.DefaultPathHandler{ + Name: "kms-key-routing-session-handler", + Paths: map[string]struct{}{ + "/key-routing-sessions": {}, + }, }, ekmsClient: client, } } -func (yh *KeyRoutingSessionHandler) Name() string { - return yh.name -} - -func (yh *KeyRoutingSessionHandler) Paths() map[string]struct{} { - return yh.paths -} - -func (yh *KeyRoutingSessionHandler) Init(c ygot.ValidatedGoStruct) error { - config, ok := c.(*gnmitargetygot.Gnmitarget) - if !ok { - return fmt.Errorf("failed type assertion for newConfig %T", (*gnmitargetygot.Gnmitarget)(nil)) - } +func (yh *KeyRoutingSessionHandler) Init(config *handler.Config, publishToSubsFunc func([]*gnmi.Notification) error) error { + yh.Config = config + yh.PublishToSubs = publishToSubsFunc var err error yh.events, err = yh.ekmsClient.Ekms().EventBus().Subscribe(event.ROUTE) @@ -56,11 +42,8 @@ func (yh *KeyRoutingSessionHandler) Init(c ygot.ValidatedGoStruct) error { return err } - // Create ygot structs for the kms - confKeyRoutingSessions := config.GetOrCreateKeyRoutingSessions() - // Fill out the known fields in the ygot structs - err = updateOrCreateKeyRoutingSessions(confKeyRoutingSessions, yh.ekmsClient) + _, err = yh.updateOrCreateKeyRoutingSessions(yh.ekmsClient) if err != nil { return err } @@ -71,8 +54,14 @@ func (yh *KeyRoutingSessionHandler) Init(c ygot.ValidatedGoStruct) error { select { case <-yh.events: log.Println("Update for Routes.") - if err := updateOrCreateKeyRoutingSessions(confKeyRoutingSessions, yh.ekmsClient); err != nil { - log.Println("Error within route update goroutine.") + diff, err := yh.updateOrCreateKeyRoutingSessions(yh.ekmsClient) + if err != nil { + log.Errorf("Error within interface subscription goroutine; %v", err) + // TODO: check again + break + } + if err := yh.PublishToSubs(diff); err != nil { + log.Errorf("Error within interface subscription goroutine; %v", err) } } } @@ -82,7 +71,7 @@ func (yh *KeyRoutingSessionHandler) Init(c ygot.ValidatedGoStruct) error { } func (yh *KeyRoutingSessionHandler) Update(c ygot.ValidatedGoStruct, jobs []*gnmi.Update) error { - fmt.Println("Update request received for ", yh.name) + fmt.Println("Update request received for ", yh.Name) config, ok := c.(*gnmitargetygot.Gnmitarget) if !ok { return fmt.Errorf("failed type assertion for config %T", (*gnmitargetygot.Gnmitarget)(nil)) @@ -133,11 +122,26 @@ func (yh *KeyRoutingSessionHandler) Update(c ygot.ValidatedGoStruct, jobs []*gnm return nil } -func updateOrCreateKeyRoutingSessions(confKMS *gnmitargetygot.Temp_KeyRoutingSessions, ekmsClient etsiqkdnclient.EkmsClient) error { +func (yh *KeyRoutingSessionHandler) updateOrCreateKeyRoutingSessions(ekmsClient etsiqkdnclient.EkmsClient) ([]*gnmi.Notification, error) { + yh.Config.Lock() + defer yh.Config.Unlock() + + copyCurrentConfig, err := ygot.DeepCopy(yh.Config.Data) + if err != nil { + return nil, err + } + + newConfig, ok := copyCurrentConfig.(*gnmitargetygot.Gnmitarget) + if !ok { + return nil, fmt.Errorf("Wrong type, exptected: %T, got: %T", (*gnmitargetygot.OpenconfigInterfaces_Interfaces)(nil), copyCurrentConfig) + } + + confKeyRoutingSessions := newConfig.GetOrCreateKeyRoutingSessions() + ekmsRoutingTable := ekmsClient.Ekms().RoutingTableDeepCopy() for _, route := range ekmsRoutingTable { - confTempRoutingSession := confKMS.GetOrCreateRoutingSessions(route.PathId.String()) + confTempRoutingSession := confKeyRoutingSessions.GetOrCreateRoutingSessions(route.PathId.String()) if route.Previous != nil { confPrevHop := confTempRoutingSession.GetOrCreatePrevHop() @@ -174,5 +178,17 @@ func updateOrCreateKeyRoutingSessions(confKMS *gnmitargetygot.Temp_KeyRoutingSes // TODO: add operation status } - return nil + //validate struct + if err := newConfig.Validate(); err != nil { + return nil, err + } + + notifications, err := ygot.DiffWithAtomic(yh.Config.Data, newConfig) + if err != nil { + return nil, err + } + + yh.Config.Data = newConfig + + return notifications, nil } diff --git a/ekms/handlers/danet/kmsHandler.go b/ekms/handlers/danet/kmsHandler.go index 84735acc099bd03e954fdc9ad267236c7016e489..e8a2e3f05570724e9551d29fae347a04b9abfeb5 100644 --- a/ekms/handlers/danet/kmsHandler.go +++ b/ekms/handlers/danet/kmsHandler.go @@ -3,6 +3,7 @@ package danet import ( "fmt" + "code.fbi.h-da.de/danet/gnmi-target/handler" "code.fbi.h-da.de/danet/quant/ekms/etsiqkdnclient" gnmitargetygot "code.fbi.h-da.de/danet/quant/ekms/model" "github.com/openconfig/gnmi/proto/gnmi" @@ -10,40 +11,28 @@ import ( ) type KmsHandler struct { - name string - paths map[string]struct{} + handler.DefaultPathHandler ekmsClient etsiqkdnclient.EkmsClient } func NewKmsHandler(client etsiqkdnclient.EkmsClient) *KmsHandler { return &KmsHandler{ - name: "kms-handler", - paths: map[string]struct{}{ - "/kms": {}, + DefaultPathHandler: handler.DefaultPathHandler{ + Name: "kms-handler", + Paths: map[string]struct{}{ + "/kms": {}, + }, }, ekmsClient: client, } } -func (yh *KmsHandler) Name() string { - return yh.name -} - -func (yh *KmsHandler) Paths() map[string]struct{} { - return yh.paths -} - -func (yh *KmsHandler) Init(c ygot.ValidatedGoStruct) error { - config, ok := c.(*gnmitargetygot.Gnmitarget) - if !ok { - return fmt.Errorf("failed type assertion for newConfig %T", (*gnmitargetygot.Gnmitarget)(nil)) - } - - // Create ygot structs for the kms - confEkms := config.GetOrCreateKms() +func (yh *KmsHandler) Init(config *handler.Config, publishToSubsFunc func([]*gnmi.Notification) error) error { + yh.Config = config + yh.PublishToSubs = publishToSubsFunc // Fill out the known fields in the ygot structs - err := updateOrCreateKMS(confEkms, yh.ekmsClient) + _, err := yh.updateOrCreateKMS(yh.ekmsClient) if err != nil { return err } @@ -56,7 +45,22 @@ func (yh *KmsHandler) Update(c ygot.ValidatedGoStruct, jobs []*gnmi.Update) erro return nil } -func updateOrCreateKMS(confKMS *gnmitargetygot.Temp_Kms, ekmsClient etsiqkdnclient.EkmsClient) error { +func (yh *KmsHandler) updateOrCreateKMS(ekmsClient etsiqkdnclient.EkmsClient) ([]*gnmi.Notification, error) { + yh.Config.Lock() + defer yh.Config.Unlock() + + copyCurrentConfig, err := ygot.DeepCopy(yh.Config.Data) + if err != nil { + return nil, err + } + + newConfig, ok := copyCurrentConfig.(*gnmitargetygot.Gnmitarget) + if !ok { + return nil, fmt.Errorf("Wrong type, exptected: %T, got: %T", (*gnmitargetygot.OpenconfigInterfaces_Interfaces)(nil), copyCurrentConfig) + } + + confKMS := newConfig.GetOrCreateKms() + confKMS.KmsId = ygot.String(ekmsClient.ID().String()) confVersionInfo := confKMS.GetOrCreateVersionInformation() @@ -64,5 +68,17 @@ func updateOrCreateKMS(confKMS *gnmitargetygot.Temp_Kms, ekmsClient etsiqkdnclie confVersionInfo.HwVersion = ygot.String(ekmsClient.Version().HardwareVersion()) confVersionInfo.SwVersion = ygot.String(ekmsClient.Version().SoftwareVersion()) - return nil + //validate struct + if err := newConfig.Validate(); err != nil { + return nil, err + } + + notifications, err := ygot.DiffWithAtomic(yh.Config.Data, newConfig) + if err != nil { + return nil, err + } + + yh.Config.Data = newConfig + + return notifications, nil } diff --git a/ekms/handlers/danet/peerHandler.go b/ekms/handlers/danet/peerHandler.go index 1a22e2753c53a186f98be3ecc0d230b73df538fb..acf1a87e4e5c43218e2e3a73d6d70511da3a5009 100644 --- a/ekms/handlers/danet/peerHandler.go +++ b/ekms/handlers/danet/peerHandler.go @@ -3,6 +3,7 @@ package danet import ( "fmt" + "code.fbi.h-da.de/danet/gnmi-target/handler" "code.fbi.h-da.de/danet/quant/ekms/etsiqkdnclient" "code.fbi.h-da.de/danet/quant/ekms/internal/kms" "code.fbi.h-da.de/danet/quant/ekms/internal/kms/event" @@ -13,36 +14,26 @@ import ( ) type PeerHandler struct { - name string - paths map[string]struct{} + handler.DefaultPathHandler ekmsClient etsiqkdnclient.EkmsClient events <-chan event.Event } func NewPeerHandler(client etsiqkdnclient.EkmsClient) *PeerHandler { return &PeerHandler{ - name: "kms-handler", - paths: map[string]struct{}{ - // TODO:change to right path - "kms-peers": {}, + DefaultPathHandler: handler.DefaultPathHandler{ + Name: "kms-peer-handler", + Paths: map[string]struct{}{ + "/kms-peers": {}, + }, }, ekmsClient: client, } } -func (yh *PeerHandler) Name() string { - return yh.name -} - -func (yh *PeerHandler) Paths() map[string]struct{} { - return yh.paths -} - -func (yh *PeerHandler) Init(c ygot.ValidatedGoStruct) error { - config, ok := c.(*gnmitargetygot.Gnmitarget) - if !ok { - return fmt.Errorf("failed type assertion for newConfig %T", (*gnmitargetygot.Gnmitarget)(nil)) - } +func (yh *PeerHandler) Init(config *handler.Config, publishToSubsFunc func([]*gnmi.Notification) error) error { + yh.Config = config + yh.PublishToSubs = publishToSubsFunc var err error yh.events, err = yh.ekmsClient.Ekms().EventBus().Subscribe(event.PEER) @@ -50,11 +41,8 @@ func (yh *PeerHandler) Init(c ygot.ValidatedGoStruct) error { return err } - // Create ygot structs for the kms - confPeerTable := config.GetOrCreateKmsPeerTable() - // Fill out the known fields in the ygot structs - err = updateOrCreatePeerTable(confPeerTable, yh.ekmsClient) + _, err = yh.updateOrCreatePeerTable(yh.ekmsClient) if err != nil { return err } @@ -65,8 +53,15 @@ func (yh *PeerHandler) Init(c ygot.ValidatedGoStruct) error { select { case <-yh.events: log.Println("Update for KMSPeer.") - if err := updateOrCreatePeerTable(confPeerTable, yh.ekmsClient); err != nil { - log.Println("Error within kmspeer update goroutine.") + //lock access for model + diff, err := yh.updateOrCreatePeerTable(yh.ekmsClient) + if err != nil { + log.Errorf("Error within interface subscription goroutine; %v", err) + // TODO: check again + break + } + if err := yh.PublishToSubs(diff); err != nil { + log.Errorf("Error within interface subscription goroutine; %v", err) } } } @@ -80,11 +75,27 @@ func (yh *PeerHandler) Update(c ygot.ValidatedGoStruct, jobs []*gnmi.Update) err return nil } -func updateOrCreatePeerTable(confKMS *gnmitargetygot.Temp_KmsPeerTable, ekmsClient etsiqkdnclient.EkmsClient) error { +func (yh *PeerHandler) updateOrCreatePeerTable(ekmsClient etsiqkdnclient.EkmsClient) ([]*gnmi.Notification, error) { + yh.Config.Lock() + defer yh.Config.Unlock() + + copyCurrentConfig, err := ygot.DeepCopy(yh.Config.Data) + if err != nil { + return nil, err + } + + newConfig, ok := copyCurrentConfig.(*gnmitargetygot.Gnmitarget) + if !ok { + return nil, fmt.Errorf("Wrong type, exptected: %T, got: %T", (*gnmitargetygot.OpenconfigInterfaces_Interfaces)(nil), copyCurrentConfig) + } + + // Create ygot structs for the kms + confKmsPeerTable := newConfig.GetOrCreateKmsPeerTable() + kmsPeers := ekmsClient.Ekms().PeersDeepCopy() for _, peer := range kmsPeers { - confTempKmsPeer := confKMS.GetOrCreateKmsPeers(peer.GetKmsPeerId().String()) + confTempKmsPeer := confKmsPeerTable.GetOrCreateKmsPeers(peer.GetKmsPeerId().String()) confTempPeerInformation := confTempKmsPeer.GetOrCreatePeerInformation() confTempPeerAddress := confTempPeerInformation.GetOrCreatePeerAddress() @@ -112,5 +123,17 @@ func updateOrCreatePeerTable(confKMS *gnmitargetygot.Temp_KmsPeerTable, ekmsClie confTempPeerInformation.NegotiatedKeyLength = ygot.Uint64(256) } - return nil + //validate struct + if err := newConfig.Validate(); err != nil { + return nil, err + } + + notifications, err := ygot.DiffWithAtomic(yh.Config.Data, newConfig) + if err != nil { + return nil, err + } + + yh.Config.Data = newConfig + + return notifications, nil } diff --git a/ekms/handlers/system/hostnameHandler.go b/ekms/handlers/system/hostnameHandler.go index e03e5776fa92c793b8812583a06a3f953115b815..461319ce29f8a1a511348a75cda7febd2fe66a74 100644 --- a/ekms/handlers/system/hostnameHandler.go +++ b/ekms/handlers/system/hostnameHandler.go @@ -3,6 +3,7 @@ package system import ( "fmt" + "code.fbi.h-da.de/danet/gnmi-target/handler" gnmitargetygot "code.fbi.h-da.de/danet/quant/ekms/model" "code.fbi.h-da.de/danet/quant/ekms/osclient" "github.com/openconfig/gnmi/proto/gnmi" @@ -12,44 +13,35 @@ import ( // HostnameHandler is the implementation of a gnmitarget.PathHandler. type HostnameHandler struct { - name string - paths map[string]struct{} + handler.DefaultPathHandler osClient osclient.Osclient } func NewHostnameHandler() *HostnameHandler { return &HostnameHandler{ - name: "openconfig-hostname-handler", - paths: map[string]struct{}{ - "/system/config/hostname": {}, + DefaultPathHandler: handler.DefaultPathHandler{ + Name: "openconfig-hostname-handler", + Paths: map[string]struct{}{ + "/system/config/hostname": {}, + }, }, osClient: osclient.NewOsClient(), } } -func (yh *HostnameHandler) Name() string { - return yh.name -} - -func (yh *HostnameHandler) Paths() map[string]struct{} { - return yh.paths -} - -func (yh *HostnameHandler) Init(c ygot.ValidatedGoStruct) error { - config, ok := c.(*gnmitargetygot.Gnmitarget) - if !ok { - return fmt.Errorf("failed type assertion for config %T", (*gnmitargetygot.Gnmitarget)(nil)) - } +func (yh *HostnameHandler) Init(config *handler.Config, publishToSubsFunc func([]*gnmi.Notification) error) error { + yh.Config = config + yh.PublishToSubs = publishToSubsFunc - confSystem := config.GetOrCreateSystem() - if err := updateOrCreateHostname(confSystem, yh.osClient); err != nil { + _, err := yh.updateOrCreateHostname(yh.osClient) + if err != nil { return err } return nil } func (yh *HostnameHandler) Update(c ygot.ValidatedGoStruct, jobs []*gnmi.Update) error { - fmt.Println("Update request received for ", yh.name) + fmt.Println("Update request received for ", yh.Name) config, ok := c.(*gnmitargetygot.Gnmitarget) if !ok { return fmt.Errorf("failed type assertion for config %T", (*gnmitargetygot.Gnmitarget)(nil)) @@ -71,19 +63,41 @@ func (yh *HostnameHandler) Update(c ygot.ValidatedGoStruct, jobs []*gnmi.Update) return nil } -func updateOrCreateHostname(confSystem *gnmitargetygot.OpenconfigSystem_System, os osclient.Osclient) error { +func (yh *HostnameHandler) updateOrCreateHostname(os osclient.Osclient) ([]*gnmi.Notification, error) { + yh.Config.Lock() + defer yh.Config.Unlock() + + copyCurrentConfig, err := ygot.DeepCopy(yh.Config.Data) + if err != nil { + return nil, err + } + + newConfig, ok := copyCurrentConfig.(*gnmitargetygot.Gnmitarget) + if !ok { + return nil, fmt.Errorf("Wrong type, exptected: %T, got: %T", (*gnmitargetygot.OpenconfigInterfaces_Interfaces)(nil), copyCurrentConfig) + } + + confSystem := newConfig.GetOrCreateSystem() + if config := confSystem.GetOrCreateConfig(); config != nil { h, err := os.GetHostname() if err != nil { - return err + return nil, err } config.Hostname = &h } - // validate struct - if err := confSystem.Validate(); err != nil { - return err + //validate struct + if err := newConfig.Validate(); err != nil { + return nil, err } - return nil + notifications, err := ygot.DiffWithAtomic(yh.Config.Data, newConfig) + if err != nil { + return nil, err + } + + yh.Config.Data = newConfig + + return notifications, nil } diff --git a/ekms/handlers/system/memoryHandler.go b/ekms/handlers/system/memoryHandler.go index 5d1b9cc1c8de4325b2476a44228f737cd6e63fc9..adb09b43e396b0c67e39c72f27c30e0fc483f00e 100644 --- a/ekms/handlers/system/memoryHandler.go +++ b/ekms/handlers/system/memoryHandler.go @@ -3,6 +3,7 @@ package system import ( "fmt" + "code.fbi.h-da.de/danet/gnmi-target/handler" gnmitargetygot "code.fbi.h-da.de/danet/quant/ekms/model" "code.fbi.h-da.de/danet/quant/ekms/osclient" "github.com/openconfig/gnmi/proto/gnmi" @@ -11,58 +12,71 @@ import ( // MemoryHandler is the implementation of a gnmitarget.PathHandler. type MemoryHandler struct { - name string - paths map[string]struct{} + handler.DefaultPathHandler osClient osclient.Osclient } func NewMemoryHandler() *MemoryHandler { return &MemoryHandler{ - name: "openconfig-memory-handler", - paths: map[string]struct{}{ - "/system/memory/state": {}, + DefaultPathHandler: handler.DefaultPathHandler{ + Name: "openconfig-memory-handler", + Paths: map[string]struct{}{ + "/system/memory/state": {}, + }, }, osClient: osclient.NewOsClient(), } } -func (yh *MemoryHandler) Name() string { - return yh.name -} - -func (yh *MemoryHandler) Paths() map[string]struct{} { - return yh.paths -} +func (yh *MemoryHandler) Init(config *handler.Config, publishToSubsFunc func([]*gnmi.Notification) error) error { + yh.Config = config + yh.PublishToSubs = publishToSubsFunc -func (yh *MemoryHandler) Init(c ygot.ValidatedGoStruct) error { - config, ok := c.(*gnmitargetygot.Gnmitarget) - if !ok { - return fmt.Errorf("failed type assertion for config %T", (*gnmitargetygot.Gnmitarget)(nil)) - } - - confSystem := config.GetOrCreateSystem() - if err := updateOrCreateMemory(confSystem, yh.osClient); err != nil { + _, err := yh.updateOrCreateMemory(yh.osClient) + if err != nil { return err } return nil } func (yh *MemoryHandler) Update(c ygot.ValidatedGoStruct, jobs []*gnmi.Update) error { - fmt.Println("Update request received for ", yh.name) + fmt.Println("Update request received for ", yh.Name) return nil } -func updateOrCreateMemory(confSystem *gnmitargetygot.OpenconfigSystem_System, os osclient.Osclient) error { +func (yh *MemoryHandler) updateOrCreateMemory(os osclient.Osclient) ([]*gnmi.Notification, error) { + yh.Config.Lock() + defer yh.Config.Unlock() + + copyCurrentConfig, err := ygot.DeepCopy(yh.Config.Data) + if err != nil { + return nil, err + } + + newConfig, ok := copyCurrentConfig.(*gnmitargetygot.Gnmitarget) + if !ok { + return nil, fmt.Errorf("Wrong type, exptected: %T, got: %T", (*gnmitargetygot.OpenconfigInterfaces_Interfaces)(nil), copyCurrentConfig) + } + + confSystem := newConfig.GetOrCreateSystem() + if memory := confSystem.GetOrCreateMemory(); memory != nil { memory.GetOrCreateState().Physical = ygot.Uint64(os.GetTotalMemory()) memory.GetOrCreateState().Free = ygot.Uint64(os.GetFreeMemory()) memory.GetOrCreateState().Used = ygot.Uint64(os.GetUsedMemory()) } - // validate struct - if err := confSystem.Validate(); err != nil { - return err + //validate struct + if err := newConfig.Validate(); err != nil { + return nil, err } - return nil + notifications, err := ygot.DiffWithAtomic(yh.Config.Data, newConfig) + if err != nil { + return nil, err + } + + yh.Config.Data = newConfig + + return notifications, nil } diff --git a/ekms/handlers/system/motdHandler.go b/ekms/handlers/system/motdHandler.go deleted file mode 100644 index 958c290b9b726b5c833e93a87d784ff9791361f2..0000000000000000000000000000000000000000 --- a/ekms/handlers/system/motdHandler.go +++ /dev/null @@ -1,89 +0,0 @@ -package system - -import ( - "fmt" - - gnmitargetygot "code.fbi.h-da.de/danet/quant/ekms/model" - "code.fbi.h-da.de/danet/quant/ekms/osclient" - "github.com/openconfig/gnmi/proto/gnmi" - "github.com/openconfig/ygot/ygot" - "github.com/sirupsen/logrus" -) - -// MotdHandler is the implementation of a gnmitarget.PathHandler. -type MotdHandler struct { - name string - paths map[string]struct{} - osClient osclient.Osclient -} - -func NewMotdHandler() *MotdHandler { - return &MotdHandler{ - name: "openconfig-motd-handler", - paths: map[string]struct{}{ - "/system/config/motd-banner": {}, - }, - osClient: osclient.NewOsClient(), - } -} - -func (yh *MotdHandler) Name() string { - return yh.name -} - -func (yh *MotdHandler) Paths() map[string]struct{} { - return yh.paths -} - -func (yh *MotdHandler) Init(c ygot.ValidatedGoStruct) error { - config, ok := c.(*gnmitargetygot.Gnmitarget) - if !ok { - return fmt.Errorf("failed type assertion for config %T", (*gnmitargetygot.Gnmitarget)(nil)) - } - - confSystem := config.GetOrCreateSystem() - if err := updateOrCreateMotd(confSystem, yh.osClient); err != nil { - return err - } - return nil -} - -func (yh *MotdHandler) Update(c ygot.ValidatedGoStruct, jobs []*gnmi.Update) error { - fmt.Println("Update request received for ", yh.name) - config, ok := c.(*gnmitargetygot.Gnmitarget) - if !ok { - return fmt.Errorf("failed type assertion for config %T", (*gnmitargetygot.Gnmitarget)(nil)) - } - - system := config.GetSystem() - - if system != nil { - if config := system.GetOrCreateConfig(); config != nil { - if motd := config.GetMotdBanner(); motd != "" { - err := yh.osClient.SetMotd(motd) - if err != nil { - logrus.Debug("Failed to set motd banner: ", err) - return err - } - } - } - } - return nil -} - -func updateOrCreateMotd(confSystem *gnmitargetygot.OpenconfigSystem_System, os osclient.Osclient) error { - if config := confSystem.GetOrCreateConfig(); config != nil { - motd, err := os.GetMotd() - if err != nil { - return err - } - config.MotdBanner = ygot.String(motd) - } - - // validate struct - if err := confSystem.Validate(); err != nil { - return err - } - - return nil -} diff --git a/ekms/handlers/system/stateHandler.go b/ekms/handlers/system/stateHandler.go index 81e9973155d92369728914ada2bb48559f1752e2..461a2a5ae8e4ef917f7e6b8a058e4e574f33572a 100644 --- a/ekms/handlers/system/stateHandler.go +++ b/ekms/handlers/system/stateHandler.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "code.fbi.h-da.de/danet/gnmi-target/handler" gnmitargetygot "code.fbi.h-da.de/danet/quant/ekms/model" "code.fbi.h-da.de/danet/quant/ekms/osclient" "github.com/openconfig/gnmi/proto/gnmi" @@ -13,53 +14,59 @@ import ( // StateHandler is the implementation of a gnmitarget.PathHandler. type StateHandler struct { - name string - paths map[string]struct{} + handler.DefaultPathHandler osClient osclient.Osclient } func NewStateHandler() *StateHandler { return &StateHandler{ - name: "openconfig-memory-handler", - paths: map[string]struct{}{ - "/system/state": {}, + DefaultPathHandler: handler.DefaultPathHandler{ + Name: "openconfig-memory-handler", + Paths: map[string]struct{}{ + "/system/state": {}, + }, }, osClient: osclient.NewOsClient(), } } -func (yh *StateHandler) Name() string { - return yh.name -} - -func (yh *StateHandler) Paths() map[string]struct{} { - return yh.paths -} +func (yh *StateHandler) Init(config *handler.Config, publishToSubsFunc func([]*gnmi.Notification) error) error { + yh.Config = config + yh.PublishToSubs = publishToSubsFunc -func (yh *StateHandler) Init(c ygot.ValidatedGoStruct) error { - config, ok := c.(*gnmitargetygot.Gnmitarget) - if !ok { - return fmt.Errorf("failed type assertion for config %T", (*gnmitargetygot.Gnmitarget)(nil)) - } - - confSystem := config.GetOrCreateSystem() - if err := updateOrCreateState(confSystem, yh.osClient); err != nil { + _, err := yh.updateOrCreateState(yh.osClient) + if err != nil { return err } return nil } func (yh *StateHandler) Update(c ygot.ValidatedGoStruct, jobs []*gnmi.Update) error { - fmt.Println("Update request received for ", yh.name) + fmt.Println("Update request received for ", yh.Name) return nil } -func updateOrCreateState(confSystem *gnmitargetygot.OpenconfigSystem_System, os osclient.Osclient) error { +func (yh *StateHandler) updateOrCreateState(os osclient.Osclient) ([]*gnmi.Notification, error) { + yh.Config.Lock() + defer yh.Config.Unlock() + + copyCurrentConfig, err := ygot.DeepCopy(yh.Config.Data) + if err != nil { + return nil, err + } + + newConfig, ok := copyCurrentConfig.(*gnmitargetygot.Gnmitarget) + if !ok { + return nil, fmt.Errorf("Wrong type, exptected: %T, got: %T", (*gnmitargetygot.OpenconfigInterfaces_Interfaces)(nil), copyCurrentConfig) + } + + confSystem := newConfig.GetOrCreateSystem() + if state := confSystem.GetOrCreateState(); state != nil { state.CurrentDatetime = ygot.String(time.Now().Format(time.RFC3339)) bootTime, err := gopshost.BootTime() if err != nil { - return err + return nil, err } state.BootTime = ygot.Uint64(bootTime) @@ -69,10 +76,17 @@ func updateOrCreateState(confSystem *gnmitargetygot.OpenconfigSystem_System, os state.SoftwareVersion = ygot.String(osVersion) } - // validate struct - if err := confSystem.Validate(); err != nil { - return err + //validate struct + if err := newConfig.Validate(); err != nil { + return nil, err } - return nil + notifications, err := ygot.DiffWithAtomic(yh.Config.Data, newConfig) + if err != nil { + return nil, err + } + + yh.Config.Data = newConfig + + return notifications, nil } diff --git a/ekms/handlers/system/systemHandler.go b/ekms/handlers/system/systemHandler.go index 932594bc883e82a124b5fa69ec3ebad489b985ca..69b6eea1a2cf6243abea9bfc4e077d03bf6fe87b 100644 --- a/ekms/handlers/system/systemHandler.go +++ b/ekms/handlers/system/systemHandler.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "code.fbi.h-da.de/danet/gnmi-target/handler" gnmitargetygot "code.fbi.h-da.de/danet/quant/ekms/model" "code.fbi.h-da.de/danet/quant/ekms/osclient" "github.com/openconfig/gnmi/proto/gnmi" @@ -12,52 +13,58 @@ import ( // SystemHandler is the implementation of a gnmitarget.PathHandler. type SystemHandler struct { - name string - paths map[string]struct{} + handler.DefaultPathHandler osClient osclient.Osclient } func NewSystemHandler() *SystemHandler { return &SystemHandler{ - name: "openconfig-system-handler", - paths: map[string]struct{}{ - "/system": {}, + DefaultPathHandler: handler.DefaultPathHandler{ + Name: "openconfig-system-handler", + Paths: map[string]struct{}{ + "/system": {}, + }, }, osClient: osclient.NewOsClient(), } } -func (yh *SystemHandler) Name() string { - return yh.name -} - -func (yh *SystemHandler) Paths() map[string]struct{} { - return yh.paths -} +func (yh *SystemHandler) Init(config *handler.Config, publishToSubsFunc func([]*gnmi.Notification) error) error { + yh.Config = config + yh.PublishToSubs = publishToSubsFunc -func (yh *SystemHandler) Init(c ygot.ValidatedGoStruct) error { - config, ok := c.(*gnmitargetygot.Gnmitarget) - if !ok { - return fmt.Errorf("failed type assertion for config %T", (*gnmitargetygot.Gnmitarget)(nil)) - } - - confSystem := config.GetOrCreateSystem() - if err := updateOrCreateSystem(confSystem, yh.osClient); err != nil { + _, err := yh.updateOrCreateSystem(yh.osClient) + if err != nil { return err } return nil } func (yh *SystemHandler) Update(c ygot.ValidatedGoStruct, jobs []*gnmi.Update) error { - fmt.Println("Update request received for ", yh.name) + fmt.Println("Update request received for ", yh.Name) return nil } -func updateOrCreateSystem(confSystem *gnmitargetygot.OpenconfigSystem_System, os osclient.Osclient) error { +func (yh *SystemHandler) updateOrCreateSystem(os osclient.Osclient) ([]*gnmi.Notification, error) { + yh.Config.Lock() + defer yh.Config.Unlock() + + copyCurrentConfig, err := ygot.DeepCopy(yh.Config.Data) + if err != nil { + return nil, err + } + + newConfig, ok := copyCurrentConfig.(*gnmitargetygot.Gnmitarget) + if !ok { + return nil, fmt.Errorf("Wrong type, exptected: %T, got: %T", (*gnmitargetygot.OpenconfigInterfaces_Interfaces)(nil), copyCurrentConfig) + } + + confSystem := newConfig.GetOrCreateSystem() + if config := confSystem.GetOrCreateConfig(); config != nil { domain, err := os.GetDomainName() if err != nil { - return err + return nil, err } config.DomainName = ygot.String(domain) } @@ -68,10 +75,17 @@ func updateOrCreateSystem(confSystem *gnmitargetygot.OpenconfigSystem_System, os } } - // validate struct - if err := confSystem.Validate(); err != nil { - return err + //validate struct + if err := newConfig.Validate(); err != nil { + return nil, err } - return nil + notifications, err := ygot.DiffWithAtomic(yh.Config.Data, newConfig) + if err != nil { + return nil, err + } + + yh.Config.Data = newConfig + + return notifications, nil } diff --git a/ekms/internal/akmsCkmsServer/akmsCkmsServer.go b/ekms/internal/akmsCkmsServer/akmsCkmsServer.go index 546e3bf0f9755b121b0833e68156ef80dd6e2428..4dc129edf1b0c51fcb432892b7bad287a2c55174 100644 --- a/ekms/internal/akmsCkmsServer/akmsCkmsServer.go +++ b/ekms/internal/akmsCkmsServer/akmsCkmsServer.go @@ -5,6 +5,8 @@ import ( "net/http" "code.fbi.h-da.de/danet/quant/ekms/internal/kms" + "code.fbi.h-da.de/danet/quant/ekms/internal/kms/event" + "github.com/google/uuid" "github.com/sirupsen/logrus" ) @@ -61,13 +63,32 @@ func ksaReqHandler(ekms *kms.EKMS) http.HandlerFunc { logrus.Infof("received KSA key request for receiving CKMS %s, request ID %s, and key properties %v", kmsKeyRequest.ReceivingCKMSID, kmsKeyRequest.RequestID, kmsKeyRequest.KeyProperties) - err = ekms.GenerateAndSendKSAKey(kmsKeyRequest.ReceivingCKMSID, kmsKeyRequest.RequestID, kmsKeyRequest.KeyProperties.Number) + pathId := uuid.New() + + receiverChan, err := ekms.Receiver.RequestReceiverChannel(pathId) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + + err = ekms.EventBus().Publish(event.NewCreateRouteEvent(pathId.String(), kmsKeyRequest.ReceivingCKMSID)) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) - logrus.Errorf("error generating and sending KSA key: %s", err) + logrus.Errorf("Failed sending a create route request: %s", err) return } + go func() { + select { + case <-receiverChan: + err = ekms.GenerateAndSendKSAKey(kmsKeyRequest.ReceivingCKMSID, pathId, kmsKeyRequest.RequestID, kmsKeyRequest.KeyProperties.Number) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + logrus.Errorf("error generating and sending KSA key: %s", err) + return + } + } + }() + logrus.Info("requested all keys") w.WriteHeader(http.StatusNoContent) } diff --git a/ekms/internal/kms/event/bus.go b/ekms/internal/kms/event/bus.go index 301b883b09fa8d71d10cfae043415fc5adad0e80..a1c297ba66d0427dde6e379d8a8b876d469bba46 100644 --- a/ekms/internal/kms/event/bus.go +++ b/ekms/internal/kms/event/bus.go @@ -30,6 +30,7 @@ func (b *EventBus) Subscribe(topic Topic) (<-chan Event, error) { return newSubChan, nil } +// TODO: check the functionality of this method. func (b *EventBus) Publish(event Event) error { subs, ok := b.subscribers[event.Topic()] if !ok { diff --git a/ekms/internal/kms/event/event.go b/ekms/internal/kms/event/event.go index 43b3da591ca433d7931a70679965a56b29384a1d..b99faee99ccabaf0ca246dff53294935ce7961ac 100644 --- a/ekms/internal/kms/event/event.go +++ b/ekms/internal/kms/event/event.go @@ -8,6 +8,7 @@ const ( PEER Topic = iota ROUTE QUANTUM_MODULE + CREATE_ROUTE ) // Event ... @@ -16,6 +17,30 @@ type Event interface { Time() time.Time } +type CreateRouteEvent struct { + EventTopic Topic + Timestamp time.Time + KmsPathId string + RemoteUkmsId string +} + +func NewCreateRouteEvent(kmsPathId, remoteUkmsId string) *CreateRouteEvent { + return &CreateRouteEvent{ + EventTopic: CREATE_ROUTE, + Timestamp: time.Now(), + KmsPathId: kmsPathId, + RemoteUkmsId: remoteUkmsId, + } +} + +func (e *CreateRouteEvent) Topic() Topic { + return e.EventTopic +} + +func (e *CreateRouteEvent) Time() time.Time { + return e.Timestamp +} + type PeerEvent struct { EventTopic Topic Timestamp time.Time diff --git a/ekms/internal/kms/kms.go b/ekms/internal/kms/kms.go index 91325426a39ef6b72fc47f93f7ad2c2d4fe6ea10..8c7157e63aad28fdc8384be7cbc9c560611e1518 100644 --- a/ekms/internal/kms/kms.go +++ b/ekms/internal/kms/kms.go @@ -77,6 +77,7 @@ type EKMS struct { supportedKeyLengths map[BitKeyLength]bool eventBus *event.EventBus ckmsAkmsClient akmsCkmsClient.CkmsAkmsClient + Receiver *Receiver } // Will keep information about the quantum elements that this EKMS is talking to @@ -122,6 +123,9 @@ func NewEKMS(kmsName string, kmsUUID uuid.UUID, logOutput io.Writer, logLevel lo supportedKeyLengths: make(map[BitKeyLength]bool), eventBus: event.NewEventBus(), ckmsAkmsClient: ckmsAkmsClient, + Receiver: &Receiver{ + receivers: make(map[uuid.UUID]chan<- struct{}), + }, } createdEKMS.supportedKeyLengths[BitKeyLen256] = true @@ -271,11 +275,6 @@ func (kms *EKMS) AssignForwardingRoute(pId, pHop, nHop string, remoteKMS *Remote kms.PKStoreMutex.Unlock() } - err = kms.eventBus.Publish(event.NewRouteEvent()) - if err != nil { - log.Error(err) - } - log.Debug("Current PKSTORE: ", kms.PKStore) return nil @@ -323,7 +322,7 @@ func (kms *EKMS) GetRemoteKMS(remoteKMSId string) (*RemoteKMS, error) { } // NOTE: address/remoteid still have to decide. -func (kms *EKMS) GenerateAndSendKSAKey(remoteKMSId string, requestId string, number int) error { +func (kms *EKMS) GenerateAndSendKSAKey(remoteKMSId string, pathId uuid.UUID, requestId string, number int) error { if number < 1 { log.Errorf("number must be positive and at least 1, provided: %d\n", number) return fmt.Errorf("number must be positive and at least 1, provided: %d", number) @@ -336,7 +335,7 @@ func (kms *EKMS) GenerateAndSendKSAKey(remoteKMSId string, requestId string, num return err } - keyId, pk, err := kms.GetRandomItemFromPKStore(remoteKMSId) + pk, err := kms.GetSpecificPK(remoteKMSId, pathId) if err != nil { log.Error(err) return err @@ -393,7 +392,7 @@ func (kms *EKMS) GenerateAndSendKSAKey(remoteKMSId string, requestId string, num ctx = metadata.NewOutgoingContext(ctx, md) defer cancel() _, err = remoteClient.KeyDelivery(ctx, &pbIC.KeyDeliveryRequest{ - KeyId: keyId.String(), + KeyId: pk.Id.String(), RequestId: requestId, KmsId: kms.kmsUUID.String(), // TODO: change if multiple keys are generated diff --git a/ekms/internal/kms/kmsintercom.go b/ekms/internal/kms/kmsintercom.go index 74905be65fad12d6463b53a54a455155bf59d73a..718816d622a2d3f84ffff34995f23f98a261582c 100644 --- a/ekms/internal/kms/kmsintercom.go +++ b/ekms/internal/kms/kmsintercom.go @@ -129,11 +129,11 @@ func (s *kmsTalkerServer) SyncKeyIdsForBulk(ctx context.Context, in *pb.SyncKeyI } eqm.rawBulkKeysMutex.Lock() + defer eqm.rawBulkKeysMutex.Unlock() bulk, ok := eqm.rawBulkKeys[in.GetBulkId()] if !ok { return nil, status.Errorf(codes.Internal, "bulk key with id: %d not found", in.GetBulkId()) } - eqm.rawBulkKeysMutex.Unlock() eqm.keyStore = NewKmsKeyStore(256) _, keyData, err := eqm.KeyChopper(bulk, in.GetKeyId()) @@ -145,18 +145,18 @@ func (s *kmsTalkerServer) SyncKeyIdsForBulk(ctx context.Context, in *pb.SyncKeyI eqm.keyStore.addKey(keyId, key) } - eqm.rawBulkKeysMutex.Lock() delete(eqm.rawBulkKeys, in.GetBulkId()) - eqm.rawBulkKeysMutex.Unlock() // update the peer status to up peer.peerStatus = KmsPeerUp // Send notification about change if peer.eventBus != nil { - err := peer.eventBus.Publish(event.NewPeerEvent(peer.tcpSocketStr)) - if err != nil { - log.Error(err) - } + go func() { + err := peer.eventBus.Publish(event.NewPeerEvent(peer.tcpSocketStr)) + if err != nil { + log.Error(err) + } + }() } return &pb.SyncKeyIdsForBulkResponse{ @@ -259,40 +259,30 @@ func (s *kmsTalkerServer) KeyForwarding(ctx context.Context, in *pb.KeyForwardin keys, ok := s.eKMS.PKStore[route.RemoteKMS.Id] if !ok { s.eKMS.PKStore[route.RemoteKMS.Id] = map[uuid.UUID]*PlatformKey{ - keyID: { + pathId: { Id: keyID, Value: decryptedKey, ProcessId: in.GetProcessId(), }, } } else { - keys[keyID] = &PlatformKey{ + keys[pathId] = &PlatformKey{ Id: keyID, Value: decryptedKey, ProcessId: in.GetProcessId(), } } + // push to channel key received + if err := s.eKMS.Receiver.InformReceiver(pathId); err != nil { + log.Debugf("%s", err) + return nil, status.Errorf(codes.Internal, "%s", err) + } + log.Debug("Current PKSTORE: ", s.eKMS.PKStore) s.eKMS.PKStoreMutex.Unlock() } - //// NOTE: For demo purpose only - //json, err := json.Marshal(KMSInfo{ - // Name: s.eKMS.kmsName, - // EncryptedMessage: in.Payload, - // DecryptedMessage: string(decryptedPayload), - // Key: base64.StdEncoding.EncodeToString(decryptKey.key), - //}) - //if err != nil { - // log.Println("Failed to marshal: ", err) - //} - - //err = sendKmsInfoMessage("http://172.20.10.21:4000/kmsinfo", json) - //if err != nil { - // log.Println("Failed to send KMS info message: ", err) - //} - return &pb.KeyForwardingResponse{Timestamp: time.Now().Unix()}, nil } diff --git a/ekms/internal/kms/module.go b/ekms/internal/kms/module.go index 59efcaa336b6292ec22f67e2ebf71b00b03b0634..212f964d99381e233e7a108ac8e5e27cbfc10c31 100644 --- a/ekms/internal/kms/module.go +++ b/ekms/internal/kms/module.go @@ -121,10 +121,12 @@ func (eqe *EmulatedQuantumModule) Sync() error { eqe.peer.peerStatus = KmsPeerUp // Send notification about change if eqe.peer.eventBus != nil { - err := eqe.peer.eventBus.Publish(event.NewPeerEvent(eqe.peer.tcpSocketStr)) - if err != nil { - log.Error(err) - } + go func() { + err := eqe.peer.eventBus.Publish(event.NewPeerEvent(eqe.peer.tcpSocketStr)) + if err != nil { + log.Error(err) + } + }() } return nil diff --git a/ekms/internal/kms/receiver.go b/ekms/internal/kms/receiver.go new file mode 100644 index 0000000000000000000000000000000000000000..225237272590755fff218a009a7069b470f040ae --- /dev/null +++ b/ekms/internal/kms/receiver.go @@ -0,0 +1,35 @@ +package kms + +import ( + "fmt" + "sync" + + "github.com/google/uuid" +) + +type Receiver struct { + mu sync.RWMutex + receivers map[uuid.UUID]chan<- struct{} +} + +func (r *Receiver) RequestReceiverChannel(pathId uuid.UUID) (<-chan struct{}, error) { + newSubChan := make(chan struct{}) + + r.mu.Lock() + defer r.mu.Unlock() + r.receivers[pathId] = newSubChan + + return newSubChan, nil +} + +func (r *Receiver) InformReceiver(pathId uuid.UUID) error { + r.mu.RLock() + defer r.mu.RUnlock() + + if receiver, ok := r.receivers[pathId]; ok { + receiver <- struct{}{} + } else { + return fmt.Errorf("There are no active subscribers for pathId: %s", pathId) + } + return nil +} diff --git a/go.mod b/go.mod index aa9005ecd10866340040c74c664cd26362b6a143..d4e9c308f2d81695558d0894e784b7d1dd5d2eda 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module code.fbi.h-da.de/danet/quant go 1.22 require ( - code.fbi.h-da.de/danet/gnmi-target v0.0.0-20240216142748-f55e5e2a1800 + code.fbi.h-da.de/danet/gnmi-target v0.0.0-20240402114917-f5441059d9a3 code.fbi.h-da.de/danet/quipsec/gen/go/quipsec v0.0.0-20231207135002-06d40645e073 github.com/google/uuid v1.6.0 github.com/gorilla/mux v1.8.1 diff --git a/go.sum b/go.sum index 6b61406041a7e80a4032088b9b00a422c22ad5c2..5329a27300c8d6bd2bd2f35b9f54d8d56ed9139c 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= code.fbi.h-da.de/danet/gnmi-target v0.0.0-20240216142748-f55e5e2a1800 h1:u2Hj0MBV6oK/FYwIXwju8wb1Qh9b5gKYIZXgWAi2+gY= code.fbi.h-da.de/danet/gnmi-target v0.0.0-20240216142748-f55e5e2a1800/go.mod h1:N1AxQEtUEmr3EscCgl3sDfIYWMfiLloA/+qf2u86uRU= +code.fbi.h-da.de/danet/gnmi-target v0.0.0-20240402114917-f5441059d9a3 h1:dPckYMg+NE2VrlNTRmh4tiIW7R3eE0D6UcSfNfj5wBg= +code.fbi.h-da.de/danet/gnmi-target v0.0.0-20240402114917-f5441059d9a3/go.mod h1:C4IbVg/BycbBXbhFn3JOUjrUk1NZwXybNC4e0bNhFHk= code.fbi.h-da.de/danet/quipsec/gen/go/quipsec v0.0.0-20231207135002-06d40645e073 h1:SFFYqhG0UkPXPnEoX3ZBhyLbn8Rxjxy7hd15BMW+pQo= code.fbi.h-da.de/danet/quipsec/gen/go/quipsec v0.0.0-20231207135002-06d40645e073/go.mod h1:lPCd19Jk8aL5B3xSk+h6y5sziXVPqyCXgO7dILvJFfQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= diff --git a/integration-tests/code/getKSAKeyTest/getKSA_key_test.go b/integration-tests/code/getKSAKeyTest/getKSA_key_test.go index 405796a4d3b4097a717d8c30b4df5937ef98be7a..20db70570cacc26716745348ebe0597c64435e41 100644 --- a/integration-tests/code/getKSAKeyTest/getKSA_key_test.go +++ b/integration-tests/code/getKSAKeyTest/getKSA_key_test.go @@ -4,6 +4,8 @@ import ( "bytes" "encoding/json" "fmt" + "strings" + "io" "net/http" "os" @@ -14,6 +16,12 @@ import ( "github.com/stretchr/testify/assert" ) +type Update struct { + Path string + Value string + JSON string +} + // For log file. type LogFile struct { Source string `json:"source"` @@ -71,17 +79,6 @@ func TestGetKSAKey(t *testing.T) { //nolint:gocyclo logFileURL2 = logFileURL_ENV2 } - output, err := integration_test_utils.GnmicCommand(kms2URL, "set", "--update-path", "key-routing-sessions/routing-sessions[path-id=38e0588b-6a2d-42c9-85a0-887cc877c299]", "--update-file", "../../config/kms/kms_2.json") - if err != nil { - t.Errorf("Error setting routing-session: %s; %s", err, output) - } - output, err = integration_test_utils.GnmicCommand(kms1URL, "set", "--update-path", "key-routing-sessions/routing-sessions[path-id=38e0588b-6a2d-42c9-85a0-887cc877c299]", "--update-file", "../../config/kms/kms_1.json") - if err != nil { - t.Errorf("Error setting routing-session: %s; %s", err, output) - } - - time.Sleep(time.Duration(2) * time.Second) - url := fmt.Sprintf("http://%s/api/v1/keys/ksa_key_req", kms1AkmsURL) data := RequestData{ ReceivingCKMSID: "5e41c291-6121-4335-84f6-41e04b8bdaa2", @@ -111,6 +108,102 @@ func TestGetKSAKey(t *testing.T) { //nolint:gocyclo t.Errorf("Expected status code 204 No Content, but got %d", resp.StatusCode) } + time.Sleep(time.Duration(2) * time.Second) + + output, err := integration_test_utils.GnmicCommand(kms1URL, "get", "--path", "create-route-requests") + if err != nil { + t.Errorf("Error getting create-route-requests: %s; %s", err, output) + } + + output = strings.Split(output, "\"kms-path-id\": \"")[1] + output = strings.Split(output, "\",")[0] + + path := fmt.Sprintf("key-routing-sessions/routing-sessions[path-id=%s]", output) + + config01 := []Update{ + { + Path: path, + JSON: fmt.Sprintf(`{"path-id": "%s"}`, output), + }, + { + Path: fmt.Sprint(path, "/prev-hop"), + JSON: fmt.Sprintf(`{"node-id": "%s"}`, "5e41c291-6121-4335-84f6-41e04b8bdaa2"), + }, + { + Path: fmt.Sprint(path, "/prev-hop"), + JSON: fmt.Sprintf(`{"hostname": "%s"}`, "kms_2"), + }, + { + Path: fmt.Sprint(path, "/prev-hop"), + JSON: fmt.Sprintf(`{"port": %d}`, 50910), + }, + { + Path: fmt.Sprint(path, "/initiating-kms-address"), + JSON: fmt.Sprintf(`{"node-id": "%s"}`, "5e41c291-6121-4335-84f6-41e04b8bdaa2"), + }, + { + Path: fmt.Sprint(path, "/initiating-kms-address"), + JSON: fmt.Sprintf(`{"hostname": "%s"}`, "kms_2"), + }, + { + Path: fmt.Sprint(path, "/initiating-kms-address"), + JSON: fmt.Sprintf(`{"port": %d}`, 50910), + }, + } + + config02 := []Update{ + { + Path: path, + JSON: fmt.Sprintf(`{"path-id": "%s"}`, output), + }, + { + Path: fmt.Sprint(path, "/next-hop"), + JSON: fmt.Sprintf(`{"node-id": "%s"}`, "0ff33c82-7fe1-482b-a0ca-67565806ee4b"), + }, + { + Path: fmt.Sprint(path, "/next-hop"), + JSON: fmt.Sprintf(`{"hostname": "%s"}`, "kms_1"), + }, + { + Path: fmt.Sprint(path, "/next-hop"), + JSON: fmt.Sprintf(`{"port": %d}`, 50910), + }, + { + Path: fmt.Sprint(path, "/initiating-kms-address"), + JSON: fmt.Sprintf(`{"node-id": "%s"}`, "0ff33c82-7fe1-482b-a0ca-67565806ee4b"), + }, + { + Path: fmt.Sprint(path, "/initiating-kms-address"), + JSON: fmt.Sprintf(`{"hostname": "%s"}`, "kms_1"), + }, + { + Path: fmt.Sprint(path, "/initiating-kms-address"), + JSON: fmt.Sprintf(`{"port": %d}`, 50910), + }, + } + + argsKMS1 := []string{"set"} + for _, update := range config01 { + argsKMS1 = append(argsKMS1, "--update-path", update.Path, "--update-value", update.JSON) + } + + argsKMS2 := []string{"set"} + for _, update := range config02 { + argsKMS2 = append(argsKMS2, "--update-path", update.Path, "--update-value", update.JSON) + } + + output, err = integration_test_utils.GnmicCommand(kms1URL, argsKMS1...) + if err != nil { + t.Errorf("Error setting routing-session: %s; %s", err, output) + } + + output, err = integration_test_utils.GnmicCommand(kms2URL, argsKMS2...) + if err != nil { + t.Errorf("Error setting routing-session: %s; %s", err, output) + } + + time.Sleep(time.Duration(2) * time.Second) + // Get logfile of akms resp, err = http.Get("http://" + logFileURL + "/debug/get_log_file") if err != nil {