From f0a7f35c1cc6759212a6764ae2a17ac612cf6d03 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 8 Jul 2021 11:00:36 -0400 Subject: [PATCH 01/46] add two events - identity connected/disconnected --- DesktopEdge/MainWindow.xaml.cs | 8 ++++++-- service/build.bat | 2 +- service/ziti-tunnel/dto/events.go | 24 +++++++++++++++++------- service/ziti-tunnel/service/ipc.go | 12 ++++++++++-- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index a727ff65..88759abe 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -773,12 +773,16 @@ namespace ZitiDesktopEdge { found.IsEnabled = zid.IsEnabled; found.MFAInfo.IsAuthenticated = !e.Id.MfaNeeded; LoadIdentities(true); - return; } } else if (e.Action == "updated") { //this indicates that all updates have been sent to the UI... wait for 2 seconds then trigger any ui updates needed await Task.Delay(2000); - + } else if (e.Action == "connected") { + //this indicates that all updates have been sent to the UI... wait for 2 seconds then trigger any ui updates needed + await Task.Delay(2000); + } else if (e.Action == "disconnected") { + //this indicates that all updates have been sent to the UI... wait for 2 seconds then trigger any ui updates needed + await Task.Delay(2000); } else { IdentityForgotten(ZitiIdentity.FromClient(e.Id)); } diff --git a/service/build.bat b/service/build.bat index cfaa6cd2..c869a6ae 100644 --- a/service/build.bat +++ b/service/build.bat @@ -19,7 +19,7 @@ REM override the c sdk used in the build - leave blank for the same as specified SET ZITI_SDK_C_BRANCH= REM the number of TCP connections the tunneler sdk can have at any one time SET TCP_MAX_CONNECTIONS=256 -SET WINTUN_DL_URL=https://www.wintun.net/builds/wintun-0.11.zip +SET WINTUN_DL_URL=https://www.wintun.net/builds/wintun-0.12.zip set SVC_ROOT_DIR=%~dp0 set CURDIR=%CD% diff --git a/service/ziti-tunnel/dto/events.go b/service/ziti-tunnel/dto/events.go index e2e43379..a612a8ef 100644 --- a/service/ziti-tunnel/dto/events.go +++ b/service/ziti-tunnel/dto/events.go @@ -17,13 +17,15 @@ package dto const ( - ADDED = "added" - BULK = "bulk" - REMOVED = "removed" - ERROR = "error" - UPDATED = "updated" - CHANGED = "changed" - NORMAL = "Normal" + ADDED = "added" + BULK = "bulk" + REMOVED = "removed" + ERROR = "error" + UPDATED = "updated" + CHANGED = "changed" + NORMAL = "Normal" + CONNECTED = "connected" + DISCONNECTED = "disconnected" SERVICE_OP = "service" BULK_SERVICE_OP = "bulkservice" @@ -60,6 +62,14 @@ var IDENTITY_REMOVED = ActionEvent{ StatusEvent: StatusEvent{Op: IDENTITY_OP}, Action: REMOVED, } +var IDENTITY_CONNECTED = ActionEvent{ + StatusEvent: StatusEvent{Op: IDENTITY_OP}, + Action: CONNECTED, +} +var IDENTITY_DISCONNECTED = ActionEvent{ + StatusEvent: StatusEvent{Op: IDENTITY_OP}, + Action: DISCONNECTED, +} var LOGLEVEL_CHANGED = ActionEvent{ StatusEvent: StatusEvent{Op: LOGLEVEL_OP}, Action: CHANGED, diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 7126d5b4..2b7cd53f 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -931,6 +931,10 @@ func connectIdentity(id *Id) { if id.CId == nil || !id.CId.Loaded { rts.LoadIdentity(id, DEFAULT_REFRESH_INTERVAL) + rts.BroadcastEvent(dto.IdentityEvent{ + ActionEvent: dto.IDENTITY_ADDED, + Id: id.Identity, + }) } else { log.Debugf("%s[%s] is already loaded", id.Name, id.FingerPrint) @@ -940,7 +944,7 @@ func connectIdentity(id *Id) { }) rts.BroadcastEvent(dto.IdentityEvent{ - ActionEvent: dto.IDENTITY_ADDED, + ActionEvent: dto.IDENTITY_CONNECTED, Id: id.Identity, }) log.Infof("connecting identity completed: %s[%s] %t/%t", id.Name, id.FingerPrint, id.MfaEnabled, id.MfaNeeded) @@ -968,6 +972,10 @@ func disconnectIdentity(id *Id) error { wg.Wait() return true }) + rts.BroadcastEvent(dto.IdentityEvent{ + ActionEvent: dto.IDENTITY_DISCONNECTED, + Id: id.Identity, + }) log.Infof("disconnecting identity complete: %s", id.Name) } } else { @@ -1118,7 +1126,7 @@ func Clean(src *Id) dto.Identity { mfaEnabled = src.CId.MfaEnabled } - log.Tracef("cleaning identity: %s", src.Name, mfaNeeded, mfaEnabled) + log.Tracef("cleaning identity: %s: mfaNeeded: %t mfaEnabled:%t", src.Name, mfaNeeded, mfaEnabled) AddMetrics(src) nid := dto.Identity{ Name: src.Name, From 945d09b9a8cc367ac9d34c737718c4dc270b2e89 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 8 Jul 2021 11:02:45 -0400 Subject: [PATCH 02/46] add release note --- release-notes.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/release-notes.md b/release-notes.md index 4b6ac18c..394e875a 100644 --- a/release-notes.md +++ b/release-notes.md @@ -1,3 +1,18 @@ +# Release 1.9.10 + +## What's New +* none + +## Other changes: +* none + +## Bugs fixed: +* none + +## Dependency Updates +* wintun updated to 0.12 + + # Release 1.9.9 ## What's New From f52e4c47b7a25a26b1d42f93582d3f9a9538e84e Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 8 Jul 2021 16:01:40 -0400 Subject: [PATCH 03/46] fix crash when the response indicates it had no queries - user hit this issue today --- service/cziti/dns-proxy.go | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/service/cziti/dns-proxy.go b/service/cziti/dns-proxy.go index 1209e975..fbc948c0 100644 --- a/service/cziti/dns-proxy.go +++ b/service/cziti/dns-proxy.go @@ -57,7 +57,7 @@ func processDNSquery(packet []byte, p *net.UDPAddr, s *net.UDPConn, ipVer int) { query = q.Question[0] log.Tracef("processing a dns query. type:%s, for:%s on %v. id:%v", dns.Type(query.Qtype), query.Name, p, q.Id) } else { - log.Warnf("DNS MSG had no question! %v", msg.String()) + log.Warnf("discarding dns message as it contained no question! %v", msg.String()) return } @@ -378,7 +378,11 @@ outer: for k, r := range reqs { if now.After(r.exp) { log.Debugf("a DNS request has expired - enable trace logging and reproduce this issue for more information") - log.Tracef("expired DNS req: %s %s", dns.Type(r.req.Question[0].Qtype), r.req.Question[0].Name) + if len(r.req.Question) > 1 { + log.Tracef("expired DNS req: %s %s", dns.Type(r.req.Question[0].Qtype), r.req.Question[0].Name) + } else { + log.Tracef("expired DNS req - had no question???") + } delete(reqs, k) } @@ -399,7 +403,7 @@ outer: case rep := <-respChan: reply := dns.Msg{} if err := reply.Unpack(rep); err == nil { - id := (uint32(reply.Id) << 16) | uint32(reply.Question[0].Qtype) + id := calcDnsId(&reply) dnsReqMutex.Lock() req, found := reqs[id] if found { @@ -428,7 +432,7 @@ outer: log.Debug("Upstream DNS proxy loop begins") for { pr := <-proxiedRequests - id := (uint32(pr.req.Id) << 16) | uint32(pr.req.Question[0].Qtype) + id := calcDnsId(pr.req) dnsReqMutex.Lock() reqs[id] = pr dnsReqMutex.Unlock() @@ -450,6 +454,13 @@ outer: log.Tracef("Proxied request sent to %v from ipv%d listener", proxy.RemoteAddr(), pr.ipVer) } } - + } +} + +func calcDnsId(req *dns.Msg) uint32 { + if len(req.Question) > 0 { + return (uint32(req.Id) << 16) | uint32(req.Question[0].Qtype) + } else { + return 0 //this shouldn't be happening - yet a user hit this situation } } From e5f1428efa52344c8cfef5544d77b5b78d7f0136 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Fri, 9 Jul 2021 14:45:17 +0530 Subject: [PATCH 04/46] initial commit for windows power events in tunnel --- service/cziti/mfa.go | 31 ++++++++++++++++++++--- service/cziti/sdk.go | 35 ++++++++++++++++++++++++-- service/ziti-tunnel/service/ipc.go | 26 ++++++++++++++++--- service/ziti-tunnel/service/service.go | 4 ++- service/ziti-tunnel/service/types.go | 4 +++ 5 files changed, 91 insertions(+), 9 deletions(-) diff --git a/service/cziti/mfa.go b/service/cziti/mfa.go index ee8ab036..6c211875 100644 --- a/service/cziti/mfa.go +++ b/service/cziti/mfa.go @@ -47,7 +47,8 @@ type mfaCodes struct { var emptyCodes []string var mfaAuthResults = make(chan string) -//export ziti_aq_mfa_cb_go +//export +/* func ziti_aq_mfa_cb_go(ztx C.ziti_context, mfa_ctx unsafe.Pointer, aq_mfa *C.ziti_auth_query_mfa, response_cb C.ziti_ar_mfa_cb) { appCtx := C.ziti_app_ctx(ztx) if appCtx != C.NULL { @@ -61,11 +62,30 @@ func ziti_aq_mfa_cb_go(ztx C.ziti_context, mfa_ctx unsafe.Pointer, aq_mfa *C.zit zid.mfa = mfa zid.MfaNeeded = true zid.MfaEnabled = true + + if zid.Fingerprint != "" { + var id = dto.Identity{ + Name: zid.Name, + FingerPrint: zid.Fingerprint, + Active: zid.Active, + ControllerVersion: zid.Version, + Status: "", + MfaNeeded: true, + MfaEnabled: true, + Tags: nil, + } + + var m = dto.IdentityEvent{ + ActionEvent: dto.IDENTITY_ADDED, + Id: id, + } + goapi.BroadcastEvent(m) + } log.Debugf("mfa enabled/needed set to true for ziti context [%p]. Identity name:%s [fingerprint: %s]", zid, zid.Name, zid.Fingerprint) } else { log.Debugf("mfa requested for ziti context/mfa context [%p, %p] but the context was NOT found in the map. This is unexpected. Please report.", ztx, mfa_ctx) } -} +}*/ func EnableMFA(id *ZIdentity) { C.ziti_mfa_enroll(id.czctx, C.ziti_mfa_cb(C.ziti_mfa_enroll_cb_go), unsafe.Pointer(C.CString(id.Fingerprint))) @@ -104,7 +124,7 @@ func VerifyMFA(id *ZIdentity, code string) { defer C.free(unsafe.Pointer(ccode)) log.Tracef("verifying MFA for fingerprint: %s using code: %s", id.Fingerprint, code) - C.ziti_mfa_verify(id.czctx, ccode, C.ziti_mfa_cb(C.ziti_mfa_cb_verify_go), unsafe.Pointer(C.CString(id.Fingerprint))) + C.ziti_mfa_auth(id.czctx, ccode, C.ziti_mfa_cb(C.ziti_mfa_cb_verify_go), unsafe.Pointer(C.CString(id.Fingerprint))) } //export ziti_mfa_cb_verify_go @@ -314,3 +334,8 @@ func ziti_mfa_cb_remove_go(_ C.ziti_context, status C.int, cFingerprint *C.char) log.Debugf("sending ziti_mfa_verify response back to UI for %s. verified: %t. error: %s", fp, m.Successful, m.Error) goapi.BroadcastEvent(m) } + +func EndpointStateChanged(id *ZIdentity, woken bool, unlocked bool) { + C.ziti_endpoint_state_change(id.czctx, woken, unlocked) + log.Debugf("Endpoint status changed - woken %t, unlocked %t", woken, unlocked) +} diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 2f116a56..3f16f68b 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -531,6 +531,37 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { } else { BulkServiceChanges <- svcChange } + case C.ZitiMfaAuthEvent: + log.Debugf("mfa requested for ziti context.") + zid := (*ZIdentity)(appCtx) + /*mfa := &Mfa{ + mfaContext: mfa_ctx, + authQuery: aq_mfa, + responseCb: response_cb, + } + zid.mfa = mfa*/ + zid.MfaNeeded = true + zid.MfaEnabled = true + + if zid.Fingerprint != "" { + var id = dto.Identity{ + Name: zid.Name, + FingerPrint: zid.Fingerprint, + Active: zid.Active, + ControllerVersion: zid.Version, + Status: "", + MfaNeeded: true, + MfaEnabled: true, + Tags: nil, + } + + var m = dto.IdentityEvent{ + ActionEvent: dto.IDENTITY_ADDED, + Id: id, + } + goapi.BroadcastEvent(m) + } + log.Debugf("mfa enabled/needed set to true for ziti context [%p]. Identity name:%s [fingerprint: %s]", zid, zid.Name, zid.Fingerprint) default: log.Infof("event %d not handled", event._type) } @@ -576,10 +607,10 @@ func LoadZiti(zid *ZIdentity, cfg string, refreshInterval int) { zid.Options.pq_os_cb = C.ziti_pq_os_cb(C.ziti_pq_os_go) zid.Options.pq_process_cb = C.ziti_pq_process_cb(C.ziti_pq_process_go) - zid.Options.events = C.ZitiContextEvent | C.ZitiServiceEvent | C.ZitiRouterEvent + zid.Options.events = C.ZitiContextEvent | C.ZitiServiceEvent | C.ZitiRouterEvent | C.ZitiMfaAuthEvent zid.Options.event_cb = C.ziti_event_cb(C.eventCB) - zid.Options.aq_mfa_cb = C.ziti_aq_mfa_cb(C.ziti_aq_mfa_cb_go) + // zid.Options.aq_mfa_cb = C.ziti_aq_mfa_cb(C.ziti_aq_mfa_cb_go) ptr := unsafe.Pointer(zid) zid.Options.app_ctx = ptr diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 7126d5b4..436d2ad1 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -62,7 +62,7 @@ func (p *Pipes) Close() { var shutdown = make(chan bool, 8) //a channel informing go routines to exit -func SubMain(ops chan string, changes chan<- svc.Status) error { +func SubMain(ops chan string, changes chan<- svc.Status, winEvents <-chan WindowsEvents) error { log.Info("============================== service begins ==============================") windns.RemoveAllNrptRules() // cleanup old ziti tun profiles @@ -82,6 +82,7 @@ func SubMain(ops chan string, changes chan<- svc.Status) error { // a channel to signal the handleEvents that initialization is complete initialized := make(chan struct{}) + shutdownDelay := make(chan bool) // initialize the network interface err := initialize(cLogLevel) @@ -101,6 +102,26 @@ func SubMain(ops chan string, changes chan<- svc.Status) error { //listen for services that show up go acceptServices() + // listen for windows power events and call mfa auth func + go func() { + for { + select { + case wEvents := <- winEvents: + log.Debugf("Received Windows Event in tunnel %d", wEvents.WinPowerEvent) + if wEvents.WinPowerEvent == PBT_APMRESUMESUSPEND || wEvents.WinPowerEvent == PBT_APMRESUMEAUTOMATIC { + for _, id := range rts.ids { + if id.MfaEnabled { + cziti.EndpointStateChanged(id.CId, true, false) + } + } + } + // should fetch lock events also + case <- shutdownDelay: + log.Tracef("Exiting windows power events loop") + } + } + }() + // open the pipe for business pipes, err := openPipes() if err != nil { @@ -136,10 +157,9 @@ func SubMain(ops chan string, changes chan<- svc.Status) error { }) // wait 1 second for the shutdown to send to clients - shutdownDelay := make(chan bool) go func() { time.Sleep(1 * time.Second) - shutdownDelay <- true + close(shutdownDelay) }() <-shutdownDelay diff --git a/service/ziti-tunnel/service/service.go b/service/ziti-tunnel/service/service.go index f9ce3fbe..b13455d1 100644 --- a/service/ziti-tunnel/service/service.go +++ b/service/ziti-tunnel/service/service.go @@ -41,8 +41,9 @@ func (m *zitiService) Execute(args []string, r <-chan svc.ChangeRequest, changes } control := make(chan string) mainLoop := make(chan struct{}) + winEvents := make(chan WindowsEvents) go func() { - err := SubMain(control, changes) + err := SubMain(control, changes, winEvents) if err != nil { log.Errorf("the main loop exited with an unexpected error: %v", err) } @@ -82,6 +83,7 @@ loop: if c.EventType == PBT_APMRESUMESUSPEND || c.EventType == PBT_APMPOWERSTATUSCHANGE || c.EventType == PBT_APMRESUMEAUTOMATIC { // more than one event may be generated powerEvent = fmt.Sprintf("Power event received - resumed, Event Type - %d", c.EventType) + winEvents <- WindowsEvents{WinPowerEvent: c.EventType} } else if c.EventType == PBT_APMSUSPEND { powerEvent = fmt.Sprintf("Power event received - suspend, Event Type - %d", c.EventType) } else { diff --git a/service/ziti-tunnel/service/types.go b/service/ziti-tunnel/service/types.go index 67ec1495..c6cfce2c 100644 --- a/service/ziti-tunnel/service/types.go +++ b/service/ziti-tunnel/service/types.go @@ -9,3 +9,7 @@ type Id struct { dto.Identity CId *cziti.ZIdentity } + +type WindowsEvents struct { + WinPowerEvent uint32 +} From c547e1e38fbba76685b8c8d21252e7a16754dbd0 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Fri, 9 Jul 2021 08:40:52 -0400 Subject: [PATCH 05/46] update adv inst version --- Installer/build.ps1 | 2 +- Installer/reg.bat | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Installer/build.ps1 b/Installer/build.ps1 index aeff0416..2083a5dc 100644 --- a/Installer/build.ps1 +++ b/Installer/build.ps1 @@ -24,7 +24,7 @@ msbuild ZitiDesktopEdge.sln /property:Configuration=Release Pop-Location -$ADV_INST_HOME = "C:\Program Files (x86)\Caphyon\Advanced Installer 18.3" +$ADV_INST_HOME = "C:\Program Files (x86)\Caphyon\Advanced Installer 18.4" $ADVINST = "${ADV_INST_HOME}\bin\x86\AdvancedInstaller.com" $ADVPROJECT = "${scriptPath}\ZitiDesktopEdge.aip" $installerVersion=(Get-Content -Path ${scriptPath}\..\version) diff --git a/Installer/reg.bat b/Installer/reg.bat index c8d030ac..044ca561 100644 --- a/Installer/reg.bat +++ b/Installer/reg.bat @@ -1 +1 @@ -"C:\Program Files (x86)\Caphyon\Advanced Installer 18.3\bin\x86\AdvancedInstaller.com" /register %1 +"C:\Program Files (x86)\Caphyon\Advanced Installer 18.4\bin\x86\AdvancedInstaller.com" /register %1 From dd40523014f76fb95ec8dd0f60f617445849a934 Mon Sep 17 00:00:00 2001 From: ziti-ci Date: Fri, 9 Jul 2021 12:49:30 +0000 Subject: [PATCH 06/46] [ci skip] committing updated version related files --- Installer/ZitiDesktopEdge.aip | 2 +- service/ziti-tunnel/version.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Installer/ZitiDesktopEdge.aip b/Installer/ZitiDesktopEdge.aip index 138e20f8..41b3886a 100644 --- a/Installer/ZitiDesktopEdge.aip +++ b/Installer/ZitiDesktopEdge.aip @@ -1,5 +1,5 @@ - + diff --git a/service/ziti-tunnel/version.go b/service/ziti-tunnel/version.go index 52a10724..0da0b615 100644 --- a/service/ziti-tunnel/version.go +++ b/service/ziti-tunnel/version.go @@ -20,9 +20,9 @@ package main const ( - Version = "1.9.9" - Revision = "b6a4ad327bd0" - Branch = "main" + Version = "1.9.10" + Revision = "c547e1e38fbb" + Branch = "release-next" BuildUser = "" - BuildDate = "2021-06-24 10:44:17" + BuildDate = "2021-07-09 12:44:22" ) From 33b7fa838883b6161be0f9696e548f48d25cad45 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Fri, 9 Jul 2021 09:09:09 -0400 Subject: [PATCH 07/46] forgot to bump the version too --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 6ae756c4..f0a2883d 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.9.9 +1.9.10 From b4ac2a0f616192cb573b366e94c42576d45381da Mon Sep 17 00:00:00 2001 From: ziti-ci Date: Fri, 9 Jul 2021 13:19:02 +0000 Subject: [PATCH 08/46] [ci skip] committing updated version related files --- DesktopEdge/Properties/AssemblyInfo.cs | 6 +++--- Installer/ZitiDesktopEdge.aip | 4 ++-- ZitiUpdateService/Properties/AssemblyInfo.cs | 6 +++--- service/ziti-tunnel/version.go | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/DesktopEdge/Properties/AssemblyInfo.cs b/DesktopEdge/Properties/AssemblyInfo.cs index 4e3bd4b5..745f32e5 100644 --- a/DesktopEdge/Properties/AssemblyInfo.cs +++ b/DesktopEdge/Properties/AssemblyInfo.cs @@ -50,6 +50,6 @@ using System.Windows; // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -// [assembly: AssemblyVersion("1.9.9.0")] -[assembly: AssemblyVersion("1.9.9.0")] -[assembly: AssemblyFileVersion("1.9.9.0")] +// [assembly: AssemblyVersion("1.9.10.0")] +[assembly: AssemblyVersion("1.9.10.0")] +[assembly: AssemblyFileVersion("1.9.10.0")] diff --git a/Installer/ZitiDesktopEdge.aip b/Installer/ZitiDesktopEdge.aip index 41b3886a..a8a6864e 100644 --- a/Installer/ZitiDesktopEdge.aip +++ b/Installer/ZitiDesktopEdge.aip @@ -23,10 +23,10 @@ - + - + diff --git a/ZitiUpdateService/Properties/AssemblyInfo.cs b/ZitiUpdateService/Properties/AssemblyInfo.cs index d56ff0f6..26778098 100644 --- a/ZitiUpdateService/Properties/AssemblyInfo.cs +++ b/ZitiUpdateService/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -// [assembly: AssemblyVersion("1.9.9.0")] -[assembly: AssemblyVersion("1.9.9.0")] -[assembly: AssemblyFileVersion("1.9.9.0")] +// [assembly: AssemblyVersion("1.9.10.0")] +[assembly: AssemblyVersion("1.9.10.0")] +[assembly: AssemblyFileVersion("1.9.10.0")] diff --git a/service/ziti-tunnel/version.go b/service/ziti-tunnel/version.go index 0da0b615..97ca7159 100644 --- a/service/ziti-tunnel/version.go +++ b/service/ziti-tunnel/version.go @@ -21,8 +21,8 @@ package main const ( Version = "1.9.10" - Revision = "c547e1e38fbb" + Revision = "b7ec7a0f90ef" Branch = "release-next" BuildUser = "" - BuildDate = "2021-07-09 12:44:22" + BuildDate = "2021-07-09 13:13:21" ) From 47a98d1dbedd36e6edefda37a7e71187a5162001 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Fri, 9 Jul 2021 12:59:59 -0400 Subject: [PATCH 09/46] allow 'adding back' removed intercepts --- service/cziti/ctun.go | 31 +++++++++++++++++++++++------- service/cziti/sdk.go | 2 ++ service/ziti-tunnel/service/ipc.go | 13 ++++++++++++- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/service/cziti/ctun.go b/service/cziti/ctun.go index 09c082cd..62b1508b 100644 --- a/service/cziti/ctun.go +++ b/service/cziti/ctun.go @@ -45,6 +45,7 @@ void readIdle(uv_prepare_t *idler); void call_on_packet(void *packet, ssize_t len, packet_cb cb, void *ctx); void remove_intercepts(uv_async_t *handle); +void add_intercepts(uv_async_t *handle); void free_async(uv_handle_t* timer); dns_manager* get_dns_mgr_from_c(); @@ -242,26 +243,42 @@ func (t *tunnel) runWriteLoop() { } } -type RemoveWG struct { +type TunnelerActionWaitGroup struct { Wg *sync.WaitGroup Czsvc *ZService } -func RemoveIntercept(rwg *RemoveWG) { +func RemoveIntercept(removeWaitGroup *TunnelerActionWaitGroup) { async := (*C.uv_async_t)(C.malloc(C.sizeof_uv_async_t)) - async.data = unsafe.Pointer(rwg) + async.data = unsafe.Pointer(removeWaitGroup) C.uv_async_init(_impl.libuvCtx.l, async, C.uv_async_cb(C.remove_intercepts)) C.uv_async_send((*C.uv_async_t)(unsafe.Pointer(async))) } +func AddIntercept(addWaitGroup *TunnelerActionWaitGroup) { + async := (*C.uv_async_t)(C.malloc(C.sizeof_uv_async_t)) + async.data = unsafe.Pointer(addWaitGroup) + C.uv_async_init(_impl.libuvCtx.l, async, C.uv_async_cb(C.add_intercepts)) + C.uv_async_send((*C.uv_async_t)(unsafe.Pointer(async))) +} + //export remove_intercepts func remove_intercepts(async *C.uv_async_t) { - rwg := (*RemoveWG)(async.data) - cSvcName := C.CString(rwg.Czsvc.Name) + removeWaitGroup := (*TunnelerActionWaitGroup)(async.data) + cSvcName := C.CString(removeWaitGroup.Czsvc.Name) defer C.free(unsafe.Pointer(cSvcName)) - C.ziti_tunneler_stop_intercepting(theTun.tunCtx, unsafe.Pointer(rwg.Czsvc.Czctx), cSvcName) + C.ziti_tunneler_stop_intercepting(theTun.tunCtx, unsafe.Pointer(removeWaitGroup.Czsvc.Czctx), cSvcName) C.uv_close((*C.uv_handle_t)(unsafe.Pointer(async)), C.uv_close_cb(C.free_async)) - rwg.Wg.Done() + removeWaitGroup.Wg.Done() +} + +//export add_intercepts +func add_intercepts(async *C.uv_async_t) { + addWaitGroup := (*TunnelerActionWaitGroup)(async.data) + + C.ziti_sdk_c_on_service(addWaitGroup.Czsvc.Czctx, addWaitGroup.Czsvc.Czsvc, C.ZITI_OK, unsafe.Pointer(theTun.tunCtx)) + C.uv_close((*C.uv_handle_t)(unsafe.Pointer(async)), C.uv_close_cb(C.free_async)) + addWaitGroup.Wg.Done() } //export apply_dns_go diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 2f116a56..1d057093 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -113,6 +113,7 @@ type ZService struct { Name string Id string Service *dto.Service + Czsvc *C.ziti_service Czctx C.ziti_context } @@ -375,6 +376,7 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z Name: name, Id: svcId, Service: svc, + Czsvc: service, Czctx: ziti_ctx, } zid.Services.Store(svcId, &added) diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 2b7cd53f..da965f39 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -940,6 +940,17 @@ func connectIdentity(id *Id) { id.CId.Services.Range(func(key interface{}, value interface{}) bool { id.Services = append(id.Services, nil) + + val := value.(*cziti.ZService) + var wg sync.WaitGroup + wg.Add(1) + rwg := &cziti.TunnelerActionWaitGroup{ + Wg: &wg, + Czsvc: val, + } + cziti.AddIntercept(rwg) + wg.Wait() + return true }) @@ -964,7 +975,7 @@ func disconnectIdentity(id *Id) error { val := value.(*cziti.ZService) var wg sync.WaitGroup wg.Add(1) - rwg := &cziti.RemoveWG{ + rwg := &cziti.TunnelerActionWaitGroup{ Wg: &wg, Czsvc: val, } From 84631c77b8e29547249d8ce3e63f54d8ebfbbaf0 Mon Sep 17 00:00:00 2001 From: ziti-ci Date: Fri, 9 Jul 2021 17:08:20 +0000 Subject: [PATCH 10/46] [ci skip] committing updated version related files --- service/ziti-tunnel/version.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/ziti-tunnel/version.go b/service/ziti-tunnel/version.go index 97ca7159..7e46dd86 100644 --- a/service/ziti-tunnel/version.go +++ b/service/ziti-tunnel/version.go @@ -21,8 +21,8 @@ package main const ( Version = "1.9.10" - Revision = "b7ec7a0f90ef" + Revision = "307fe37ade59" Branch = "release-next" BuildUser = "" - BuildDate = "2021-07-09 13:13:21" + BuildDate = "2021-07-09 17:03:23" ) From 035b7225c25393c13eee7b61028b83162a1a38d3 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Sun, 11 Jul 2021 19:38:50 +0530 Subject: [PATCH 11/46] mfa new auth funtion - initial commit --- service/cziti/mfa.c | 4 +-- service/cziti/mfa.go | 59 ++++++++++++++++++++++++++++--- service/cziti/sdk.go | 21 ++++++++--- service/cziti/sdk.h | 5 +-- service/ziti-tunnel/dto/dtos.go | 2 ++ service/ziti-tunnel/dto/events.go | 5 +++ 6 files changed, 84 insertions(+), 12 deletions(-) diff --git a/service/cziti/mfa.c b/service/cziti/mfa.c index 1a8d7f02..52fdefbd 100644 --- a/service/cziti/mfa.c +++ b/service/cziti/mfa.c @@ -14,11 +14,11 @@ * limitations under the License. * */ - +/* #include "sdk.h" #include #include void ziti_mfa_auth_request(ziti_ar_mfa_cb response_cb, ziti_context ztx, void *mfa_ctx, char *code, ziti_ar_mfa_status_cb auth_response, char *fingerprint) { response_cb(ztx, mfa_ctx, code, auth_response, fingerprint); -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/service/cziti/mfa.go b/service/cziti/mfa.go index 6c211875..95dbf2df 100644 --- a/service/cziti/mfa.go +++ b/service/cziti/mfa.go @@ -46,6 +46,7 @@ type mfaCodes struct { var emptyCodes []string var mfaAuthResults = make(chan string) +var mfa2FactorAuthResults = make(chan string) //export /* @@ -119,12 +120,13 @@ func ziti_mfa_enroll_cb_go(_ C.ziti_context, status C.int, enrollment *C.ziti_mf } } +// requires that the identity already be fully authenticated and used specifically for enrollment func VerifyMFA(id *ZIdentity, code string) { ccode := C.CString(code) defer C.free(unsafe.Pointer(ccode)) log.Tracef("verifying MFA for fingerprint: %s using code: %s", id.Fingerprint, code) - C.ziti_mfa_auth(id.czctx, ccode, C.ziti_mfa_cb(C.ziti_mfa_cb_verify_go), unsafe.Pointer(C.CString(id.Fingerprint))) + C.ziti_mfa_verify(id.czctx, ccode, C.ziti_mfa_cb(C.ziti_mfa_cb_verify_go), unsafe.Pointer(C.CString(id.Fingerprint))) } //export ziti_mfa_cb_verify_go @@ -177,6 +179,55 @@ func ReturnMfaCodes(id *ZIdentity, code string) ([]string, error) { } } + +// used when an identity is partially authenticated and waiting on 2fa, i.e. for authentication and for timeouts +func AuthMFA(id *ZIdentity, code string) error { + ccode := C.CString(code) + defer C.free(unsafe.Pointer(ccode)) + + log.Tracef("authenticating 2factor MFA for fingerprint: %s using code: %s", id.Fingerprint, code) + // call back for ziti_mfa_auth, status check and send the error or success response + C.ziti_mfa_auth(id.czctx, ccode, C.ziti_mfa_cb(C.ziti_2fauth_mfa_status_cb_go), unsafe.Pointer(C.CString(id.Fingerprint))) + authResult := strings.TrimSpace(<-mfa2FactorAuthResults) + + if authResult == "" { + id.MfaEnabled = true + id.MfaNeeded = false + return nil + } + return fmt.Errorf("error in 2factor authMFA: %v", authResult) +} + +//export ziti_2fauth_mfa_status_cb_go +func ziti_2fauth_mfa_status_cb_go(ztx C.ziti_context, status C.int, cFingerprint *C.char) { + defer C.free(unsafe.Pointer(cFingerprint)) + fp := C.GoString(cFingerprint) + + log.Debugf("ziti_2fauth_mfa_status_cb_go called for %s. status: %d for ", fp, int(status)) + var m = dto.MfaEvent{ + ActionEvent: dto.MFA2FactorAuthenticationEvent, + Fingerprint: fp, + Successful: false, + RecoveryCodes: nil, + } + + if status != C.ZITI_OK { + e := C.ziti_errorstr(status) + ego := C.GoString(e) + log.Errorf("Error encounted when authenticating 2f mfa: %v", ego) + m.Error = ego + mfa2FactorAuthResults <- ego + } else { + log.Infof("Identity with fingerprint %s has successfully authenticated MFA", fp) + m.Successful = true + goapi.UpdateMfa(fp, true, false) + mfa2FactorAuthResults <- "" + } + + log.Debugf("sending ziti_mfa_auth response back to UI for %s. verified: %t. error: %s", fp, m.Successful, m.Error) + goapi.BroadcastEvent(m) +} + //export ziti_mfa_recovery_codes_cb_return func ziti_mfa_recovery_codes_cb_return(_ C.ziti_context, status C.int, recoveryCodes **C.char, cFingerprint *C.char) { fp := C.GoString(cFingerprint) @@ -257,7 +308,7 @@ func populateStringSlice(c_char_array **C.char) []string { return strs } -func AuthMFA(id *ZIdentity, code string) error { +/*func AuthMFA_old(id *ZIdentity, code string) error { if id.mfa == nil { log.Warnf("AuthMFA called but mfa is nil. This usually is because AuthMFA is called from an unenrolled MFA endpoint or the endpoint has already been auth'ed") return fmt.Errorf("identity has not authenticated yet") @@ -297,7 +348,7 @@ func ziti_ar_mfa_status_cb_go(ztx C.ziti_context, mfa_ctx unsafe.Pointer, status ego := C.GoString(e) mfaAuthResults <- ego } -} +}*/ func RemoveMFA(id *ZIdentity, code string) { ccode := C.CString(code) @@ -336,6 +387,6 @@ func ziti_mfa_cb_remove_go(_ C.ziti_context, status C.int, cFingerprint *C.char) } func EndpointStateChanged(id *ZIdentity, woken bool, unlocked bool) { - C.ziti_endpoint_state_change(id.czctx, woken, unlocked) + C.ziti_endpoint_state_change(id.czctx, C.bool(woken), C.bool(unlocked)) log.Debugf("Endpoint status changed - woken %t, unlocked %t", woken, unlocked) } diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 3f16f68b..1aee0ce3 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -131,14 +131,14 @@ type ZIdentity struct { StatusChanges func(int) MfaNeeded bool MfaEnabled bool - mfa *Mfa + //mfa *Mfa } -type Mfa struct { +/*type Mfa struct { mfaContext unsafe.Pointer authQuery *C.ziti_auth_query_mfa responseCb C.ziti_ar_mfa_cb -} +}*/ func NewZid(statusChange func(int)) *ZIdentity { zid := &ZIdentity{} @@ -315,6 +315,7 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z //if any posture query sets pass - that will grant the user access to that service hasAccess := false + timeout := -1 //find all posture checks sets... for setIdx := 0; true; setIdx++ { @@ -348,13 +349,24 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z _, found := pcIds[pcId] if found { log.Tracef("posture check with id %s already in failing posture check map", pcId) + for _, pc := range postureChecks { + if pc.Id == C.GoString(pq.id) { + if pc.Timeout > int(pq.timeout) { + pc.Timeout = int(pq.timeout) + timeout = pc.Timeout + } + break + } + } } else { pcIds[C.GoString(pq.id)] = false pc := dto.PostureCheck{ IsPassing: bool(pq.is_passing), QueryType: C.GoString(pq.query_type), Id: pcId, + Timeout: int(pq.timeout), } + timeout = pc.Timeout postureChecks = append(postureChecks, pc) } @@ -370,6 +382,7 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z OwnsIntercept: true, PostureChecks: postureChecks, IsAccessable: hasAccess, + Timeout: timeout, } added := ZService{ Name: name, @@ -532,8 +545,8 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { BulkServiceChanges <- svcChange } case C.ZitiMfaAuthEvent: - log.Debugf("mfa requested for ziti context.") zid := (*ZIdentity)(appCtx) + log.Debugf("mfa requested for finger print %s", zid.Fingerprint) /*mfa := &Mfa{ mfaContext: mfa_ctx, authQuery: aq_mfa, diff --git a/service/cziti/sdk.h b/service/cziti/sdk.h index d68ead6a..5a18c4fd 100644 --- a/service/cziti/sdk.h +++ b/service/cziti/sdk.h @@ -75,15 +75,16 @@ ziti_service* ziti_service_array_get(ziti_service_array arr, int idx); void ziti_dump_go(char *msg); //declare all mfa callbacks -void ziti_aq_mfa_cb_go(ziti_context ztx, void *mfa_ctx, ziti_auth_query_mfa *aq_mfa, ziti_ar_mfa_cb response_cb); +//void ziti_aq_mfa_cb_go(ziti_context ztx, void *mfa_ctx, ziti_auth_query_mfa *aq_mfa, ziti_ar_mfa_cb response_cb); void ziti_mfa_enroll_cb_go(ziti_context ztx, int status, ziti_mfa_enrollment *mfa_enrollment, char *fingerprint); void ziti_mfa_cb_verify_go(ziti_context ztx, int status, char *fingerprint); void ziti_mfa_cb_remove_go(ziti_context ztx, int status, char *fingerprint); void ziti_mfa_recovery_codes_cb_return(ziti_context ztx, int status, char **recovery_codes, char *fingerprint); void ziti_mfa_recovery_codes_cb_generate(ziti_context ztx, int status, char **recovery_codes, char *fingerprint); -void ziti_mfa_auth_request(ziti_ar_mfa_cb response_cb, ziti_context ztx, void *mfa_ctx, char *code, ziti_ar_mfa_status_cb auth_response, char *fingerprint); +//void ziti_mfa_auth_request(ziti_ar_mfa_cb response_cb, ziti_context ztx, void *mfa_ctx, char *code, ziti_ar_mfa_status_cb auth_response, char *fingerprint); void ziti_mfa_ar_cb(ziti_context ztx, void *mfa_ctx, int status); void ziti_ar_mfa_status_cb_go(ziti_context ztx, void *mfa_ctx, int status, char *fingerprint); +void ziti_2fauth_mfa_status_cb_go(ziti_context ztx, int status, char *fingerprint); ziti_posture_query_set* posture_query_set_get(ziti_posture_query_set_array arr, int idx); ziti_posture_query* posture_queries_get(ziti_posture_query_array arr, int idx); diff --git a/service/ziti-tunnel/dto/dtos.go b/service/ziti-tunnel/dto/dtos.go index c8930d43..b0da0629 100644 --- a/service/ziti-tunnel/dto/dtos.go +++ b/service/ziti-tunnel/dto/dtos.go @@ -39,6 +39,7 @@ type Service struct { OwnsIntercept bool PostureChecks []PostureCheck IsAccessable bool + Timeout int } type Address struct { @@ -57,6 +58,7 @@ type PostureCheck struct { IsPassing bool QueryType string Id string + Timeout int } type ServiceOwner struct { diff --git a/service/ziti-tunnel/dto/events.go b/service/ziti-tunnel/dto/events.go index e2e43379..59e1555a 100644 --- a/service/ziti-tunnel/dto/events.go +++ b/service/ziti-tunnel/dto/events.go @@ -37,6 +37,7 @@ const ( MFAEnrollmentRemovedAction = "enrollment_remove" MFA_AUTH_CHALLENGE_ACTION = "auth_challenge" + MFA2FactorAuthenticationAction = "mfa_2f_auth" ) var SERVICE_ADDED = ActionEvent{ @@ -96,3 +97,7 @@ var MFAAuthChallengeEvent = ActionEvent{ StatusEvent: StatusEvent{Op: MFA_OP}, Action: MFA_AUTH_CHALLENGE_ACTION, } +var MFA2FactorAuthenticationEvent = ActionEvent{ + StatusEvent: StatusEvent{Op: MFA_OP}, + Action: MFA2FactorAuthenticationAction, +} From 673529d5524fa9f2344dcaffb2732048b4178d01 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 12 Jul 2021 12:54:19 +0530 Subject: [PATCH 12/46] renaming 2 factor auth to auth --- DesktopEdge/MainWindow.xaml.cs | 2 ++ service/cziti/mfa.go | 28 ++++++++++++++-------------- service/cziti/sdk.h | 2 +- service/ziti-tunnel/dto/events.go | 6 +++--- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index a727ff65..c3c02b3d 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -126,6 +126,8 @@ namespace ZitiDesktopEdge { } } else if (mfa.Action == "enrollment_remove") { // ShowBlurb("removed mfa: " + mfa.Successful, ""); + } else if (mfa.Action == "mfa_auth_status") { + // ShowBlurb("mfa authenticated: " + mfa.Successful, ""); } else { await ShowBlurbAsync ("Unexpected error when processing MFA", ""); logger.Error("unexpected action: " + mfa.Action); diff --git a/service/cziti/mfa.go b/service/cziti/mfa.go index 95dbf2df..04df08da 100644 --- a/service/cziti/mfa.go +++ b/service/cziti/mfa.go @@ -46,7 +46,7 @@ type mfaCodes struct { var emptyCodes []string var mfaAuthResults = make(chan string) -var mfa2FactorAuthResults = make(chan string) +//var mfaOldAuthResults = make(chan string) //export /* @@ -185,27 +185,27 @@ func AuthMFA(id *ZIdentity, code string) error { ccode := C.CString(code) defer C.free(unsafe.Pointer(ccode)) - log.Tracef("authenticating 2factor MFA for fingerprint: %s using code: %s", id.Fingerprint, code) + log.Tracef("authenticating MFA for fingerprint: %s using code: %s", id.Fingerprint, code) // call back for ziti_mfa_auth, status check and send the error or success response - C.ziti_mfa_auth(id.czctx, ccode, C.ziti_mfa_cb(C.ziti_2fauth_mfa_status_cb_go), unsafe.Pointer(C.CString(id.Fingerprint))) - authResult := strings.TrimSpace(<-mfa2FactorAuthResults) + C.ziti_mfa_auth(id.czctx, ccode, C.ziti_mfa_cb(C.ziti_auth_mfa_status_cb_go), unsafe.Pointer(C.CString(id.Fingerprint))) + authResult := strings.TrimSpace(<-mfaAuthResults) if authResult == "" { id.MfaEnabled = true id.MfaNeeded = false return nil } - return fmt.Errorf("error in 2factor authMFA: %v", authResult) + return fmt.Errorf("error in authMFA: %v", authResult) } -//export ziti_2fauth_mfa_status_cb_go -func ziti_2fauth_mfa_status_cb_go(ztx C.ziti_context, status C.int, cFingerprint *C.char) { +//export ziti_auth_mfa_status_cb_go +func ziti_auth_mfa_status_cb_go(ztx C.ziti_context, status C.int, cFingerprint *C.char) { defer C.free(unsafe.Pointer(cFingerprint)) fp := C.GoString(cFingerprint) - log.Debugf("ziti_2fauth_mfa_status_cb_go called for %s. status: %d for ", fp, int(status)) + log.Debugf("ziti_auth_mfa_status_cb_go called for %s. status: %d for ", fp, int(status)) var m = dto.MfaEvent{ - ActionEvent: dto.MFA2FactorAuthenticationEvent, + ActionEvent: dto.MFAAuthenticationEvent, Fingerprint: fp, Successful: false, RecoveryCodes: nil, @@ -216,12 +216,12 @@ func ziti_2fauth_mfa_status_cb_go(ztx C.ziti_context, status C.int, cFingerprint ego := C.GoString(e) log.Errorf("Error encounted when authenticating 2f mfa: %v", ego) m.Error = ego - mfa2FactorAuthResults <- ego + mfaAuthResults <- ego } else { log.Infof("Identity with fingerprint %s has successfully authenticated MFA", fp) m.Successful = true goapi.UpdateMfa(fp, true, false) - mfa2FactorAuthResults <- "" + mfaAuthResults <- "" } log.Debugf("sending ziti_mfa_auth response back to UI for %s. verified: %t. error: %s", fp, m.Successful, m.Error) @@ -325,7 +325,7 @@ func populateStringSlice(c_char_array **C.char) []string { defer C.free(unsafe.Pointer(cfp)) log.Debugf("beginning authentication for fingerprint %s with code %s", id.Fingerprint, code) C.ziti_mfa_auth_request(id.mfa.responseCb, id.czctx, id.mfa.mfaContext, ccode, C.ziti_ar_mfa_status_cb(C.ziti_ar_mfa_status_cb_go), cfp) - authResult := strings.TrimSpace(<-mfaAuthResults) + authResult := strings.TrimSpace(<-mfaOldAuthResults) if authResult == "" { id.mfa.responseCb = nil @@ -341,12 +341,12 @@ func ziti_ar_mfa_status_cb_go(ztx C.ziti_context, mfa_ctx unsafe.Pointer, status log.Debugf("ziti_ar_mfa_status_cb_go called for fingerprint: %s with status %v", fp, status) if status == C.ZITI_OK { log.Infof("mfa authentication succeeded for fingerprint: %s", fp) - mfaAuthResults <- "" + mfaOldAuthResults <- "" } else { log.Warnf("mfa authentication failed for fingerprint: %s", fp) e := C.ziti_errorstr(status) ego := C.GoString(e) - mfaAuthResults <- ego + mfaOldAuthResults <- ego } }*/ diff --git a/service/cziti/sdk.h b/service/cziti/sdk.h index 5a18c4fd..a60aedce 100644 --- a/service/cziti/sdk.h +++ b/service/cziti/sdk.h @@ -84,7 +84,7 @@ void ziti_mfa_recovery_codes_cb_generate(ziti_context ztx, int status, char **re //void ziti_mfa_auth_request(ziti_ar_mfa_cb response_cb, ziti_context ztx, void *mfa_ctx, char *code, ziti_ar_mfa_status_cb auth_response, char *fingerprint); void ziti_mfa_ar_cb(ziti_context ztx, void *mfa_ctx, int status); void ziti_ar_mfa_status_cb_go(ziti_context ztx, void *mfa_ctx, int status, char *fingerprint); -void ziti_2fauth_mfa_status_cb_go(ziti_context ztx, int status, char *fingerprint); +void ziti_auth_mfa_status_cb_go(ziti_context ztx, int status, char *fingerprint); ziti_posture_query_set* posture_query_set_get(ziti_posture_query_set_array arr, int idx); ziti_posture_query* posture_queries_get(ziti_posture_query_array arr, int idx); diff --git a/service/ziti-tunnel/dto/events.go b/service/ziti-tunnel/dto/events.go index 59e1555a..81bf20c1 100644 --- a/service/ziti-tunnel/dto/events.go +++ b/service/ziti-tunnel/dto/events.go @@ -37,7 +37,7 @@ const ( MFAEnrollmentRemovedAction = "enrollment_remove" MFA_AUTH_CHALLENGE_ACTION = "auth_challenge" - MFA2FactorAuthenticationAction = "mfa_2f_auth" + MFAAuthenticationAction = "mfa_auth_status" ) var SERVICE_ADDED = ActionEvent{ @@ -97,7 +97,7 @@ var MFAAuthChallengeEvent = ActionEvent{ StatusEvent: StatusEvent{Op: MFA_OP}, Action: MFA_AUTH_CHALLENGE_ACTION, } -var MFA2FactorAuthenticationEvent = ActionEvent{ +var MFAAuthenticationEvent = ActionEvent{ StatusEvent: StatusEvent{Op: MFA_OP}, - Action: MFA2FactorAuthenticationAction, + Action: MFAAuthenticationAction, } From 0465e3ddd53c6e2f586ac1e661ff29742fbe727a Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 12 Jul 2021 13:39:00 +0530 Subject: [PATCH 13/46] fixing log messages --- service/cziti/mfa.go | 1 - service/cziti/sdk.go | 4 ++-- service/ziti-tunnel/service/ipc.go | 3 ++- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/service/cziti/mfa.go b/service/cziti/mfa.go index 04df08da..38fd0d8e 100644 --- a/service/cziti/mfa.go +++ b/service/cziti/mfa.go @@ -186,7 +186,6 @@ func AuthMFA(id *ZIdentity, code string) error { defer C.free(unsafe.Pointer(ccode)) log.Tracef("authenticating MFA for fingerprint: %s using code: %s", id.Fingerprint, code) - // call back for ziti_mfa_auth, status check and send the error or success response C.ziti_mfa_auth(id.czctx, ccode, C.ziti_mfa_cb(C.ziti_auth_mfa_status_cb_go), unsafe.Pointer(C.CString(id.Fingerprint))) authResult := strings.TrimSpace(<-mfaAuthResults) diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 1aee0ce3..c2624234 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -546,7 +546,7 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { } case C.ZitiMfaAuthEvent: zid := (*ZIdentity)(appCtx) - log.Debugf("mfa requested for finger print %s", zid.Fingerprint) + log.Debugf("mfa auth event for finger print %s", zid.Fingerprint) /*mfa := &Mfa{ mfaContext: mfa_ctx, authQuery: aq_mfa, @@ -574,7 +574,7 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { } goapi.BroadcastEvent(m) } - log.Debugf("mfa enabled/needed set to true for ziti context [%p]. Identity name:%s [fingerprint: %s]", zid, zid.Name, zid.Fingerprint) + log.Debugf("mfa auth event set enabled/needed to true for ziti context [%p]. Identity name:%s [fingerprint: %s]", zid, zid.Name, zid.Fingerprint) default: log.Infof("event %d not handled", event._type) } diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 436d2ad1..530782ca 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -115,9 +115,10 @@ func SubMain(ops chan string, changes chan<- svc.Status, winEvents <-chan Window } } } - // should fetch lock events also + // should fetch lock events also case <- shutdownDelay: log.Tracef("Exiting windows power events loop") + break } } }() From cd087214f17d65d603c88de8d1a3b374db0281ff Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 12 Jul 2021 16:18:15 +0530 Subject: [PATCH 14/46] accept windows unlock events in ZDE --- service/cziti/mfa.go | 2 +- service/ziti-tunnel/service/ipc.go | 13 +++++++++++-- service/ziti-tunnel/service/pkg-vars.go | 6 +++++- service/ziti-tunnel/service/service.go | 14 +++++++++++++- service/ziti-tunnel/service/types.go | 1 + 5 files changed, 31 insertions(+), 5 deletions(-) diff --git a/service/cziti/mfa.go b/service/cziti/mfa.go index 38fd0d8e..e4dabb55 100644 --- a/service/cziti/mfa.go +++ b/service/cziti/mfa.go @@ -387,5 +387,5 @@ func ziti_mfa_cb_remove_go(_ C.ziti_context, status C.int, cFingerprint *C.char) func EndpointStateChanged(id *ZIdentity, woken bool, unlocked bool) { C.ziti_endpoint_state_change(id.czctx, C.bool(woken), C.bool(unlocked)) - log.Debugf("Endpoint status changed - woken %t, unlocked %t", woken, unlocked) + log.Debugf("Endpoint status changed for id %s - woken %t, unlocked %t", id.Fingerprint, woken, unlocked) } diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 530782ca..bec2088b 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -104,21 +104,30 @@ func SubMain(ops chan string, changes chan<- svc.Status, winEvents <-chan Window // listen for windows power events and call mfa auth func go func() { + windowsEvents: for { select { case wEvents := <- winEvents: - log.Debugf("Received Windows Event in tunnel %d", wEvents.WinPowerEvent) if wEvents.WinPowerEvent == PBT_APMRESUMESUSPEND || wEvents.WinPowerEvent == PBT_APMRESUMEAUTOMATIC { + log.Debugf("Received Windows Power Event in tunnel %d", wEvents.WinPowerEvent) for _, id := range rts.ids { if id.MfaEnabled { cziti.EndpointStateChanged(id.CId, true, false) } } } + if wEvents.WinSessionEvent == WTS_SESSION_UNLOCK { + log.Debugf("Received Windows Session Event in tunnel %d", wEvents.WinSessionEvent) + for _, id := range rts.ids { + if id.MfaEnabled { + cziti.EndpointStateChanged(id.CId, false, true) + } + } + } // should fetch lock events also case <- shutdownDelay: log.Tracef("Exiting windows power events loop") - break + break windowsEvents } } }() diff --git a/service/ziti-tunnel/service/pkg-vars.go b/service/ziti-tunnel/service/pkg-vars.go index fdd49633..97dbd7b9 100644 --- a/service/ziti-tunnel/service/pkg-vars.go +++ b/service/ziti-tunnel/service/pkg-vars.go @@ -64,7 +64,7 @@ const ( DEFAULT_REFRESH_INTERVAL = 10 - cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown | svc.AcceptPauseAndContinue | svc.AcceptPowerEvent + cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown | svc.AcceptPauseAndContinue | svc.AcceptPowerEvent | svc.AcceptSessionChange InformationEvent = 0 //1 ContinueEvent = 0 //2 @@ -81,6 +81,10 @@ const ( PBT_APMPOWERSTATUSCHANGE = 10 // Power Status Change PBT_APMRESUMEAUTOMATIC = 18 // Resume Automatic + // windows session changes microsoft docs https://docs.microsoft.com/en-us/windows/win32/termserv/wm-wtssession-change + WTS_SESSION_LOCK = 7 + WTS_SESSION_UNLOCK = 8 + // This is the name you will use for the NET START command SvcStartName = "ziti" diff --git a/service/ziti-tunnel/service/service.go b/service/ziti-tunnel/service/service.go index b13455d1..45d47ca0 100644 --- a/service/ziti-tunnel/service/service.go +++ b/service/ziti-tunnel/service/service.go @@ -83,7 +83,7 @@ loop: if c.EventType == PBT_APMRESUMESUSPEND || c.EventType == PBT_APMPOWERSTATUSCHANGE || c.EventType == PBT_APMRESUMEAUTOMATIC { // more than one event may be generated powerEvent = fmt.Sprintf("Power event received - resumed, Event Type - %d", c.EventType) - winEvents <- WindowsEvents{WinPowerEvent: c.EventType} + winEvents <- WindowsEvents{WinPowerEvent: c.EventType, WinSessionEvent: 0} } else if c.EventType == PBT_APMSUSPEND { powerEvent = fmt.Sprintf("Power event received - suspend, Event Type - %d", c.EventType) } else { @@ -91,6 +91,18 @@ loop: } _ = logging.Elog.Info(InformationEvent, powerEvent) log.Infof(powerEvent) + case svc.SessionChange: + var sessionChangedEvent string + if c.EventType == WTS_SESSION_UNLOCK { + sessionChangedEvent = fmt.Sprintf("Windows session changed event received - unlocked device, Event Type %d", c.EventType) + winEvents <- WindowsEvents{WinPowerEvent: 0, WinSessionEvent: c.EventType} + } else if c.EventType == WTS_SESSION_LOCK { + sessionChangedEvent = fmt.Sprintf("Windows session changed event received - locked device, Event Type %d", c.EventType) + } else { + sessionChangedEvent = fmt.Sprintf("Windows session changed unknown event received - Event Type %d", c.EventType) + } + _ = logging.Elog.Info(InformationEvent, sessionChangedEvent) + log.Infof(sessionChangedEvent) default: _ = logging.Elog.Error(1, fmt.Sprintf("unexpected control request #%d", c)) } diff --git a/service/ziti-tunnel/service/types.go b/service/ziti-tunnel/service/types.go index c6cfce2c..d9fd04b6 100644 --- a/service/ziti-tunnel/service/types.go +++ b/service/ziti-tunnel/service/types.go @@ -12,4 +12,5 @@ type Id struct { type WindowsEvents struct { WinPowerEvent uint32 + WinSessionEvent uint32 } From 308e94dec838a4a17acb96408a2ba25950f37ad0 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Tue, 13 Jul 2021 21:43:09 +0530 Subject: [PATCH 15/46] adding timer logic for service timeout notifications --- service/cziti/sdk.go | 30 ++++++++++ service/ziti-tunnel/service/ipc.go | 96 ++++++++++++++++++++++++++---- 2 files changed, 114 insertions(+), 12 deletions(-) diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index c2624234..1a0760e8 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -46,6 +46,7 @@ import "C" import ( "encoding/json" "errors" + "fmt" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/api" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/util/logging" @@ -60,6 +61,7 @@ var log = logging.Logger() var noFileLog = logging.NoFilenameLogger() var Version dto.ServiceVersion var BulkServiceChanges = make(chan BulkServiceChange, 32) +var ToastNotifications = make(chan ToastNotification, 32) var cCfgZitiTunnelerClientV1 = C.CString("ziti-tunneler-client.v1") var cCfgInterceptV1 = C.CString("intercept.v1") @@ -80,6 +82,12 @@ type BulkServiceChange struct { ServicesToAdd []*dto.Service } +type ToastNotification struct { + Message string + TimeOut int + Severity string +} + var _impl sdk func init() { @@ -345,6 +353,7 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z var pcId string pcId = C.GoString(pq.id) + log.Infof("Posture query %s, timeout %d", C.GoString(pq.id) , int(pq.timeout)) _, found := pcIds[pcId] if found { @@ -464,6 +473,7 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { hostnamesToRemove := make(map[string]bool) servicesToRemove := make([]*dto.Service, 0) servicesToAdd := make([]*dto.Service, 0) + servicesTimingOut := make([]string, 0, 3) srvEvent := C.ziti_event_service_event(event) @@ -514,6 +524,7 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { servicesToAdd = append(servicesToAdd, svcToAdd) } } + minimumTimeout := 0 for i := 0; true; i++ { added := C.ziti_service_array_get(srvEvent.added, C.int(i)) if unsafe.Pointer(added) == C.NULL { @@ -521,6 +532,9 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { } svcToAdd := serviceCB(ztx, added, C.ZITI_OK, zid) if svcToAdd != nil { + if svcToAdd.Timeout >= 0 && (minimumTimeout == 0 || minimumTimeout >= svcToAdd.Timeout) { + minimumTimeout = svcToAdd.Timeout + } addAddys := svcToAdd.Addresses for _, toAdd := range addAddys { if toAdd.IsHost && hostnameAdded(toAdd.HostName) == 1 { @@ -530,6 +544,22 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { servicesToAdd = append(servicesToAdd, svcToAdd) } } + if len(servicesToAdd) > 0 && minimumTimeout > 0 { + for _, svcAdded := range servicesToAdd { + if svcAdded.Timeout == minimumTimeout && len(servicesTimingOut) < cap(servicesTimingOut) { + servicesTimingOut = append(servicesTimingOut, svcAdded.Name) + } + if len(servicesTimingOut) == cap(servicesTimingOut) { + break + } + } + toastNotificationMsg := ToastNotification { + Message: fmt.Sprintf("Some of the services (%v) are timing out in sometime", servicesTimingOut), + TimeOut: minimumTimeout, + Severity: "Major", + } + ToastNotifications <- toastNotificationMsg + } svcChange := BulkServiceChange{ Fingerprint: zid.Fingerprint, diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index bec2088b..81365f65 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -102,32 +102,28 @@ func SubMain(ops chan string, changes chan<- svc.Status, winEvents <-chan Window //listen for services that show up go acceptServices() + go sendNotifications() + // listen for windows power events and call mfa auth func go func() { - windowsEvents: for { select { case wEvents := <- winEvents: if wEvents.WinPowerEvent == PBT_APMRESUMESUSPEND || wEvents.WinPowerEvent == PBT_APMRESUMEAUTOMATIC { log.Debugf("Received Windows Power Event in tunnel %d", wEvents.WinPowerEvent) for _, id := range rts.ids { - if id.MfaEnabled { - cziti.EndpointStateChanged(id.CId, true, false) - } + cziti.EndpointStateChanged(id.CId, true, false) } } if wEvents.WinSessionEvent == WTS_SESSION_UNLOCK { - log.Debugf("Received Windows Session Event in tunnel %d", wEvents.WinSessionEvent) + log.Debugf("Received Windows Session Event (device unlocked) in tunnel %d", wEvents.WinSessionEvent) for _, id := range rts.ids { - if id.MfaEnabled { - cziti.EndpointStateChanged(id.CId, false, true) - } + cziti.EndpointStateChanged(id.CId, false, true) } } - // should fetch lock events also case <- shutdownDelay: log.Tracef("Exiting windows power events loop") - break windowsEvents + return } } }() @@ -203,8 +199,9 @@ func SubMain(ops chan string, changes chan<- svc.Status, winEvents <-chan Window func requestShutdown(requester string) { log.Infof("shutdown requested by %v", requester) - shutdown <- true // stops the metrics ticker - shutdown <- true // stops the service change listener + // shutdown <- true // stops the metrics ticker + // shutdown <- true // stops the service change listener + close(shutdown) // stops the metrics ticker, service change listener and notification alert loop } func waitForStopRequest(ops <-chan string) { @@ -1229,3 +1226,78 @@ func sendIdentityAndNotifyUI(enc *json.Encoder, fingerprint string) { resp := dto.Response{Message: "", Code: ERROR, Error: "Could not find id matching fingerprint " + fingerprint, Payload: ""} respond(enc, resp) } + +func sendNotifications() { + log.Debug("Started toast notification routine") + + var notificationTicker *time.Ticker = nil + var notificationEndTicker *time.Ticker = nil + notificationMap := make(map[string]cziti.ToastNotification) + + timerStop := make(chan bool) + timerStart := time.Now() + + for { + select { + case <- shutdown: + log.Debugf("Exiting Notification Alert loop") + return + case notification := <- cziti.ToastNotifications: + log.Infof("Notification Message : %s, timeout %d", notification.Message, notification.TimeOut) + + if _, ok := notificationMap["mfaTimeOut"]; ok { + if notification.TimeOut < ( notificationMap["mfaTimeOut"].TimeOut - int(time.Since(timerStart).Seconds() - 60) ) || + notification.TimeOut > ( notificationMap["mfaTimeOut"].TimeOut - int(time.Since(timerStart).Seconds() + 60) ) { + notificationMap["mfaTimeOut"] = notification + notificationEndTicker.Reset(time.Duration(notification.TimeOut)) + } + } + + if _, ok := notificationMap["mfaTimeOut"]; !ok { + notificationMap["mfaTimeOut"] = notification + timerStart = time.Now() + + // get frequency 300 from config, get it from ui and save it in config + notificationTicker = time.NewTicker(time.Duration(300) * time.Second) + + go func () { + for { + select { + case <- shutdown: + log.Debugf("shutdown request received, exiting notification ticker loop") + return + case <- timerStop: + notificationTicker.Stop() + log.Debugf("timer is stopped, exiting notification ticker loop") + notificationTicker = nil + delete(notificationMap, "mfaTimeOut") + return + case <- notificationTicker.C: + log.Infof("Notification Message to be sent to UI %s", notificationMap["mfaTimeOut"]) + + // should send a toast message to UI + // should send a toast message to windows + } + } + + }() + notificationEndTicker = time.NewTicker(time.Duration(notification.TimeOut) * time.Second) + go func () { + for { + select { + case <- shutdown: + log.Debugf("shutdown request received, exiting notification ticker loop") + return + case <- notificationEndTicker.C: + log.Infof("Stopping all MFA Notification timers") + notificationEndTicker.Stop() + notificationEndTicker = nil + close(timerStop) + return + } + } + }() + } + } + } +} From ac9e30706a70624e7b94d0617fc4ea1f377bb558 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Wed, 14 Jul 2021 18:49:55 +0530 Subject: [PATCH 16/46] send notification and status message to UI --- service/cziti/sdk.go | 51 ++++++++++--- service/ziti-tunnel/service/ipc.go | 109 +++++++++++++++++++-------- service/ziti-tunnel/service/state.go | 16 ++++ 3 files changed, 135 insertions(+), 41 deletions(-) diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 1a0760e8..cf535aa7 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -54,6 +54,7 @@ import ( "os" "strings" "sync" + "time" "unsafe" ) @@ -83,9 +84,18 @@ type BulkServiceChange struct { } type ToastNotification struct { - Message string - TimeOut int - Severity string + IdentityName string + Fingerprint string + Message string + MinimumTimeOut int + AllServicesTimeout int + NotificationTime time.Time + Severity string +} + +type TunnelNotificationEvent struct { + Op string + Notification []ToastNotification } var _impl sdk @@ -524,7 +534,8 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { servicesToAdd = append(servicesToAdd, svcToAdd) } } - minimumTimeout := 0 + minimumTimeout := -1 + allServicesTimeout := -1 for i := 0; true; i++ { added := C.ziti_service_array_get(srvEvent.added, C.int(i)) if unsafe.Pointer(added) == C.NULL { @@ -532,8 +543,13 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { } svcToAdd := serviceCB(ztx, added, C.ZITI_OK, zid) if svcToAdd != nil { - if svcToAdd.Timeout >= 0 && (minimumTimeout == 0 || minimumTimeout >= svcToAdd.Timeout) { - minimumTimeout = svcToAdd.Timeout + if svcToAdd.Timeout >= 0 { + if minimumTimeout == -1 || minimumTimeout >= svcToAdd.Timeout { + minimumTimeout = svcToAdd.Timeout + } + if allServicesTimeout == -1 || allServicesTimeout <= svcToAdd.Timeout { + allServicesTimeout = svcToAdd.Timeout + } } addAddys := svcToAdd.Addresses for _, toAdd := range addAddys { @@ -544,7 +560,7 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { servicesToAdd = append(servicesToAdd, svcToAdd) } } - if len(servicesToAdd) > 0 && minimumTimeout > 0 { + if len(servicesToAdd) > 0 && minimumTimeout > -1 { for _, svcAdded := range servicesToAdd { if svcAdded.Timeout == minimumTimeout && len(servicesTimingOut) < cap(servicesTimingOut) { servicesTimingOut = append(servicesTimingOut, svcAdded.Name) @@ -553,12 +569,25 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { break } } - toastNotificationMsg := ToastNotification { - Message: fmt.Sprintf("Some of the services (%v) are timing out in sometime", servicesTimingOut), - TimeOut: minimumTimeout, + ToastNotifications <- ToastNotification { + IdentityName: zid.Name, + Fingerprint: zid.Fingerprint, + Message: fmt.Sprintf("Some of the services, eg: %v of Identity %s are timing out in some time", servicesTimingOut, zid.Name), + MinimumTimeOut: minimumTimeout, + AllServicesTimeout: allServicesTimeout, + NotificationTime: time.Now(), Severity: "Major", } - ToastNotifications <- toastNotificationMsg + } else { + ToastNotifications <- ToastNotification { + IdentityName: zid.Name, + Fingerprint: zid.Fingerprint, + Message: fmt.Sprintf("No timeout set for the services of Identity %s", zid.Name), + MinimumTimeOut: minimumTimeout, + AllServicesTimeout: allServicesTimeout, + NotificationTime: time.Now(), + Severity: "Info", + } } svcChange := BulkServiceChange{ diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 81365f65..2c32ec0c 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -1230,12 +1230,11 @@ func sendIdentityAndNotifyUI(enc *json.Encoder, fingerprint string) { func sendNotifications() { log.Debug("Started toast notification routine") + var runtimeStatusTicker *time.Ticker = nil var notificationTicker *time.Ticker = nil - var notificationEndTicker *time.Ticker = nil notificationMap := make(map[string]cziti.ToastNotification) timerStop := make(chan bool) - timerStart := time.Now() for { select { @@ -1243,23 +1242,59 @@ func sendNotifications() { log.Debugf("Exiting Notification Alert loop") return case notification := <- cziti.ToastNotifications: - log.Infof("Notification Message : %s, timeout %d", notification.Message, notification.TimeOut) + log.Infof("Notification Message : %s, lowest timeout %d, all services timeout : %d", notification.Message, notification.MinimumTimeOut, notification.AllServicesTimeout) - if _, ok := notificationMap["mfaTimeOut"]; ok { - if notification.TimeOut < ( notificationMap["mfaTimeOut"].TimeOut - int(time.Since(timerStart).Seconds() - 60) ) || - notification.TimeOut > ( notificationMap["mfaTimeOut"].TimeOut - int(time.Since(timerStart).Seconds() + 60) ) { - notificationMap["mfaTimeOut"] = notification - notificationEndTicker.Reset(time.Duration(notification.TimeOut)) + // if timeout is -1, remove it from the notification map and close all timers is the map is empty + if notification.MinimumTimeOut == -1 { + if _, ok := notificationMap[notification.Fingerprint]; ok { + delete(notificationMap, notification.Fingerprint) + + if len(notificationMap) == 0 { + log.Tracef("Closing all the notification timers") + close(timerStop) + } } + break } - if _, ok := notificationMap["mfaTimeOut"]; !ok { - notificationMap["mfaTimeOut"] = notification - timerStart = time.Now() + if len(notificationMap) > 0 { + notificationMap[notification.Fingerprint] = notification + } + + if len(notificationMap) == 0 { + notificationMap[notification.Fingerprint] = notification + + // update the timeout in the runtime state and send runtime status to UI every 5 minutes + runtimeStatusTicker = time.NewTicker(time.Duration(300) * time.Second) // get frequency 300 from config, get it from ui and save it in config notificationTicker = time.NewTicker(time.Duration(300) * time.Second) + // send runtime status to UI every 5 minutes + go func () { + for { + select { + case <- shutdown: + log.Debugf("shutdown request received, exiting notification ticker loop") + return + case <- timerStop: + runtimeStatusTicker.Stop() + log.Debugf("timer is stopped, exiting runtime status ticker loop") + runtimeStatusTicker = nil + return + case <- runtimeStatusTicker.C: + log.Debugf("Runtime status to be sent to UI") + rts.BroadcastEvent(dto.TunnelStatusEvent{ + StatusEvent: dto.StatusEvent{Op: "status"}, + Status: rts.updateTimeOut(notificationMap), + ApiVersion: API_VERSION, + }) + } + } + + }() + + // send notification to UI and windows toast message based on the frequency set by the user go func () { for { select { @@ -1270,33 +1305,47 @@ func sendNotifications() { notificationTicker.Stop() log.Debugf("timer is stopped, exiting notification ticker loop") notificationTicker = nil - delete(notificationMap, "mfaTimeOut") + // remove all elements from map + notificationMap = make(map[string]cziti.ToastNotification) return case <- notificationTicker.C: - log.Infof("Notification Message to be sent to UI %s", notificationMap["mfaTimeOut"]) + cleanNotifications := make([]cziti.ToastNotification, 0) + for k, v := range notificationMap { + newMinTimeOut := 0 + newAllServicesTimeout := 0 + if (v.MinimumTimeOut - int(time.Since(v.NotificationTime).Seconds())) < 0 { + v.Message = fmt.Sprintf("Some of the services of identity %s are timed out", v.IdentityName) + } else { + newMinTimeOut = v.MinimumTimeOut - int(time.Since(v.NotificationTime).Seconds()) + } + if (v.AllServicesTimeout - int(time.Since(v.NotificationTime).Seconds())) < 0 { + v.Message = fmt.Sprintf("All of the services of identity %s are timed out", v.IdentityName) + } else { + newAllServicesTimeout = v.AllServicesTimeout - int(time.Since(v.NotificationTime).Seconds()) + } + notificationMap[k] = v + + cleanNotifications = append(cleanNotifications, cziti.ToastNotification{ + Fingerprint: v.Fingerprint, + IdentityName: v.IdentityName, + Severity: v.Severity, + MinimumTimeOut: newMinTimeOut, + AllServicesTimeout: newAllServicesTimeout, + NotificationTime: v.NotificationTime, + }) + } + log.Debugf("Sending notification message to be sent to UI %v", cleanNotifications) + rts.BroadcastEvent(cziti.TunnelNotificationEvent{ + Op: "notification", + Notification: cleanNotifications, + }) - // should send a toast message to UI // should send a toast message to windows } } }() - notificationEndTicker = time.NewTicker(time.Duration(notification.TimeOut) * time.Second) - go func () { - for { - select { - case <- shutdown: - log.Debugf("shutdown request received, exiting notification ticker loop") - return - case <- notificationEndTicker.C: - log.Infof("Stopping all MFA Notification timers") - notificationEndTicker.Stop() - notificationEndTicker = nil - close(timerStop) - return - } - } - }() + } } } diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index 0157a2c5..dac9dacc 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -145,6 +145,22 @@ func (t *RuntimeState) ToStatus(onlyInitialized bool) dto.TunnelStatus { return clean } +func (t *RuntimeState) updateTimeOut(notificationMap map[string]cziti.ToastNotification) dto.TunnelStatus { + clean := t.ToStatus(true) + for _,v := range notificationMap { + for _,id := range clean.Identities { + for _, svc := range id.Services { + if (svc.Timeout - int(time.Since(v.NotificationTime).Seconds())) >= 0 { + svc.Timeout = svc.Timeout - int(time.Since(v.NotificationTime).Seconds()) + } else { + svc.Timeout = 0 + } + } + } + } + return clean +} + func (t *RuntimeState) ToMetrics() dto.TunnelStatus { clean := dto.TunnelStatus{ Identities: make([]*dto.Identity, len(t.ids)), From e8ffb6b433464613c8f81ae98a4d364ac6ffbc1e Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Wed, 14 Jul 2021 13:19:10 -0400 Subject: [PATCH 17/46] add licence, code of conduct, contributing --- CODE_OF_CONDUCT.md | 17 ++++ CONTRIBUTING.md | 6 ++ LICENSE | 201 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..6c34532c --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,17 @@ +# Code of Conduct + +All open source projects managed by NetFoundry share a common [code of +conduct](https://netfoundry.github.io/policies/CODE_OF_CONDUCT.html) which all contributors are expected to follow. +Please be sure you read, understand and adhere to the thoughts expressed therein. + +Individuals acting in any way that is considered in violation of the Code of Conduct will receive corrective actions +appropriate for the violation. It is possible to act in ways which technically do not violate the Code of Conduct but +are clearly against the spirit of the project. These situations will also be considered on a case by case basis and if +necessary the Code of Conduct will be revised accordingly and approrpiate notifications will be made to the community +and to the violator. + +## Violations + +Contributors violating the Code of Conduct will receive public notification of the violation. Continued violations or +aggregious violations of the Code of Conduct will result in the contributor being removed from the contributors list as +well as further contributions being declined. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..03bb09f0 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,6 @@ +# Contributing + +NetFoundry welcomes all and any contributions. All open source projects managed by NetFoundry share a common +[guide for contributions](https://netfoundry.github.io/policies/CONTRIBUTING.html). + +If you are eager to contribute to a NetFoundry-managed open source project please read and act accordingly. diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..93e58374 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2019 NetFoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From 38c925e12689372ff6d4caa78495b9162a0db486 Mon Sep 17 00:00:00 2001 From: ziti-ci Date: Wed, 14 Jul 2021 17:29:10 +0000 Subject: [PATCH 18/46] [ci skip] committing updated version related files --- service/ziti-tunnel/version.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/service/ziti-tunnel/version.go b/service/ziti-tunnel/version.go index 7e46dd86..d4988fb5 100644 --- a/service/ziti-tunnel/version.go +++ b/service/ziti-tunnel/version.go @@ -20,9 +20,9 @@ package main const ( - Version = "1.9.10" - Revision = "307fe37ade59" + Version = "1.9.11" + Revision = "e8ffb6b43346" Branch = "release-next" BuildUser = "" - BuildDate = "2021-07-09 17:03:23" + BuildDate = "2021-07-14 17:23:06" ) From 113b521c2bd47ef650d214af385b20bcc258c03f Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Thu, 15 Jul 2021 16:41:23 +0530 Subject: [PATCH 19/46] notification Messages --- DesktopEdge/MainWindow.xaml.cs | 34 +++- .../DataStructures/DataStructures.cs | 16 ++ .../ServiceClient/DataClient.cs | 12 +- service/cziti/sdk.go | 6 +- service/ziti-tunnel/service/ipc.go | 159 +++++++----------- service/ziti-tunnel/service/state.go | 51 ++++-- 6 files changed, 157 insertions(+), 121 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index c3c02b3d..27ab2a2a 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -506,6 +506,7 @@ namespace ZitiDesktopEdge { serviceClient.OnMfaEvent += ServiceClient_OnMfaEvent; serviceClient.OnLogLevelEvent += ServiceClient_OnLogLevelEvent; serviceClient.OnBulkServiceEvent += ServiceClient_OnBulkServiceEvent; + serviceClient.OnNotificationEvent += ServiceClient_OnNotificationEvent; Application.Current.Properties.Add("ServiceClient", serviceClient); monitorClient = new MonitorClient(); @@ -566,7 +567,38 @@ namespace ZitiDesktopEdge { } } - string nextVersionStr = null; + private void ServiceClient_OnNotificationEvent(object sender, NotificationEvent e) { + var displayMFARequired = false; + foreach (var notification in e.Notification) { + var found = identities.Find(id => id.Fingerprint == notification.Fingerprint); + if (found == null) { + logger.Warn($"{e.Op} event for {notification.Fingerprint} but the provided identity fingerprint was not found!"); + continue; + } + if (notification.AllServicesTimeout == 0) { + found.MFAInfo.IsAuthenticated = false; + // display mfa token icon + displayMFARequired = true; + } else if (notification.MinimumTimeOut == 0) { + // display option to enter mfa, only few services are timed out + } else { + // display option to enter mfa, only few services are about to timeout + } + } + // we need to display mfa icon for the identities that have all the services timed out. + if (displayMFARequired) { + LoadIdentities(true); + this.Dispatcher.Invoke(() => { + IdentityDetails deets = ((MainWindow)Application.Current.MainWindow).IdentityMenu; + if (deets.IsVisible) { + deets.UpdateView(); + } + }); + } + } + + + string nextVersionStr = null; private void MonitorClient_OnReconnectFailure(object sender, object e) { if (nextVersionStr == null) { // check for the current version diff --git a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs index e8eaa729..957e1b44 100644 --- a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs +++ b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs @@ -321,6 +321,17 @@ namespace ZitiDesktopEdge.DataStructures { } } + public class Notification { + public string IdentityName { get; set; } + public string Fingerprint { get; set; } + public string Message { get; set; } + public int MinimumTimeOut { get; set; } + public int AllServicesTimeout { get; set; } + public string NotificationTime { get; set; } + public string Severity { get; set; } + + } + public class ZitiTunnelStatus : SvcResponse { public TunnelStatus Status { get; set; } @@ -415,6 +426,11 @@ namespace ZitiDesktopEdge.DataStructures { public List Identities { get; set; } } + public class NotificationEvent : StatusEvent { + public List Notification { get; set; } + + } + public class ServiceEvent : ActionEvent { public string Fingerprint { get; set; } public Service Service { get; set; } diff --git a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs index cc1f0695..1afc3e65 100644 --- a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs +++ b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs @@ -36,6 +36,7 @@ namespace ZitiDesktopEdge.ServiceClient { public event EventHandler OnLogLevelEvent; public event EventHandler OnMfaEvent; public event EventHandler OnBulkServiceEvent; + public event EventHandler OnNotificationEvent; protected override void ShutdownEvent(StatusEvent e) { Logger.Debug("Clean shutdown detected from ziti"); @@ -71,6 +72,10 @@ namespace ZitiDesktopEdge.ServiceClient { OnMfaEvent?.Invoke(this, e); } + protected virtual void NotificationEvent(NotificationEvent e) { + OnNotificationEvent?.Invoke(this, e); + } + protected override void ClientConnected(object e) { base.ClientConnected(e); } @@ -366,7 +371,12 @@ namespace ZitiDesktopEdge.ServiceClient { Logger.Debug("mfa event received"); MfaEvent mfa = serializer.Deserialize(jsonReader); MfaEvent(mfa); - break; + break; + case "notification": + Logger.Debug("Notification event received"); + NotificationEvent notificationEvent = serializer.Deserialize(jsonReader); + NotificationEvent(notificationEvent); + break; default: Logger.Debug("unexpected operation! " + evt.Op); break; diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index cf535aa7..369323f2 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -370,9 +370,9 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z log.Tracef("posture check with id %s already in failing posture check map", pcId) for _, pc := range postureChecks { if pc.Id == C.GoString(pq.id) { - if pc.Timeout > int(pq.timeout) { - pc.Timeout = int(pq.timeout) - timeout = pc.Timeout + if timeout == -1 || timeout > int(pq.timeout) { + // pc.Timeout = int(pq.timeout) + timeout = int(pq.timeout) } break } diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 2c32ec0c..162bc6dc 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -1230,123 +1230,82 @@ func sendIdentityAndNotifyUI(enc *json.Encoder, fingerprint string) { func sendNotifications() { log.Debug("Started toast notification routine") - var runtimeStatusTicker *time.Ticker = nil - var notificationTicker *time.Ticker = nil notificationMap := make(map[string]cziti.ToastNotification) + var notificationMutex = &sync.Mutex{} + // change to 5 minutes + broadcastStatusTicker := time.NewTicker(1 * time.Minute) + // allow user to set frequency + broadcastNotificationTicker := time.NewTicker(5 * time.Minute) - timerStop := make(chan bool) for { select { case <- shutdown: log.Debugf("Exiting Notification Alert loop") return + + case <- broadcastStatusTicker.C: + notificationMutex.Lock() + if len(notificationMap) > 0 { + /*rts.BroadcastEvent(dto.TunnelStatusEvent{ + StatusEvent: dto.StatusEvent{Op: "status"}, + Status: rts.StatusWithUpdatedTimeOut(notificationMap), + ApiVersion: API_VERSION, + })*/ + } + notificationMutex.Unlock() + case <- broadcastNotificationTicker.C: + notificationMutex.Lock() + if len(notificationMap) > 0 { + cleanNotifications := make([]cziti.ToastNotification, 0) + for _, v := range notificationMap { + newMinTimeOut := 0 + newAllServicesTimeout := 0 + newMessage := v.Message + if (v.MinimumTimeOut - int(time.Since(v.NotificationTime).Seconds())) < 0 { + newMessage = fmt.Sprintf("Some of the services of identity %s are timed out", v.IdentityName) + } else { + newMinTimeOut = v.MinimumTimeOut - int(time.Since(v.NotificationTime).Seconds()) + } + if (v.AllServicesTimeout - int(time.Since(v.NotificationTime).Seconds())) < 0 { + newMessage = fmt.Sprintf("All of the services of identity %s are timed out", v.IdentityName) + } else { + newAllServicesTimeout = v.AllServicesTimeout - int(time.Since(v.NotificationTime).Seconds()) + } + + cleanNotifications = append(cleanNotifications, cziti.ToastNotification{ + Fingerprint: v.Fingerprint, + IdentityName: v.IdentityName, + Severity: v.Severity, + MinimumTimeOut: newMinTimeOut, + AllServicesTimeout: newAllServicesTimeout, + NotificationTime: v.NotificationTime, + Message: newMessage, + }) + } + log.Debugf("Sending notification message to UI %v", cleanNotifications) + rts.BroadcastEvent(cziti.TunnelNotificationEvent{ + Op: "notification", + Notification: cleanNotifications, + }) + + // should send a toast message to windows + } + notificationMutex.Unlock() + case notification := <- cziti.ToastNotifications: log.Infof("Notification Message : %s, lowest timeout %d, all services timeout : %d", notification.Message, notification.MinimumTimeOut, notification.AllServicesTimeout) - // if timeout is -1, remove it from the notification map and close all timers is the map is empty + notificationMutex.Lock() + // if timeout is -1, remove it from the notification map if notification.MinimumTimeOut == -1 { if _, ok := notificationMap[notification.Fingerprint]; ok { delete(notificationMap, notification.Fingerprint) - - if len(notificationMap) == 0 { - log.Tracef("Closing all the notification timers") - close(timerStop) - } } - break - } - - if len(notificationMap) > 0 { + } else { notificationMap[notification.Fingerprint] = notification } - - if len(notificationMap) == 0 { - notificationMap[notification.Fingerprint] = notification - - // update the timeout in the runtime state and send runtime status to UI every 5 minutes - runtimeStatusTicker = time.NewTicker(time.Duration(300) * time.Second) - - // get frequency 300 from config, get it from ui and save it in config - notificationTicker = time.NewTicker(time.Duration(300) * time.Second) - - // send runtime status to UI every 5 minutes - go func () { - for { - select { - case <- shutdown: - log.Debugf("shutdown request received, exiting notification ticker loop") - return - case <- timerStop: - runtimeStatusTicker.Stop() - log.Debugf("timer is stopped, exiting runtime status ticker loop") - runtimeStatusTicker = nil - return - case <- runtimeStatusTicker.C: - log.Debugf("Runtime status to be sent to UI") - rts.BroadcastEvent(dto.TunnelStatusEvent{ - StatusEvent: dto.StatusEvent{Op: "status"}, - Status: rts.updateTimeOut(notificationMap), - ApiVersion: API_VERSION, - }) - } - } - - }() - - // send notification to UI and windows toast message based on the frequency set by the user - go func () { - for { - select { - case <- shutdown: - log.Debugf("shutdown request received, exiting notification ticker loop") - return - case <- timerStop: - notificationTicker.Stop() - log.Debugf("timer is stopped, exiting notification ticker loop") - notificationTicker = nil - // remove all elements from map - notificationMap = make(map[string]cziti.ToastNotification) - return - case <- notificationTicker.C: - cleanNotifications := make([]cziti.ToastNotification, 0) - for k, v := range notificationMap { - newMinTimeOut := 0 - newAllServicesTimeout := 0 - if (v.MinimumTimeOut - int(time.Since(v.NotificationTime).Seconds())) < 0 { - v.Message = fmt.Sprintf("Some of the services of identity %s are timed out", v.IdentityName) - } else { - newMinTimeOut = v.MinimumTimeOut - int(time.Since(v.NotificationTime).Seconds()) - } - if (v.AllServicesTimeout - int(time.Since(v.NotificationTime).Seconds())) < 0 { - v.Message = fmt.Sprintf("All of the services of identity %s are timed out", v.IdentityName) - } else { - newAllServicesTimeout = v.AllServicesTimeout - int(time.Since(v.NotificationTime).Seconds()) - } - notificationMap[k] = v - - cleanNotifications = append(cleanNotifications, cziti.ToastNotification{ - Fingerprint: v.Fingerprint, - IdentityName: v.IdentityName, - Severity: v.Severity, - MinimumTimeOut: newMinTimeOut, - AllServicesTimeout: newAllServicesTimeout, - NotificationTime: v.NotificationTime, - }) - } - log.Debugf("Sending notification message to be sent to UI %v", cleanNotifications) - rts.BroadcastEvent(cziti.TunnelNotificationEvent{ - Op: "notification", - Notification: cleanNotifications, - }) - - // should send a toast message to windows - } - } - - }() - - } + notificationMutex.Unlock() } } } diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index dac9dacc..4aa909a2 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -145,22 +145,6 @@ func (t *RuntimeState) ToStatus(onlyInitialized bool) dto.TunnelStatus { return clean } -func (t *RuntimeState) updateTimeOut(notificationMap map[string]cziti.ToastNotification) dto.TunnelStatus { - clean := t.ToStatus(true) - for _,v := range notificationMap { - for _,id := range clean.Identities { - for _, svc := range id.Services { - if (svc.Timeout - int(time.Since(v.NotificationTime).Seconds())) >= 0 { - svc.Timeout = svc.Timeout - int(time.Since(v.NotificationTime).Seconds()) - } else { - svc.Timeout = 0 - } - } - } - } - return clean -} - func (t *RuntimeState) ToMetrics() dto.TunnelStatus { clean := dto.TunnelStatus{ Identities: make([]*dto.Identity, len(t.ids)), @@ -560,3 +544,38 @@ func (t *RuntimeState) UpdateMfa(fingerprint string, mfaEnabled bool, mfaNeeded id.MfaNeeded = mfaNeeded } } + +func (t *RuntimeState) StatusWithUpdatedTimeOut(notificationMap map[string]cziti.ToastNotification) dto.TunnelStatus { + clean := t.ToStatus(true) + for _,v := range notificationMap { + for _,id := range clean.Identities { + log.Debugf("Id %s Mfa enabled %t", id.FingerPrint, id.MfaEnabled) + allSvcTimedOut := true + for _, svc := range id.Services { + timeout := -1 + for _, pc := range svc.PostureChecks { + if timeout == -1 || timeout > pc.Timeout { + timeout = pc.Timeout + } + } + if timeout >= 0 { + if (timeout - int(time.Since(v.NotificationTime).Seconds())) >= 0 { + svc.Timeout = timeout - int(time.Since(v.NotificationTime).Seconds()) + allSvcTimedOut = false + } else { + svc.Timeout = 0 + } + } + } + if allSvcTimedOut && id.MfaEnabled { + rts.UpdateMfa(id.FingerPrint, false, true) + + // update mfa in return value + id.MfaEnabled = false + id.MfaNeeded = true + } + } + } + return clean +} + From 5afa04f1b172ac395a01f9a0943c8340922ee569 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Fri, 16 Jul 2021 00:03:50 +0530 Subject: [PATCH 20/46] code review fixes --- service/cziti/sdk.go | 45 ++++++++++++++++++---------- service/ziti-tunnel/dto/dtos.go | 4 +++ service/ziti-tunnel/service/ipc.go | 44 ++++++++++++++++++++++++--- service/ziti-tunnel/service/state.go | 34 --------------------- 4 files changed, 73 insertions(+), 54 deletions(-) diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 369323f2..e80c218e 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -81,6 +81,9 @@ type BulkServiceChange struct { HostnamesToRemove map[string]bool ServicesToRemove []*dto.Service ServicesToAdd []*dto.Service + MinTimeout int + MaxTimeout int + LastUpdatedTime time.Time } type ToastNotification struct { @@ -135,20 +138,23 @@ type ZService struct { } type ZIdentity struct { - Options *C.ziti_options - czctx C.ziti_context - czid *C.ziti_identity - status int - statusErr error - Loaded bool - Name string - Version string - Services sync.Map - Fingerprint string - Active bool - StatusChanges func(int) - MfaNeeded bool - MfaEnabled bool + Options *C.ziti_options + czctx C.ziti_context + czid *C.ziti_identity + status int + statusErr error + Loaded bool + Name string + Version string + Services sync.Map + Fingerprint string + Active bool + StatusChanges func(int) + MfaNeeded bool + MfaEnabled bool + MinTimeout int + MaxTimeout int + LastUpdatedTime time.Time //mfa *Mfa } @@ -544,10 +550,10 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { svcToAdd := serviceCB(ztx, added, C.ZITI_OK, zid) if svcToAdd != nil { if svcToAdd.Timeout >= 0 { - if minimumTimeout == -1 || minimumTimeout >= svcToAdd.Timeout { + if minimumTimeout == -1 || minimumTimeout > svcToAdd.Timeout { minimumTimeout = svcToAdd.Timeout } - if allServicesTimeout == -1 || allServicesTimeout <= svcToAdd.Timeout { + if allServicesTimeout == -1 || allServicesTimeout < svcToAdd.Timeout { allServicesTimeout = svcToAdd.Timeout } } @@ -590,12 +596,19 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { } } + zid.MinTimeout = minimumTimeout + zid.MaxTimeout = allServicesTimeout + zid.LastUpdatedTime = time.Now() + svcChange := BulkServiceChange{ Fingerprint: zid.Fingerprint, HostnamesToAdd: hostnamesToAdd, HostnamesToRemove: hostnamesToRemove, ServicesToAdd: servicesToAdd, ServicesToRemove: servicesToRemove, + MinTimeout: minimumTimeout, + MaxTimeout: allServicesTimeout, + LastUpdatedTime: time.Now(), } if len(BulkServiceChanges) == cap(BulkServiceChanges) { diff --git a/service/ziti-tunnel/dto/dtos.go b/service/ziti-tunnel/dto/dtos.go index b0da0629..c407e1fa 100644 --- a/service/ziti-tunnel/dto/dtos.go +++ b/service/ziti-tunnel/dto/dtos.go @@ -19,6 +19,7 @@ package dto import ( "log" + "time" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/config" idcfg "github.com/openziti/sdk-golang/ziti/config" @@ -81,6 +82,9 @@ type Identity struct { Services []*Service `json:",omitempty"` Metrics *Metrics `json:",omitempty"` Tags []string `json:",omitempty"` + MinTimeout int + MaxTimeout int + LastUpdatedTime time.Time } type Metrics struct { Up int64 diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 162bc6dc..764e725a 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -1162,12 +1162,48 @@ func Clean(src *Id) dto.Identity { } if src.CId != nil { + minTimeout := -1 + maxTimeout := -1 + allSvcTimeout := -1 src.CId.Services.Range(func(key interface{}, value interface{}) bool { //string, ZService val := value.(*cziti.ZService) + timeout := -1 + + for _, pc := range val.Service.PostureChecks { + if timeout == -1 || timeout > pc.Timeout { + timeout = pc.Timeout + } + } + if (timeout - int(time.Since(src.CId.LastUpdatedTime).Seconds())) < 0 { + val.Service.Timeout = 0 + } else { + val.Service.Timeout = timeout - int(time.Since(src.CId.LastUpdatedTime).Seconds()) + } + if allSvcTimeout == -1 || allSvcTimeout < val.Service.Timeout { + allSvcTimeout = val.Service.Timeout + } + if minTimeout == -1 || minTimeout > timeout { + minTimeout = timeout + } + if maxTimeout == -1 || maxTimeout < timeout { + maxTimeout = timeout + } + nid.Services = append(nid.Services /*svcToDto(val)*/, val.Service) return true }) + nid.MinTimeout = minTimeout + nid.MaxTimeout = maxTimeout + if minTimeout == -1 && maxTimeout == -1 { + nid.LastUpdatedTime = time.Now() + } else { + nid.LastUpdatedTime = src.CId.LastUpdatedTime + } + + if allSvcTimeout == 0 && nid.MfaEnabled { + nid.MfaNeeded = true + } } nid.Config.ZtAPI = src.Config.ZtAPI @@ -1232,7 +1268,6 @@ func sendNotifications() { notificationMap := make(map[string]cziti.ToastNotification) var notificationMutex = &sync.Mutex{} - // change to 5 minutes broadcastStatusTicker := time.NewTicker(1 * time.Minute) // allow user to set frequency broadcastNotificationTicker := time.NewTicker(5 * time.Minute) @@ -1247,11 +1282,12 @@ func sendNotifications() { case <- broadcastStatusTicker.C: notificationMutex.Lock() if len(notificationMap) > 0 { - /*rts.BroadcastEvent(dto.TunnelStatusEvent{ + clean := rts.ToStatus(true) + rts.BroadcastEvent(dto.TunnelStatusEvent{ StatusEvent: dto.StatusEvent{Op: "status"}, - Status: rts.StatusWithUpdatedTimeOut(notificationMap), + Status: clean, ApiVersion: API_VERSION, - })*/ + }) } notificationMutex.Unlock() case <- broadcastNotificationTicker.C: diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index 4aa909a2..b979cd86 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -545,37 +545,3 @@ func (t *RuntimeState) UpdateMfa(fingerprint string, mfaEnabled bool, mfaNeeded } } -func (t *RuntimeState) StatusWithUpdatedTimeOut(notificationMap map[string]cziti.ToastNotification) dto.TunnelStatus { - clean := t.ToStatus(true) - for _,v := range notificationMap { - for _,id := range clean.Identities { - log.Debugf("Id %s Mfa enabled %t", id.FingerPrint, id.MfaEnabled) - allSvcTimedOut := true - for _, svc := range id.Services { - timeout := -1 - for _, pc := range svc.PostureChecks { - if timeout == -1 || timeout > pc.Timeout { - timeout = pc.Timeout - } - } - if timeout >= 0 { - if (timeout - int(time.Since(v.NotificationTime).Seconds())) >= 0 { - svc.Timeout = timeout - int(time.Since(v.NotificationTime).Seconds()) - allSvcTimedOut = false - } else { - svc.Timeout = 0 - } - } - } - if allSvcTimedOut && id.MfaEnabled { - rts.UpdateMfa(id.FingerPrint, false, true) - - // update mfa in return value - id.MfaEnabled = false - id.MfaNeeded = true - } - } - } - return clean -} - From 048e4c4d93eeef24b85fa74b0f2f7d180656593c Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Fri, 16 Jul 2021 14:51:35 +0530 Subject: [PATCH 21/46] removing commented code --- service/cziti/mfa.go | 83 ---------------------------- service/cziti/sdk.go | 32 ----------- service/ziti-tunnel/service/ipc.go | 89 ++++++++++++------------------ 3 files changed, 36 insertions(+), 168 deletions(-) diff --git a/service/cziti/mfa.go b/service/cziti/mfa.go index e4dabb55..be067a7d 100644 --- a/service/cziti/mfa.go +++ b/service/cziti/mfa.go @@ -46,47 +46,6 @@ type mfaCodes struct { var emptyCodes []string var mfaAuthResults = make(chan string) -//var mfaOldAuthResults = make(chan string) - -//export -/* -func ziti_aq_mfa_cb_go(ztx C.ziti_context, mfa_ctx unsafe.Pointer, aq_mfa *C.ziti_auth_query_mfa, response_cb C.ziti_ar_mfa_cb) { - appCtx := C.ziti_app_ctx(ztx) - if appCtx != C.NULL { - log.Debugf("mfa requested for ziti context %p.", ztx) - zid := (*ZIdentity)(appCtx) - mfa := &Mfa{ - mfaContext: mfa_ctx, - authQuery: aq_mfa, - responseCb: response_cb, - } - zid.mfa = mfa - zid.MfaNeeded = true - zid.MfaEnabled = true - - if zid.Fingerprint != "" { - var id = dto.Identity{ - Name: zid.Name, - FingerPrint: zid.Fingerprint, - Active: zid.Active, - ControllerVersion: zid.Version, - Status: "", - MfaNeeded: true, - MfaEnabled: true, - Tags: nil, - } - - var m = dto.IdentityEvent{ - ActionEvent: dto.IDENTITY_ADDED, - Id: id, - } - goapi.BroadcastEvent(m) - } - log.Debugf("mfa enabled/needed set to true for ziti context [%p]. Identity name:%s [fingerprint: %s]", zid, zid.Name, zid.Fingerprint) - } else { - log.Debugf("mfa requested for ziti context/mfa context [%p, %p] but the context was NOT found in the map. This is unexpected. Please report.", ztx, mfa_ctx) - } -}*/ func EnableMFA(id *ZIdentity) { C.ziti_mfa_enroll(id.czctx, C.ziti_mfa_cb(C.ziti_mfa_enroll_cb_go), unsafe.Pointer(C.CString(id.Fingerprint))) @@ -307,48 +266,6 @@ func populateStringSlice(c_char_array **C.char) []string { return strs } -/*func AuthMFA_old(id *ZIdentity, code string) error { - if id.mfa == nil { - log.Warnf("AuthMFA called but mfa is nil. This usually is because AuthMFA is called from an unenrolled MFA endpoint or the endpoint has already been auth'ed") - return fmt.Errorf("identity has not authenticated yet") - } - if id.mfa.responseCb == nil { - log.Warnf("AuthMFA called but response cb is nil. This usually is because the session is already validiated. returning true from AuthMFA") - return nil - } - - ccode := C.CString(code) - defer C.free(unsafe.Pointer(ccode)) - - cfp := C.CString(id.Fingerprint) - defer C.free(unsafe.Pointer(cfp)) - log.Debugf("beginning authentication for fingerprint %s with code %s", id.Fingerprint, code) - C.ziti_mfa_auth_request(id.mfa.responseCb, id.czctx, id.mfa.mfaContext, ccode, C.ziti_ar_mfa_status_cb(C.ziti_ar_mfa_status_cb_go), cfp) - authResult := strings.TrimSpace(<-mfaOldAuthResults) - - if authResult == "" { - id.mfa.responseCb = nil - id.MfaNeeded = false - return nil - } - return fmt.Errorf("error in authMFA: %v", authResult) -} - -//export ziti_ar_mfa_status_cb_go -func ziti_ar_mfa_status_cb_go(ztx C.ziti_context, mfa_ctx unsafe.Pointer, status C.int, cFingerprint *C.char) { - fp := C.GoString(cFingerprint) - log.Debugf("ziti_ar_mfa_status_cb_go called for fingerprint: %s with status %v", fp, status) - if status == C.ZITI_OK { - log.Infof("mfa authentication succeeded for fingerprint: %s", fp) - mfaOldAuthResults <- "" - } else { - log.Warnf("mfa authentication failed for fingerprint: %s", fp) - e := C.ziti_errorstr(status) - ego := C.GoString(e) - mfaOldAuthResults <- ego - } -}*/ - func RemoveMFA(id *ZIdentity, code string) { ccode := C.CString(code) defer C.free(unsafe.Pointer(ccode)) diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index e80c218e..f7010744 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -46,7 +46,6 @@ import "C" import ( "encoding/json" "errors" - "fmt" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/api" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/util/logging" @@ -62,7 +61,6 @@ var log = logging.Logger() var noFileLog = logging.NoFilenameLogger() var Version dto.ServiceVersion var BulkServiceChanges = make(chan BulkServiceChange, 32) -var ToastNotifications = make(chan ToastNotification, 32) var cCfgZitiTunnelerClientV1 = C.CString("ziti-tunneler-client.v1") var cCfgInterceptV1 = C.CString("intercept.v1") @@ -489,7 +487,6 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { hostnamesToRemove := make(map[string]bool) servicesToRemove := make([]*dto.Service, 0) servicesToAdd := make([]*dto.Service, 0) - servicesTimingOut := make([]string, 0, 3) srvEvent := C.ziti_event_service_event(event) @@ -566,35 +563,6 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { servicesToAdd = append(servicesToAdd, svcToAdd) } } - if len(servicesToAdd) > 0 && minimumTimeout > -1 { - for _, svcAdded := range servicesToAdd { - if svcAdded.Timeout == minimumTimeout && len(servicesTimingOut) < cap(servicesTimingOut) { - servicesTimingOut = append(servicesTimingOut, svcAdded.Name) - } - if len(servicesTimingOut) == cap(servicesTimingOut) { - break - } - } - ToastNotifications <- ToastNotification { - IdentityName: zid.Name, - Fingerprint: zid.Fingerprint, - Message: fmt.Sprintf("Some of the services, eg: %v of Identity %s are timing out in some time", servicesTimingOut, zid.Name), - MinimumTimeOut: minimumTimeout, - AllServicesTimeout: allServicesTimeout, - NotificationTime: time.Now(), - Severity: "Major", - } - } else { - ToastNotifications <- ToastNotification { - IdentityName: zid.Name, - Fingerprint: zid.Fingerprint, - Message: fmt.Sprintf("No timeout set for the services of Identity %s", zid.Name), - MinimumTimeOut: minimumTimeout, - AllServicesTimeout: allServicesTimeout, - NotificationTime: time.Now(), - Severity: "Info", - } - } zid.MinTimeout = minimumTimeout zid.MaxTimeout = allServicesTimeout diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 764e725a..135b90ae 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -1264,12 +1264,11 @@ func sendIdentityAndNotifyUI(enc *json.Encoder, fingerprint string) { } func sendNotifications() { - log.Debug("Started toast notification routine") + log.Debug("Started notification routine") - notificationMap := make(map[string]cziti.ToastNotification) var notificationMutex = &sync.Mutex{} broadcastStatusTicker := time.NewTicker(1 * time.Minute) - // allow user to set frequency + // allow user to set frequency dynamically broadcastNotificationTicker := time.NewTicker(5 * time.Minute) @@ -1281,67 +1280,51 @@ func sendNotifications() { case <- broadcastStatusTicker.C: notificationMutex.Lock() - if len(notificationMap) > 0 { - clean := rts.ToStatus(true) - rts.BroadcastEvent(dto.TunnelStatusEvent{ - StatusEvent: dto.StatusEvent{Op: "status"}, - Status: clean, - ApiVersion: API_VERSION, - }) - } + clean := rts.ToStatus(true) notificationMutex.Unlock() + + rts.BroadcastEvent(dto.TunnelStatusEvent{ + StatusEvent: dto.StatusEvent{Op: "status"}, + Status: clean, + ApiVersion: API_VERSION, + }) + case <- broadcastNotificationTicker.C: notificationMutex.Lock() - if len(notificationMap) > 0 { - cleanNotifications := make([]cziti.ToastNotification, 0) - for _, v := range notificationMap { - newMinTimeOut := 0 - newAllServicesTimeout := 0 - newMessage := v.Message - if (v.MinimumTimeOut - int(time.Since(v.NotificationTime).Seconds())) < 0 { - newMessage = fmt.Sprintf("Some of the services of identity %s are timed out", v.IdentityName) - } else { - newMinTimeOut = v.MinimumTimeOut - int(time.Since(v.NotificationTime).Seconds()) - } - if (v.AllServicesTimeout - int(time.Since(v.NotificationTime).Seconds())) < 0 { - newMessage = fmt.Sprintf("All of the services of identity %s are timed out", v.IdentityName) - } else { - newAllServicesTimeout = v.AllServicesTimeout - int(time.Since(v.NotificationTime).Seconds()) - } + clean := rts.ToStatus(true) + notificationMutex.Unlock() - cleanNotifications = append(cleanNotifications, cziti.ToastNotification{ - Fingerprint: v.Fingerprint, - IdentityName: v.IdentityName, - Severity: v.Severity, - MinimumTimeOut: newMinTimeOut, - AllServicesTimeout: newAllServicesTimeout, - NotificationTime: v.NotificationTime, - Message: newMessage, - }) + cleanNotifications := make([]cziti.ToastNotification, 0) + + notificationMessage := "" + for _, id := range clean.Identities { + + if (id.MaxTimeout - int(time.Since(id.LastUpdatedTime).Seconds())) < 0 { + notificationMessage = fmt.Sprintf("All of the services of identity %s are timed out", id.Name) + } else if (id.MinTimeout - int(time.Since(id.LastUpdatedTime).Seconds())) < 0 { + notificationMessage = fmt.Sprintf("Some of the services of identity %s are timed out", id.Name) + } else if (id.MinTimeout - int(time.Since(id.LastUpdatedTime).Seconds())) < int(time.Duration(20 * time.Minute)) { + notificationMessage = fmt.Sprintf("Some of the services of identity %s are timing out in sometime", id.Name) } + + cleanNotifications = append(cleanNotifications, cziti.ToastNotification{ + Fingerprint: id.FingerPrint, + IdentityName: id.Name, + Severity: "major", + MinimumTimeOut: id.MinTimeout, + AllServicesTimeout: id.MaxTimeout, + Message: notificationMessage, + }) + + } + if len(cleanNotifications) > 0 { log.Debugf("Sending notification message to UI %v", cleanNotifications) rts.BroadcastEvent(cziti.TunnelNotificationEvent{ Op: "notification", Notification: cleanNotifications, }) - - // should send a toast message to windows } - notificationMutex.Unlock() - - case notification := <- cziti.ToastNotifications: - log.Infof("Notification Message : %s, lowest timeout %d, all services timeout : %d", notification.Message, notification.MinimumTimeOut, notification.AllServicesTimeout) - - notificationMutex.Lock() - // if timeout is -1, remove it from the notification map - if notification.MinimumTimeOut == -1 { - if _, ok := notificationMap[notification.Fingerprint]; ok { - delete(notificationMap, notification.Fingerprint) - } - } else { - notificationMap[notification.Fingerprint] = notification - } - notificationMutex.Unlock() + // should send a toast message to windows } } } From 46d64a8d626669d577c4bce76bb3638db1fafc82 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Fri, 16 Jul 2021 18:06:18 +0530 Subject: [PATCH 22/46] code review changes --- service/cziti/mfa.c | 24 ----- service/cziti/sdk.go | 28 +++--- service/cziti/sdk.h | 2 - service/ziti-tunnel/service/ipc.go | 126 ++++++++++++++++----------- service/ziti-tunnel/service/state.go | 37 ++++++++ 5 files changed, 124 insertions(+), 93 deletions(-) delete mode 100644 service/cziti/mfa.c diff --git a/service/cziti/mfa.c b/service/cziti/mfa.c deleted file mode 100644 index 52fdefbd..00000000 --- a/service/cziti/mfa.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright NetFoundry, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -/* -#include "sdk.h" -#include -#include - -void ziti_mfa_auth_request(ziti_ar_mfa_cb response_cb, ziti_context ztx, void *mfa_ctx, char *code, ziti_ar_mfa_status_cb auth_response, char *fingerprint) { - response_cb(ztx, mfa_ctx, code, auth_response, fingerprint); -}*/ \ No newline at end of file diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index f7010744..d7b042b4 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -61,6 +61,7 @@ var log = logging.Logger() var noFileLog = logging.NoFilenameLogger() var Version dto.ServiceVersion var BulkServiceChanges = make(chan BulkServiceChange, 32) +var TimeoutPostureChecks = make(chan map[string]bool) var cCfgZitiTunnelerClientV1 = C.CString("ziti-tunneler-client.v1") var cCfgInterceptV1 = C.CString("intercept.v1") @@ -90,7 +91,7 @@ type ToastNotification struct { Message string MinimumTimeOut int AllServicesTimeout int - NotificationTime time.Time + TimeDuration int Severity string } @@ -153,15 +154,8 @@ type ZIdentity struct { MinTimeout int MaxTimeout int LastUpdatedTime time.Time - //mfa *Mfa } -/*type Mfa struct { - mfaContext unsafe.Pointer - authQuery *C.ziti_auth_query_mfa - responseCb C.ziti_ar_mfa_cb -}*/ - func NewZid(statusChange func(int)) *ZIdentity { zid := &ZIdentity{} zid.Services = sync.Map{} @@ -568,6 +562,16 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { zid.MaxTimeout = allServicesTimeout zid.LastUpdatedTime = time.Now() + if minimumTimeout == -1 && allServicesTimeout == -1 { + TimeoutPostureChecks <- map[string]bool { + zid.Fingerprint: false, + } + } else { + TimeoutPostureChecks <- map[string]bool { + zid.Fingerprint: true, + } + } + svcChange := BulkServiceChange{ Fingerprint: zid.Fingerprint, HostnamesToAdd: hostnamesToAdd, @@ -587,12 +591,6 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { case C.ZitiMfaAuthEvent: zid := (*ZIdentity)(appCtx) log.Debugf("mfa auth event for finger print %s", zid.Fingerprint) - /*mfa := &Mfa{ - mfaContext: mfa_ctx, - authQuery: aq_mfa, - responseCb: response_cb, - } - zid.mfa = mfa*/ zid.MfaNeeded = true zid.MfaEnabled = true @@ -663,8 +661,6 @@ func LoadZiti(zid *ZIdentity, cfg string, refreshInterval int) { zid.Options.events = C.ZitiContextEvent | C.ZitiServiceEvent | C.ZitiRouterEvent | C.ZitiMfaAuthEvent zid.Options.event_cb = C.ziti_event_cb(C.eventCB) - // zid.Options.aq_mfa_cb = C.ziti_aq_mfa_cb(C.ziti_aq_mfa_cb_go) - ptr := unsafe.Pointer(zid) zid.Options.app_ctx = ptr diff --git a/service/cziti/sdk.h b/service/cziti/sdk.h index a60aedce..d57ca5e3 100644 --- a/service/cziti/sdk.h +++ b/service/cziti/sdk.h @@ -75,13 +75,11 @@ ziti_service* ziti_service_array_get(ziti_service_array arr, int idx); void ziti_dump_go(char *msg); //declare all mfa callbacks -//void ziti_aq_mfa_cb_go(ziti_context ztx, void *mfa_ctx, ziti_auth_query_mfa *aq_mfa, ziti_ar_mfa_cb response_cb); void ziti_mfa_enroll_cb_go(ziti_context ztx, int status, ziti_mfa_enrollment *mfa_enrollment, char *fingerprint); void ziti_mfa_cb_verify_go(ziti_context ztx, int status, char *fingerprint); void ziti_mfa_cb_remove_go(ziti_context ztx, int status, char *fingerprint); void ziti_mfa_recovery_codes_cb_return(ziti_context ztx, int status, char **recovery_codes, char *fingerprint); void ziti_mfa_recovery_codes_cb_generate(ziti_context ztx, int status, char **recovery_codes, char *fingerprint); -//void ziti_mfa_auth_request(ziti_ar_mfa_cb response_cb, ziti_context ztx, void *mfa_ctx, char *code, ziti_ar_mfa_status_cb auth_response, char *fingerprint); void ziti_mfa_ar_cb(ziti_context ztx, void *mfa_ctx, int status); void ziti_ar_mfa_status_cb_go(ziti_context ztx, void *mfa_ctx, int status, char *fingerprint); void ziti_auth_mfa_status_cb_go(ziti_context ztx, int status, char *fingerprint); diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 135b90ae..2d37f2d1 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -102,7 +102,7 @@ func SubMain(ops chan string, changes chan<- svc.Status, winEvents <-chan Window //listen for services that show up go acceptServices() - go sendNotifications() + go rts.CheckTimeOuts() // listen for windows power events and call mfa auth func go func() { @@ -1263,68 +1263,92 @@ func sendIdentityAndNotifyUI(enc *json.Encoder, fingerprint string) { respond(enc, resp) } -func sendNotifications() { +func StartRefreshTimer() { + + RuntimeStatusTicker := time.NewTicker(time.Duration(1) * time.Minute) + log.Debugf("starting service timeout refresh routine") + + go func () { + for { + select { + case <- shutdown: + log.Debugf("shutdown request received, exiting refresh timer routine") + return + case <- RuntimeTimerStop: + RuntimeStatusTicker.Stop() + log.Debugf("timer is stopped, exiting runtime status ticker loop") + RuntimeStatusTicker = nil + return + case <- RuntimeStatusTicker.C: + clean := rts.ToStatus(true) + rts.BroadcastEvent(dto.TunnelStatusEvent{ + StatusEvent: dto.StatusEvent{Op: "status"}, + Status: clean, + ApiVersion: API_VERSION, + }) + } + } + } () +} + +func SendNotifications() { log.Debug("Started notification routine") - var notificationMutex = &sync.Mutex{} - broadcastStatusTicker := time.NewTicker(1 * time.Minute) // allow user to set frequency dynamically broadcastNotificationTicker := time.NewTicker(5 * time.Minute) + go func(){ + for { + select { + case <- shutdown: + log.Debugf("Exiting Notification Alert loop") + return + case <- RuntimeTimerStop: + broadcastNotificationTicker.Stop() + log.Debugf("timer is stopped, exiting Notifications ticker loop") + broadcastNotificationTicker = nil + return + case <- broadcastNotificationTicker.C: + clean := rts.ToStatus(true) - for { - select { - case <- shutdown: - log.Debugf("Exiting Notification Alert loop") - return + cleanNotifications := make([]cziti.ToastNotification, 0) - case <- broadcastStatusTicker.C: - notificationMutex.Lock() - clean := rts.ToStatus(true) - notificationMutex.Unlock() + notificationMessage := "" + for _, id := range clean.Identities { - rts.BroadcastEvent(dto.TunnelStatusEvent{ - StatusEvent: dto.StatusEvent{Op: "status"}, - Status: clean, - ApiVersion: API_VERSION, - }) + if id.MaxTimeout == -1 && id.MinTimeout == -1 { + continue + } - case <- broadcastNotificationTicker.C: - notificationMutex.Lock() - clean := rts.ToStatus(true) - notificationMutex.Unlock() + if (id.MaxTimeout - int(time.Since(id.LastUpdatedTime).Seconds())) < 0 { + notificationMessage = fmt.Sprintf("All of the services of identity %s are timed out", id.Name) + } else if (id.MinTimeout - int(time.Since(id.LastUpdatedTime).Seconds())) < 0 { + notificationMessage = fmt.Sprintf("Some of the services of identity %s are timed out", id.Name) + } else if (id.MinTimeout - int(time.Since(id.LastUpdatedTime).Seconds())) < int(time.Duration(20 * time.Minute)) { + notificationMessage = fmt.Sprintf("Some of the services of identity %s are timing out in sometime", id.Name) + } - cleanNotifications := make([]cziti.ToastNotification, 0) + cleanNotifications = append(cleanNotifications, cziti.ToastNotification{ + Fingerprint: id.FingerPrint, + IdentityName: id.Name, + Severity: "major", + MinimumTimeOut: id.MinTimeout, + AllServicesTimeout: id.MaxTimeout, + Message: notificationMessage, + TimeDuration: int(time.Since(id.LastUpdatedTime).Seconds()), + }) - notificationMessage := "" - for _, id := range clean.Identities { - - if (id.MaxTimeout - int(time.Since(id.LastUpdatedTime).Seconds())) < 0 { - notificationMessage = fmt.Sprintf("All of the services of identity %s are timed out", id.Name) - } else if (id.MinTimeout - int(time.Since(id.LastUpdatedTime).Seconds())) < 0 { - notificationMessage = fmt.Sprintf("Some of the services of identity %s are timed out", id.Name) - } else if (id.MinTimeout - int(time.Since(id.LastUpdatedTime).Seconds())) < int(time.Duration(20 * time.Minute)) { - notificationMessage = fmt.Sprintf("Some of the services of identity %s are timing out in sometime", id.Name) } - - cleanNotifications = append(cleanNotifications, cziti.ToastNotification{ - Fingerprint: id.FingerPrint, - IdentityName: id.Name, - Severity: "major", - MinimumTimeOut: id.MinTimeout, - AllServicesTimeout: id.MaxTimeout, - Message: notificationMessage, - }) - + if len(cleanNotifications) > 0 { + log.Debugf("Sending notification message to UI %v", cleanNotifications) + rts.BroadcastEvent(cziti.TunnelNotificationEvent{ + Op: "notification", + Notification: cleanNotifications, + }) + } + // should send a toast message to windows } - if len(cleanNotifications) > 0 { - log.Debugf("Sending notification message to UI %v", cleanNotifications) - rts.BroadcastEvent(cziti.TunnelNotificationEvent{ - Op: "notification", - Notification: cleanNotifications, - }) - } - // should send a toast message to windows } - } + }() + } diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index b979cd86..f939bcc3 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -43,6 +43,9 @@ import ( "time" ) +var RuntimeTimerStop = make(chan bool) +var RuntimeStatusTicker *time.Ticker = nil + type RuntimeState struct { state *dto.TunnelStatus tun *tun.Device @@ -545,3 +548,37 @@ func (t *RuntimeState) UpdateMfa(fingerprint string, mfaEnabled bool, mfaNeeded } } +func (t *RuntimeState) CheckTimeOuts() { + go func () { + for { + select { + case <- shutdown: + log.Debugf("Shutting down posture check timeout loop") + return + case timeoutEvent := <- cziti.TimeoutPostureChecks: + + timeoutRefreshRequired := false + for _, id := range rts.ids { + if val, ok := timeoutEvent[id.FingerPrint]; ok { + if val { + timeoutRefreshRequired = true + } + } else { + if id.MinTimeout > -1 || id.MaxTimeout > -1 { + timeoutRefreshRequired = true + } + } + } + if timeoutRefreshRequired { + if RuntimeStatusTicker == nil { + StartRefreshTimer() + SendNotifications() + } + } else { + RuntimeTimerStop <- true + } + } + } + }() +} + From bf425522607940088284430ffbb62ef85489956c Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 19 Jul 2021 12:59:10 +0530 Subject: [PATCH 23/46] moving the tickers to one go routine --- service/cziti/sdk.go | 62 ++++----- service/ziti-tunnel/dto/dtos.go | 6 +- service/ziti-tunnel/service/ipc.go | 201 ++++++++++----------------- service/ziti-tunnel/service/state.go | 44 ++---- service/ziti-tunnel/service/types.go | 2 +- 5 files changed, 121 insertions(+), 194 deletions(-) diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index d7b042b4..33ced0ac 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -61,7 +61,6 @@ var log = logging.Logger() var noFileLog = logging.NoFilenameLogger() var Version dto.ServiceVersion var BulkServiceChanges = make(chan BulkServiceChange, 32) -var TimeoutPostureChecks = make(chan map[string]bool) var cCfgZitiTunnelerClientV1 = C.CString("ziti-tunneler-client.v1") var cCfgInterceptV1 = C.CString("intercept.v1") @@ -80,24 +79,24 @@ type BulkServiceChange struct { HostnamesToRemove map[string]bool ServicesToRemove []*dto.Service ServicesToAdd []*dto.Service - MinTimeout int - MaxTimeout int + MinTimeout int32 + MaxTimeout int32 LastUpdatedTime time.Time } -type ToastNotification struct { +type NotificationMessage struct { IdentityName string Fingerprint string Message string - MinimumTimeOut int - AllServicesTimeout int + MinimumTimeOut int32 + AllServicesTimeout int32 TimeDuration int Severity string } type TunnelNotificationEvent struct { Op string - Notification []ToastNotification + Notification []NotificationMessage } var _impl sdk @@ -129,6 +128,8 @@ func (inst *sdk) run(loglevel int) { C.libuv_run(inst.libuvCtx) } +type RefreshRequiredCheck func(int32, int32) bool + type ZService struct { Name string Id string @@ -151,16 +152,21 @@ type ZIdentity struct { StatusChanges func(int) MfaNeeded bool MfaEnabled bool - MinTimeout int - MaxTimeout int + MinTimeout int32 + MaxTimeout int32 + RefreshCheck RefreshRequiredCheck LastUpdatedTime time.Time } -func NewZid(statusChange func(int)) *ZIdentity { +func NewZid(statusChange func(int), refreshCheck func(int32, int32) bool) *ZIdentity { zid := &ZIdentity{} zid.Services = sync.Map{} zid.Options = (*C.ziti_options)(C.calloc(1, C.sizeof_ziti_options)) zid.StatusChanges = statusChange + zid.RefreshCheck = refreshCheck + zid.MinTimeout = -1 + zid.MaxTimeout = -1 + zid.LastUpdatedTime = time.Now() return zid } @@ -399,7 +405,7 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z OwnsIntercept: true, PostureChecks: postureChecks, IsAccessable: hasAccess, - Timeout: timeout, + Timeout: int32(timeout), } added := ZService{ Name: name, @@ -531,8 +537,8 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { servicesToAdd = append(servicesToAdd, svcToAdd) } } - minimumTimeout := -1 - allServicesTimeout := -1 + var minimumTimeout int32 = -1 + var allServicesTimeout int32 = -1 for i := 0; true; i++ { added := C.ziti_service_array_get(srvEvent.added, C.int(i)) if unsafe.Pointer(added) == C.NULL { @@ -540,14 +546,6 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { } svcToAdd := serviceCB(ztx, added, C.ZITI_OK, zid) if svcToAdd != nil { - if svcToAdd.Timeout >= 0 { - if minimumTimeout == -1 || minimumTimeout > svcToAdd.Timeout { - minimumTimeout = svcToAdd.Timeout - } - if allServicesTimeout == -1 || allServicesTimeout < svcToAdd.Timeout { - allServicesTimeout = svcToAdd.Timeout - } - } addAddys := svcToAdd.Addresses for _, toAdd := range addAddys { if toAdd.IsHost && hostnameAdded(toAdd.HostName) == 1 { @@ -557,21 +555,23 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { servicesToAdd = append(servicesToAdd, svcToAdd) } } + if len(servicesToAdd) > 0 { + for _,svc := range servicesToAdd { + if svc.Timeout >= 0 { + if minimumTimeout == -1 || minimumTimeout > svc.Timeout { + minimumTimeout = svc.Timeout + } + if allServicesTimeout == -1 || allServicesTimeout < svc.Timeout { + allServicesTimeout = svc.Timeout + } + } + } + } zid.MinTimeout = minimumTimeout zid.MaxTimeout = allServicesTimeout zid.LastUpdatedTime = time.Now() - if minimumTimeout == -1 && allServicesTimeout == -1 { - TimeoutPostureChecks <- map[string]bool { - zid.Fingerprint: false, - } - } else { - TimeoutPostureChecks <- map[string]bool { - zid.Fingerprint: true, - } - } - svcChange := BulkServiceChange{ Fingerprint: zid.Fingerprint, HostnamesToAdd: hostnamesToAdd, diff --git a/service/ziti-tunnel/dto/dtos.go b/service/ziti-tunnel/dto/dtos.go index c407e1fa..698e91c3 100644 --- a/service/ziti-tunnel/dto/dtos.go +++ b/service/ziti-tunnel/dto/dtos.go @@ -40,7 +40,7 @@ type Service struct { OwnsIntercept bool PostureChecks []PostureCheck IsAccessable bool - Timeout int + Timeout int32 } type Address struct { @@ -82,8 +82,8 @@ type Identity struct { Services []*Service `json:",omitempty"` Metrics *Metrics `json:",omitempty"` Tags []string `json:",omitempty"` - MinTimeout int - MaxTimeout int + MinTimeout int32 + MaxTimeout int32 LastUpdatedTime time.Time } type Metrics struct { diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 2d37f2d1..2be060cc 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -17,6 +17,7 @@ package service +import "C" import ( "bufio" "crypto/sha1" @@ -45,6 +46,7 @@ import ( "strconv" "strings" "sync" + "sync/atomic" "time" ) @@ -102,8 +104,6 @@ func SubMain(ops chan string, changes chan<- svc.Status, winEvents <-chan Window //listen for services that show up go acceptServices() - go rts.CheckTimeOuts() - // listen for windows power events and call mfa auth func go func() { for { @@ -199,8 +199,6 @@ func SubMain(ops chan string, changes chan<- svc.Status, winEvents <-chan Window func requestShutdown(requester string) { log.Infof("shutdown requested by %v", requester) - // shutdown <- true // stops the metrics ticker - // shutdown <- true // stops the service change listener close(shutdown) // stops the metrics ticker, service change listener and notification alert loop } @@ -1116,6 +1114,7 @@ func handleEvents(isInitialized chan struct{}) { events.run() d := 5 * time.Second every5s := time.NewTicker(d) + notificationFrequency := time.NewTicker(time.Duration(5) * time.Second) defer log.Debugf("exiting handleEvents. loops were set for %v", d) <-isInitialized @@ -1127,10 +1126,78 @@ func handleEvents(isInitialized chan struct{}) { case <-every5s.C: s := rts.ToMetrics() + // broadcast metrics rts.BroadcastEvent(dto.MetricsEvent{ StatusEvent: dto.StatusEvent{Op: "metrics"}, Identities: s.Identities, }) + + // refresh timeout of services + for _,id := range rts.ids { + zid := id.CId + if zid == nil || !zid.RefreshCheck(zid.MinTimeout, zid.MaxTimeout) { + continue + } + + // refresh timeout + zid.Services.Range(func(key interface{}, value interface{}) bool { + //string, ZService + val := value.(*cziti.ZService) + + var svcTimeout int32 = -1 + for _, pc := range val.Service.PostureChecks { + if svcTimeout == -1 || svcTimeout > int32(pc.Timeout) { + svcTimeout = int32(pc.Timeout) + } + break + } + if (svcTimeout - int32(time.Since(zid.LastUpdatedTime).Seconds())) < 0 { + atomic.StoreInt32(&val.Service.Timeout, 0) + } else { + atomic.StoreInt32(&val.Service.Timeout, svcTimeout - int32(time.Since(zid.LastUpdatedTime).Seconds())) + } + return true + }) + + } + + // notification message + case <- notificationFrequency.C: + cleanNotifications := make([]cziti.NotificationMessage, 0) + for _,id := range rts.ids{ + if id.CId == nil || !id.CId.RefreshCheck(id.CId.MinTimeout, id.CId.MaxTimeout) { + continue + } + notificationMessage := "" + + if (id.CId.MaxTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { + notificationMessage = fmt.Sprintf("All of the services of identity %s are timed out", id.Name) + } else if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { + notificationMessage = fmt.Sprintf("Some of the services of identity %s are timed out", id.Name) + } else if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < int32(time.Duration(20 * time.Minute).Seconds()) { + notificationMessage = fmt.Sprintf("Some of the services of identity %s are timing out in sometime", id.Name) + } + + if len(notificationMessage) > 0 { + cleanNotifications = append(cleanNotifications, cziti.NotificationMessage{ + Fingerprint: id.FingerPrint, + IdentityName: id.Name, + Severity: "major", + MinimumTimeOut: id.CId.MinTimeout, + AllServicesTimeout: id.CId.MaxTimeout, + Message: notificationMessage, + TimeDuration: int(time.Since(id.CId.LastUpdatedTime).Seconds()), + }) + } + } + + if len(cleanNotifications) > 0 { + log.Debugf("Sending notification message to UI %v", cleanNotifications) + rts.BroadcastEvent(cziti.TunnelNotificationEvent{ + Op: "notification", + Notification: cleanNotifications, + }) + } } } } @@ -1162,47 +1229,22 @@ func Clean(src *Id) dto.Identity { } if src.CId != nil { - minTimeout := -1 - maxTimeout := -1 - allSvcTimeout := -1 src.CId.Services.Range(func(key interface{}, value interface{}) bool { //string, ZService val := value.(*cziti.ZService) - timeout := -1 - - for _, pc := range val.Service.PostureChecks { - if timeout == -1 || timeout > pc.Timeout { - timeout = pc.Timeout - } - } - if (timeout - int(time.Since(src.CId.LastUpdatedTime).Seconds())) < 0 { - val.Service.Timeout = 0 - } else { - val.Service.Timeout = timeout - int(time.Since(src.CId.LastUpdatedTime).Seconds()) - } - if allSvcTimeout == -1 || allSvcTimeout < val.Service.Timeout { - allSvcTimeout = val.Service.Timeout - } - if minTimeout == -1 || minTimeout > timeout { - minTimeout = timeout - } - if maxTimeout == -1 || maxTimeout < timeout { - maxTimeout = timeout - } nid.Services = append(nid.Services /*svcToDto(val)*/, val.Service) return true }) - nid.MinTimeout = minTimeout - nid.MaxTimeout = maxTimeout - if minTimeout == -1 && maxTimeout == -1 { + nid.MinTimeout = src.CId.MinTimeout + nid.MaxTimeout = src.CId.MaxTimeout + if !src.CId.RefreshCheck(nid.MinTimeout, nid.MaxTimeout) { nid.LastUpdatedTime = time.Now() } else { nid.LastUpdatedTime = src.CId.LastUpdatedTime - } - - if allSvcTimeout == 0 && nid.MfaEnabled { - nid.MfaNeeded = true + if (nid.MaxTimeout - int32(time.Since(nid.LastUpdatedTime).Seconds())) < 0 && nid.MfaEnabled { + nid.MfaNeeded = true + } } } @@ -1263,92 +1305,3 @@ func sendIdentityAndNotifyUI(enc *json.Encoder, fingerprint string) { respond(enc, resp) } -func StartRefreshTimer() { - - RuntimeStatusTicker := time.NewTicker(time.Duration(1) * time.Minute) - log.Debugf("starting service timeout refresh routine") - - go func () { - for { - select { - case <- shutdown: - log.Debugf("shutdown request received, exiting refresh timer routine") - return - case <- RuntimeTimerStop: - RuntimeStatusTicker.Stop() - log.Debugf("timer is stopped, exiting runtime status ticker loop") - RuntimeStatusTicker = nil - return - case <- RuntimeStatusTicker.C: - clean := rts.ToStatus(true) - rts.BroadcastEvent(dto.TunnelStatusEvent{ - StatusEvent: dto.StatusEvent{Op: "status"}, - Status: clean, - ApiVersion: API_VERSION, - }) - } - } - } () -} - -func SendNotifications() { - log.Debug("Started notification routine") - - // allow user to set frequency dynamically - broadcastNotificationTicker := time.NewTicker(5 * time.Minute) - - go func(){ - for { - select { - case <- shutdown: - log.Debugf("Exiting Notification Alert loop") - return - case <- RuntimeTimerStop: - broadcastNotificationTicker.Stop() - log.Debugf("timer is stopped, exiting Notifications ticker loop") - broadcastNotificationTicker = nil - return - case <- broadcastNotificationTicker.C: - clean := rts.ToStatus(true) - - cleanNotifications := make([]cziti.ToastNotification, 0) - - notificationMessage := "" - for _, id := range clean.Identities { - - if id.MaxTimeout == -1 && id.MinTimeout == -1 { - continue - } - - if (id.MaxTimeout - int(time.Since(id.LastUpdatedTime).Seconds())) < 0 { - notificationMessage = fmt.Sprintf("All of the services of identity %s are timed out", id.Name) - } else if (id.MinTimeout - int(time.Since(id.LastUpdatedTime).Seconds())) < 0 { - notificationMessage = fmt.Sprintf("Some of the services of identity %s are timed out", id.Name) - } else if (id.MinTimeout - int(time.Since(id.LastUpdatedTime).Seconds())) < int(time.Duration(20 * time.Minute)) { - notificationMessage = fmt.Sprintf("Some of the services of identity %s are timing out in sometime", id.Name) - } - - cleanNotifications = append(cleanNotifications, cziti.ToastNotification{ - Fingerprint: id.FingerPrint, - IdentityName: id.Name, - Severity: "major", - MinimumTimeOut: id.MinTimeout, - AllServicesTimeout: id.MaxTimeout, - Message: notificationMessage, - TimeDuration: int(time.Since(id.LastUpdatedTime).Seconds()), - }) - - } - if len(cleanNotifications) > 0 { - log.Debugf("Sending notification message to UI %v", cleanNotifications) - rts.BroadcastEvent(cziti.TunnelNotificationEvent{ - Op: "notification", - Notification: cleanNotifications, - }) - } - // should send a toast message to windows - } - } - }() - -} diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index f939bcc3..c70c8719 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -296,7 +296,15 @@ func (t *RuntimeState) LoadIdentity(id *Id, refreshInterval int) { log.Infof("connecting identity completed: %s[%s] %t/%t", id.Name, id.FingerPrint, id.MfaEnabled, id.MfaNeeded) } - id.CId = cziti.NewZid(sc) + rc := func(minTimeout int32, maxTimeOut int32) bool { + if minTimeout == -1 && maxTimeOut == -1 { + return false + } else { + return true + } + } + + id.CId = cziti.NewZid(sc, rc) id.CId.Active = id.Active cziti.LoadZiti(id.CId, id.Path(), refreshInterval) } @@ -548,37 +556,3 @@ func (t *RuntimeState) UpdateMfa(fingerprint string, mfaEnabled bool, mfaNeeded } } -func (t *RuntimeState) CheckTimeOuts() { - go func () { - for { - select { - case <- shutdown: - log.Debugf("Shutting down posture check timeout loop") - return - case timeoutEvent := <- cziti.TimeoutPostureChecks: - - timeoutRefreshRequired := false - for _, id := range rts.ids { - if val, ok := timeoutEvent[id.FingerPrint]; ok { - if val { - timeoutRefreshRequired = true - } - } else { - if id.MinTimeout > -1 || id.MaxTimeout > -1 { - timeoutRefreshRequired = true - } - } - } - if timeoutRefreshRequired { - if RuntimeStatusTicker == nil { - StartRefreshTimer() - SendNotifications() - } - } else { - RuntimeTimerStop <- true - } - } - } - }() -} - diff --git a/service/ziti-tunnel/service/types.go b/service/ziti-tunnel/service/types.go index d9fd04b6..32a676c8 100644 --- a/service/ziti-tunnel/service/types.go +++ b/service/ziti-tunnel/service/types.go @@ -7,7 +7,7 @@ import ( type Id struct { dto.Identity - CId *cziti.ZIdentity + CId *cziti.ZIdentity } type WindowsEvents struct { From f69767cbd8ef4054faabf4955199ace3e1f0bd28 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 19 Jul 2021 13:02:12 +0530 Subject: [PATCH 24/46] formatting code --- service/cziti/mfa.go | 1 - service/cziti/sdk.go | 82 ++++++++++++------------- service/windns/windns.go | 2 +- service/ziti-tunnel/dto/dtos.go | 10 +-- service/ziti-tunnel/dto/events.go | 2 +- service/ziti-tunnel/service/ipc.go | 41 ++++++------- service/ziti-tunnel/service/pkg-vars.go | 4 +- service/ziti-tunnel/service/state.go | 1 - service/ziti-tunnel/service/types.go | 4 +- 9 files changed, 72 insertions(+), 75 deletions(-) diff --git a/service/cziti/mfa.go b/service/cziti/mfa.go index be067a7d..cce2c9fb 100644 --- a/service/cziti/mfa.go +++ b/service/cziti/mfa.go @@ -138,7 +138,6 @@ func ReturnMfaCodes(id *ZIdentity, code string) ([]string, error) { } } - // used when an identity is partially authenticated and waiting on 2fa, i.e. for authentication and for timeouts func AuthMFA(id *ZIdentity, code string) error { ccode := C.CString(code) diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 33ced0ac..e8b1fd24 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -79,24 +79,24 @@ type BulkServiceChange struct { HostnamesToRemove map[string]bool ServicesToRemove []*dto.Service ServicesToAdd []*dto.Service - MinTimeout int32 - MaxTimeout int32 - LastUpdatedTime time.Time + MinTimeout int32 + MaxTimeout int32 + LastUpdatedTime time.Time } type NotificationMessage struct { - IdentityName string - Fingerprint string - Message string - MinimumTimeOut int32 - AllServicesTimeout int32 - TimeDuration int - Severity string + IdentityName string + Fingerprint string + Message string + MinimumTimeOut int32 + AllServicesTimeout int32 + TimeDuration int + Severity string } type TunnelNotificationEvent struct { - Op string - Notification []NotificationMessage + Op string + Notification []NotificationMessage } var _impl sdk @@ -138,24 +138,24 @@ type ZService struct { } type ZIdentity struct { - Options *C.ziti_options - czctx C.ziti_context - czid *C.ziti_identity - status int - statusErr error - Loaded bool - Name string - Version string - Services sync.Map - Fingerprint string - Active bool - StatusChanges func(int) - MfaNeeded bool - MfaEnabled bool - MinTimeout int32 - MaxTimeout int32 - RefreshCheck RefreshRequiredCheck - LastUpdatedTime time.Time + Options *C.ziti_options + czctx C.ziti_context + czid *C.ziti_identity + status int + statusErr error + Loaded bool + Name string + Version string + Services sync.Map + Fingerprint string + Active bool + StatusChanges func(int) + MfaNeeded bool + MfaEnabled bool + MinTimeout int32 + MaxTimeout int32 + RefreshCheck RefreshRequiredCheck + LastUpdatedTime time.Time } func NewZid(statusChange func(int), refreshCheck func(int32, int32) bool) *ZIdentity { @@ -164,9 +164,9 @@ func NewZid(statusChange func(int), refreshCheck func(int32, int32) bool) *ZIden zid.Options = (*C.ziti_options)(C.calloc(1, C.sizeof_ziti_options)) zid.StatusChanges = statusChange zid.RefreshCheck = refreshCheck - zid.MinTimeout = -1 - zid.MaxTimeout = -1 - zid.LastUpdatedTime = time.Now() + zid.MinTimeout = -1 + zid.MaxTimeout = -1 + zid.LastUpdatedTime = time.Now() return zid } @@ -337,7 +337,7 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z //if any posture query sets pass - that will grant the user access to that service hasAccess := false - timeout := -1 + timeout := -1 //find all posture checks sets... for setIdx := 0; true; setIdx++ { @@ -367,7 +367,7 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z var pcId string pcId = C.GoString(pq.id) - log.Infof("Posture query %s, timeout %d", C.GoString(pq.id) , int(pq.timeout)) + log.Infof("Posture query %s, timeout %d", C.GoString(pq.id), int(pq.timeout)) _, found := pcIds[pcId] if found { @@ -376,7 +376,7 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z if pc.Id == C.GoString(pq.id) { if timeout == -1 || timeout > int(pq.timeout) { // pc.Timeout = int(pq.timeout) - timeout = int(pq.timeout) + timeout = int(pq.timeout) } break } @@ -389,7 +389,7 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z Id: pcId, Timeout: int(pq.timeout), } - timeout = pc.Timeout + timeout = pc.Timeout postureChecks = append(postureChecks, pc) } @@ -405,7 +405,7 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z OwnsIntercept: true, PostureChecks: postureChecks, IsAccessable: hasAccess, - Timeout: int32(timeout), + Timeout: int32(timeout), } added := ZService{ Name: name, @@ -556,7 +556,7 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { } } if len(servicesToAdd) > 0 { - for _,svc := range servicesToAdd { + for _, svc := range servicesToAdd { if svc.Timeout >= 0 { if minimumTimeout == -1 || minimumTimeout > svc.Timeout { minimumTimeout = svc.Timeout @@ -578,8 +578,8 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { HostnamesToRemove: hostnamesToRemove, ServicesToAdd: servicesToAdd, ServicesToRemove: servicesToRemove, - MinTimeout: minimumTimeout, - MaxTimeout: allServicesTimeout, + MinTimeout: minimumTimeout, + MaxTimeout: allServicesTimeout, LastUpdatedTime: time.Now(), } diff --git a/service/windns/windns.go b/service/windns/windns.go index 0d38d8f6..701f45a7 100644 --- a/service/windns/windns.go +++ b/service/windns/windns.go @@ -307,4 +307,4 @@ Get-ItemProperty -Path $key | where {$_.ProfileName -match "Ziti.*"} | Remove-It log.Errorf("ERROR Cleaning up the Network Adapter profiles: %v", err) } -} \ No newline at end of file +} diff --git a/service/ziti-tunnel/dto/dtos.go b/service/ziti-tunnel/dto/dtos.go index 698e91c3..93f6b535 100644 --- a/service/ziti-tunnel/dto/dtos.go +++ b/service/ziti-tunnel/dto/dtos.go @@ -40,7 +40,7 @@ type Service struct { OwnsIntercept bool PostureChecks []PostureCheck IsAccessable bool - Timeout int32 + Timeout int32 } type Address struct { @@ -59,7 +59,7 @@ type PostureCheck struct { IsPassing bool QueryType string Id string - Timeout int + Timeout int } type ServiceOwner struct { @@ -82,9 +82,9 @@ type Identity struct { Services []*Service `json:",omitempty"` Metrics *Metrics `json:",omitempty"` Tags []string `json:",omitempty"` - MinTimeout int32 - MaxTimeout int32 - LastUpdatedTime time.Time + MinTimeout int32 + MaxTimeout int32 + LastUpdatedTime time.Time } type Metrics struct { Up int64 diff --git a/service/ziti-tunnel/dto/events.go b/service/ziti-tunnel/dto/events.go index 81bf20c1..bd825e73 100644 --- a/service/ziti-tunnel/dto/events.go +++ b/service/ziti-tunnel/dto/events.go @@ -37,7 +37,7 @@ const ( MFAEnrollmentRemovedAction = "enrollment_remove" MFA_AUTH_CHALLENGE_ACTION = "auth_challenge" - MFAAuthenticationAction = "mfa_auth_status" + MFAAuthenticationAction = "mfa_auth_status" ) var SERVICE_ADDED = ActionEvent{ diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 2be060cc..d3de2f21 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -108,7 +108,7 @@ func SubMain(ops chan string, changes chan<- svc.Status, winEvents <-chan Window go func() { for { select { - case wEvents := <- winEvents: + case wEvents := <-winEvents: if wEvents.WinPowerEvent == PBT_APMRESUMESUSPEND || wEvents.WinPowerEvent == PBT_APMRESUMEAUTOMATIC { log.Debugf("Received Windows Power Event in tunnel %d", wEvents.WinPowerEvent) for _, id := range rts.ids { @@ -121,7 +121,7 @@ func SubMain(ops chan string, changes chan<- svc.Status, winEvents <-chan Window cziti.EndpointStateChanged(id.CId, false, true) } } - case <- shutdownDelay: + case <-shutdownDelay: log.Tracef("Exiting windows power events loop") return } @@ -1133,7 +1133,7 @@ func handleEvents(isInitialized chan struct{}) { }) // refresh timeout of services - for _,id := range rts.ids { + for _, id := range rts.ids { zid := id.CId if zid == nil || !zid.RefreshCheck(zid.MinTimeout, zid.MaxTimeout) { continue @@ -1146,15 +1146,15 @@ func handleEvents(isInitialized chan struct{}) { var svcTimeout int32 = -1 for _, pc := range val.Service.PostureChecks { - if svcTimeout == -1 || svcTimeout > int32(pc.Timeout) { - svcTimeout = int32(pc.Timeout) - } - break + if svcTimeout == -1 || svcTimeout > int32(pc.Timeout) { + svcTimeout = int32(pc.Timeout) + } + break } if (svcTimeout - int32(time.Since(zid.LastUpdatedTime).Seconds())) < 0 { atomic.StoreInt32(&val.Service.Timeout, 0) } else { - atomic.StoreInt32(&val.Service.Timeout, svcTimeout - int32(time.Since(zid.LastUpdatedTime).Seconds())) + atomic.StoreInt32(&val.Service.Timeout, svcTimeout-int32(time.Since(zid.LastUpdatedTime).Seconds())) } return true }) @@ -1162,9 +1162,9 @@ func handleEvents(isInitialized chan struct{}) { } // notification message - case <- notificationFrequency.C: + case <-notificationFrequency.C: cleanNotifications := make([]cziti.NotificationMessage, 0) - for _,id := range rts.ids{ + for _, id := range rts.ids { if id.CId == nil || !id.CId.RefreshCheck(id.CId.MinTimeout, id.CId.MaxTimeout) { continue } @@ -1174,19 +1174,19 @@ func handleEvents(isInitialized chan struct{}) { notificationMessage = fmt.Sprintf("All of the services of identity %s are timed out", id.Name) } else if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { notificationMessage = fmt.Sprintf("Some of the services of identity %s are timed out", id.Name) - } else if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < int32(time.Duration(20 * time.Minute).Seconds()) { + } else if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < int32(time.Duration(20*time.Minute).Seconds()) { notificationMessage = fmt.Sprintf("Some of the services of identity %s are timing out in sometime", id.Name) } if len(notificationMessage) > 0 { cleanNotifications = append(cleanNotifications, cziti.NotificationMessage{ - Fingerprint: id.FingerPrint, - IdentityName: id.Name, - Severity: "major", - MinimumTimeOut: id.CId.MinTimeout, + Fingerprint: id.FingerPrint, + IdentityName: id.Name, + Severity: "major", + MinimumTimeOut: id.CId.MinTimeout, AllServicesTimeout: id.CId.MaxTimeout, - Message: notificationMessage, - TimeDuration: int(time.Since(id.CId.LastUpdatedTime).Seconds()), + Message: notificationMessage, + TimeDuration: int(time.Since(id.CId.LastUpdatedTime).Seconds()), }) } } @@ -1194,8 +1194,8 @@ func handleEvents(isInitialized chan struct{}) { if len(cleanNotifications) > 0 { log.Debugf("Sending notification message to UI %v", cleanNotifications) rts.BroadcastEvent(cziti.TunnelNotificationEvent{ - Op: "notification", - Notification: cleanNotifications, + Op: "notification", + Notification: cleanNotifications, }) } } @@ -1242,7 +1242,7 @@ func Clean(src *Id) dto.Identity { nid.LastUpdatedTime = time.Now() } else { nid.LastUpdatedTime = src.CId.LastUpdatedTime - if (nid.MaxTimeout - int32(time.Since(nid.LastUpdatedTime).Seconds())) < 0 && nid.MfaEnabled { + if (nid.MaxTimeout-int32(time.Since(nid.LastUpdatedTime).Seconds())) < 0 && nid.MfaEnabled { nid.MfaNeeded = true } } @@ -1304,4 +1304,3 @@ func sendIdentityAndNotifyUI(enc *json.Encoder, fingerprint string) { resp := dto.Response{Message: "", Code: ERROR, Error: "Could not find id matching fingerprint " + fingerprint, Payload: ""} respond(enc, resp) } - diff --git a/service/ziti-tunnel/service/pkg-vars.go b/service/ziti-tunnel/service/pkg-vars.go index 97dbd7b9..c4488fb0 100644 --- a/service/ziti-tunnel/service/pkg-vars.go +++ b/service/ziti-tunnel/service/pkg-vars.go @@ -82,8 +82,8 @@ const ( PBT_APMRESUMEAUTOMATIC = 18 // Resume Automatic // windows session changes microsoft docs https://docs.microsoft.com/en-us/windows/win32/termserv/wm-wtssession-change - WTS_SESSION_LOCK = 7 - WTS_SESSION_UNLOCK = 8 + WTS_SESSION_LOCK = 7 + WTS_SESSION_UNLOCK = 8 // This is the name you will use for the NET START command SvcStartName = "ziti" diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index c70c8719..a0cfbc7f 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -555,4 +555,3 @@ func (t *RuntimeState) UpdateMfa(fingerprint string, mfaEnabled bool, mfaNeeded id.MfaNeeded = mfaNeeded } } - diff --git a/service/ziti-tunnel/service/types.go b/service/ziti-tunnel/service/types.go index 32a676c8..9a6e2b0a 100644 --- a/service/ziti-tunnel/service/types.go +++ b/service/ziti-tunnel/service/types.go @@ -7,10 +7,10 @@ import ( type Id struct { dto.Identity - CId *cziti.ZIdentity + CId *cziti.ZIdentity } type WindowsEvents struct { - WinPowerEvent uint32 + WinPowerEvent uint32 WinSessionEvent uint32 } From fcaa135d7195e6e9aa56458c67b9378807752200 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 19 Jul 2021 16:06:51 +0530 Subject: [PATCH 25/46] changing the frequency back to 5 minutes --- service/cziti/sdk.go | 1 - service/ziti-tunnel/service/ipc.go | 10 ++++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index e8b1fd24..0f2e03f7 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -375,7 +375,6 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z for _, pc := range postureChecks { if pc.Id == C.GoString(pq.id) { if timeout == -1 || timeout > int(pq.timeout) { - // pc.Timeout = int(pq.timeout) timeout = int(pq.timeout) } break diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index d3de2f21..412a40e5 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -118,7 +118,9 @@ func SubMain(ops chan string, changes chan<- svc.Status, winEvents <-chan Window if wEvents.WinSessionEvent == WTS_SESSION_UNLOCK { log.Debugf("Received Windows Session Event (device unlocked) in tunnel %d", wEvents.WinSessionEvent) for _, id := range rts.ids { - cziti.EndpointStateChanged(id.CId, false, true) + if id.CId != nil && id.CId.Loaded { + cziti.EndpointStateChanged(id.CId, false, true) + } } } case <-shutdownDelay: @@ -1114,7 +1116,7 @@ func handleEvents(isInitialized chan struct{}) { events.run() d := 5 * time.Second every5s := time.NewTicker(d) - notificationFrequency := time.NewTicker(time.Duration(5) * time.Second) + notificationFrequency := time.NewTicker(time.Duration(5) * time.Minute) defer log.Debugf("exiting handleEvents. loops were set for %v", d) <-isInitialized @@ -1144,6 +1146,10 @@ func handleEvents(isInitialized chan struct{}) { //string, ZService val := value.(*cziti.ZService) + if val.Service.Timeout <= 0 { + return true + } + var svcTimeout int32 = -1 for _, pc := range val.Service.PostureChecks { if svcTimeout == -1 || svcTimeout > int32(pc.Timeout) { From f539c45c7024b6176bf213dca372979daecb8a9c Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 19 Jul 2021 22:36:17 +0530 Subject: [PATCH 26/46] changes as per the code review comments --- DesktopEdge/MainWindow.xaml.cs | 4 +- .../DataStructures/DataStructures.cs | 6 +-- .../ServiceClient/DataClient.cs | 1 + service/cziti/sdk.go | 40 +++++++++++-------- service/ziti-tunnel/service/ipc.go | 22 +++++----- service/ziti-tunnel/service/state.go | 13 +----- 6 files changed, 42 insertions(+), 44 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index 27ab2a2a..d49afb1e 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -575,11 +575,11 @@ namespace ZitiDesktopEdge { logger.Warn($"{e.Op} event for {notification.Fingerprint} but the provided identity fingerprint was not found!"); continue; } - if (notification.AllServicesTimeout == 0) { + if (notification.MaximumTimeout > -1 && (notification.TimeDuration - notification.MaximumTimeout) == 0) { found.MFAInfo.IsAuthenticated = false; // display mfa token icon displayMFARequired = true; - } else if (notification.MinimumTimeOut == 0) { + } else if (notification.MinimumTimeout == 0) { // display option to enter mfa, only few services are timed out } else { // display option to enter mfa, only few services are about to timeout diff --git a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs index 957e1b44..465182f2 100644 --- a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs +++ b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs @@ -325,9 +325,9 @@ namespace ZitiDesktopEdge.DataStructures { public string IdentityName { get; set; } public string Fingerprint { get; set; } public string Message { get; set; } - public int MinimumTimeOut { get; set; } - public int AllServicesTimeout { get; set; } - public string NotificationTime { get; set; } + public int MinimumTimeout { get; set; } + public int MaximumTimeout { get; set; } + public int TimeDuration { get; set; } public string Severity { get; set; } } diff --git a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs index 1afc3e65..ecc24218 100644 --- a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs +++ b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs @@ -181,6 +181,7 @@ namespace ZitiDesktopEdge.ServiceClient { Function = "RemoveIdentity", Payload = new FingerprintPayload() { Fingerprint = fingerPrint } }; + Logger.Info("Removing Identity with fingerprint {0}", fingerPrint); await sendAsync(removeFunction); var r = await readAsync(ipcReader); } catch (Exception ioe) { diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 0f2e03f7..234786fb 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -85,13 +85,13 @@ type BulkServiceChange struct { } type NotificationMessage struct { - IdentityName string - Fingerprint string - Message string - MinimumTimeOut int32 - AllServicesTimeout int32 - TimeDuration int - Severity string + IdentityName string + Fingerprint string + Message string + MinimumTimeout int32 + MaximumTimeout int32 + TimeDuration int + Severity string } type TunnelNotificationEvent struct { @@ -154,16 +154,14 @@ type ZIdentity struct { MfaEnabled bool MinTimeout int32 MaxTimeout int32 - RefreshCheck RefreshRequiredCheck LastUpdatedTime time.Time } -func NewZid(statusChange func(int), refreshCheck func(int32, int32) bool) *ZIdentity { +func NewZid(statusChange func(int)) *ZIdentity { zid := &ZIdentity{} zid.Services = sync.Map{} zid.Options = (*C.ziti_options)(C.calloc(1, C.sizeof_ziti_options)) zid.StatusChanges = statusChange - zid.RefreshCheck = refreshCheck zid.MinTimeout = -1 zid.MaxTimeout = -1 zid.LastUpdatedTime = time.Now() @@ -246,6 +244,10 @@ func (zid *ZIdentity) Shutdown() { C.uv_async_send((*C.uv_async_t)(unsafe.Pointer(async))) } +func (zid *ZIdentity) RefreshNeeded() bool { + return !(zid.MinTimeout == -1 && zid.MaxTimeout == -1) +} + //export doZitiShutdown func doZitiShutdown(async *C.uv_async_t) { ctx := C.ziti_context(async.data) @@ -536,8 +538,6 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { servicesToAdd = append(servicesToAdd, svcToAdd) } } - var minimumTimeout int32 = -1 - var allServicesTimeout int32 = -1 for i := 0; true; i++ { added := C.ziti_service_array_get(srvEvent.added, C.int(i)) if unsafe.Pointer(added) == C.NULL { @@ -554,21 +554,29 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { servicesToAdd = append(servicesToAdd, svcToAdd) } } + var minimumTimeout int32 = -1 + var maximumTimeout int32 = -1 + noTimeoutSvc := false if len(servicesToAdd) > 0 { for _, svc := range servicesToAdd { if svc.Timeout >= 0 { if minimumTimeout == -1 || minimumTimeout > svc.Timeout { minimumTimeout = svc.Timeout } - if allServicesTimeout == -1 || allServicesTimeout < svc.Timeout { - allServicesTimeout = svc.Timeout + if maximumTimeout == -1 || maximumTimeout < svc.Timeout { + maximumTimeout = svc.Timeout } + } else { + noTimeoutSvc = true } } + if noTimeoutSvc { + maximumTimeout = -1 + } } zid.MinTimeout = minimumTimeout - zid.MaxTimeout = allServicesTimeout + zid.MaxTimeout = maximumTimeout zid.LastUpdatedTime = time.Now() svcChange := BulkServiceChange{ @@ -578,7 +586,7 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { ServicesToAdd: servicesToAdd, ServicesToRemove: servicesToRemove, MinTimeout: minimumTimeout, - MaxTimeout: allServicesTimeout, + MaxTimeout: maximumTimeout, LastUpdatedTime: time.Now(), } diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 412a40e5..00ffb0d4 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -1137,7 +1137,7 @@ func handleEvents(isInitialized chan struct{}) { // refresh timeout of services for _, id := range rts.ids { zid := id.CId - if zid == nil || !zid.RefreshCheck(zid.MinTimeout, zid.MaxTimeout) { + if zid == nil || !zid.RefreshNeeded() { continue } @@ -1171,12 +1171,12 @@ func handleEvents(isInitialized chan struct{}) { case <-notificationFrequency.C: cleanNotifications := make([]cziti.NotificationMessage, 0) for _, id := range rts.ids { - if id.CId == nil || !id.CId.RefreshCheck(id.CId.MinTimeout, id.CId.MaxTimeout) { + if id.CId == nil || !id.CId.RefreshNeeded() { continue } notificationMessage := "" - if (id.CId.MaxTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { + if (id.CId.MaxTimeout > -1) && (id.CId.MaxTimeout-int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { notificationMessage = fmt.Sprintf("All of the services of identity %s are timed out", id.Name) } else if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { notificationMessage = fmt.Sprintf("Some of the services of identity %s are timed out", id.Name) @@ -1186,13 +1186,13 @@ func handleEvents(isInitialized chan struct{}) { if len(notificationMessage) > 0 { cleanNotifications = append(cleanNotifications, cziti.NotificationMessage{ - Fingerprint: id.FingerPrint, - IdentityName: id.Name, - Severity: "major", - MinimumTimeOut: id.CId.MinTimeout, - AllServicesTimeout: id.CId.MaxTimeout, - Message: notificationMessage, - TimeDuration: int(time.Since(id.CId.LastUpdatedTime).Seconds()), + Fingerprint: id.FingerPrint, + IdentityName: id.Name, + Severity: "major", + MinimumTimeout: id.CId.MinTimeout, + MaximumTimeout: id.CId.MaxTimeout, + Message: notificationMessage, + TimeDuration: int(time.Since(id.CId.LastUpdatedTime).Seconds()), }) } } @@ -1244,7 +1244,7 @@ func Clean(src *Id) dto.Identity { }) nid.MinTimeout = src.CId.MinTimeout nid.MaxTimeout = src.CId.MaxTimeout - if !src.CId.RefreshCheck(nid.MinTimeout, nid.MaxTimeout) { + if !src.CId.RefreshNeeded() { nid.LastUpdatedTime = time.Now() } else { nid.LastUpdatedTime = src.CId.LastUpdatedTime diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index a0cfbc7f..0157a2c5 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -43,9 +43,6 @@ import ( "time" ) -var RuntimeTimerStop = make(chan bool) -var RuntimeStatusTicker *time.Ticker = nil - type RuntimeState struct { state *dto.TunnelStatus tun *tun.Device @@ -296,15 +293,7 @@ func (t *RuntimeState) LoadIdentity(id *Id, refreshInterval int) { log.Infof("connecting identity completed: %s[%s] %t/%t", id.Name, id.FingerPrint, id.MfaEnabled, id.MfaNeeded) } - rc := func(minTimeout int32, maxTimeOut int32) bool { - if minTimeout == -1 && maxTimeOut == -1 { - return false - } else { - return true - } - } - - id.CId = cziti.NewZid(sc, rc) + id.CId = cziti.NewZid(sc) id.CId.Active = id.Active cziti.LoadZiti(id.CId, id.Path(), refreshInterval) } From 281f7a8d3d98e4682386d3c370aa3d5f9f5eab71 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 19 Jul 2021 22:42:41 +0530 Subject: [PATCH 27/46] fixing if condition --- DesktopEdge/MainWindow.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index d49afb1e..d24e76aa 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -575,7 +575,7 @@ namespace ZitiDesktopEdge { logger.Warn($"{e.Op} event for {notification.Fingerprint} but the provided identity fingerprint was not found!"); continue; } - if (notification.MaximumTimeout > -1 && (notification.TimeDuration - notification.MaximumTimeout) == 0) { + if (notification.MaximumTimeout > -1 && (notification.TimeDuration - notification.MaximumTimeout) > 0) { found.MFAInfo.IsAuthenticated = false; // display mfa token icon displayMFARequired = true; From 8fbafde0c502de68535169227999d2d020d7d84e Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Tue, 20 Jul 2021 12:21:00 +0530 Subject: [PATCH 28/46] fixing log message --- service/cziti/sdk.go | 4 +++- service/ziti-tunnel/service/ipc.go | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 234786fb..54faff67 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -618,8 +618,10 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { Id: id, } goapi.BroadcastEvent(m) + log.Debugf("mfa auth event set enabled/needed to true for ziti context [%p]. Identity name:%s [fingerprint: %s]", zid, zid.Name, zid.Fingerprint) + } else { + log.Debugf("mfa auth event set received with empty finger print, ziti context [%p]", zid) } - log.Debugf("mfa auth event set enabled/needed to true for ziti context [%p]. Identity name:%s [fingerprint: %s]", zid, zid.Name, zid.Fingerprint) default: log.Infof("event %d not handled", event._type) } diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 00ffb0d4..5e864eac 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -1180,7 +1180,7 @@ func handleEvents(isInitialized chan struct{}) { notificationMessage = fmt.Sprintf("All of the services of identity %s are timed out", id.Name) } else if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { notificationMessage = fmt.Sprintf("Some of the services of identity %s are timed out", id.Name) - } else if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < int32(time.Duration(20*time.Minute).Seconds()) { + } else if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < int32(20*60) { notificationMessage = fmt.Sprintf("Some of the services of identity %s are timing out in sometime", id.Name) } @@ -1274,6 +1274,7 @@ func authMfa(out *json.Encoder, fingerprint string, code string) { id := rts.Find(fingerprint) result := cziti.AuthMFA(id.CId, code) if result == nil { + id.CId.MfaNeeded = false respond(out, dto.Response{Message: "AuthMFA complete", Code: SUCCESS, Error: "", Payload: fingerprint}) } else { respondWithError(out, fmt.Sprintf("AuthMFA failed. the supplied code [%s] was not valid: %s", code, result), 1, result) From 14aa0c35cc44eb4c5f16c0b6f601505261c6746e Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Tue, 20 Jul 2021 12:52:57 +0530 Subject: [PATCH 29/46] fix notification message --- DesktopEdge/MainWindow.xaml.cs | 11 ++++++----- service/ziti-tunnel/service/ipc.go | 9 +++++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index d24e76aa..903eeacb 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -575,17 +575,18 @@ namespace ZitiDesktopEdge { logger.Warn($"{e.Op} event for {notification.Fingerprint} but the provided identity fingerprint was not found!"); continue; } - if (notification.MaximumTimeout > -1 && (notification.TimeDuration - notification.MaximumTimeout) > 0) { + if (notification.MaximumTimeout == 0) { found.MFAInfo.IsAuthenticated = false; - // display mfa token icon + // display notification message - critical displayMFARequired = true; } else if (notification.MinimumTimeout == 0) { - // display option to enter mfa, only few services are timed out + // display notification message, only few services are timed out } else { - // display option to enter mfa, only few services are about to timeout + // display notification message, only few services are about to timeout } } - // we need to display mfa icon for the identities that have all the services timed out. + // we may need to display mfa icon, based on the timer in UI, remove found.MFAInfo.IsAuthenticated setting in this function. + // the below function can show mfa icon even after user authenticates successfully, in race conditions if (displayMFARequired) { LoadIdentities(true); this.Dispatcher.Invoke(() => { diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 5e864eac..31567ea8 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -1176,11 +1176,16 @@ func handleEvents(isInitialized chan struct{}) { } notificationMessage := "" + var notificationMinTimeout int32 = 0 + var notificationMaxTimeout int32 = 0 if (id.CId.MaxTimeout > -1) && (id.CId.MaxTimeout-int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { notificationMessage = fmt.Sprintf("All of the services of identity %s are timed out", id.Name) } else if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { + notificationMaxTimeout = id.CId.MaxTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds()) notificationMessage = fmt.Sprintf("Some of the services of identity %s are timed out", id.Name) } else if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < int32(20*60) { + notificationMinTimeout = id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds()) + notificationMaxTimeout = id.CId.MaxTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds()) notificationMessage = fmt.Sprintf("Some of the services of identity %s are timing out in sometime", id.Name) } @@ -1189,8 +1194,8 @@ func handleEvents(isInitialized chan struct{}) { Fingerprint: id.FingerPrint, IdentityName: id.Name, Severity: "major", - MinimumTimeout: id.CId.MinTimeout, - MaximumTimeout: id.CId.MaxTimeout, + MinimumTimeout: notificationMinTimeout, + MaximumTimeout: notificationMaxTimeout, Message: notificationMessage, TimeDuration: int(time.Since(id.CId.LastUpdatedTime).Seconds()), }) From 3c02593e3d8469901bca8ce529b83b53677937ac Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Tue, 20 Jul 2021 21:28:00 +0530 Subject: [PATCH 30/46] update frequency initial commit --- DesktopEdge/Views/Screens/MainMenu.xaml | 12 +++++++ DesktopEdge/Views/Screens/MainMenu.xaml.cs | 31 +++++++++++++++++++ .../DataStructures/DataStructures.cs | 15 +++++++++ .../ServiceClient/DataClient.cs | 24 ++++++++++++++ service/build.bat | 2 +- service/ziti-tunnel/constants/consts.go | 2 ++ service/ziti-tunnel/dto/dtos.go | 1 + service/ziti-tunnel/service/ipc.go | 23 +++++++++++++- service/ziti-tunnel/service/state.go | 23 ++++++++++++++ 9 files changed, 131 insertions(+), 2 deletions(-) diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml b/DesktopEdge/Views/Screens/MainMenu.xaml index b3c566a2..9654d16c 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml +++ b/DesktopEdge/Views/Screens/MainMenu.xaml @@ -180,6 +180,18 @@ + + + + + + + + + + diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml.cs b/DesktopEdge/Views/Screens/MainMenu.xaml.cs index 58ddab5d..319c2b5a 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml.cs +++ b/DesktopEdge/Views/Screens/MainMenu.xaml.cs @@ -501,6 +501,33 @@ namespace ZitiDesktopEdge { } } + /// + /// Save the frequency information to the properties and queue for update. + /// + async private void UpdateFrequency() { + logger.Info("updating frequency..."); + DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; + try { + var newFrequencyVar = Int32.Parse(FrequencyNew.Text); + + var r = await client.NotificationFrequencyPayloadAsync(newFrequencyVar); + if (r.Code != 0) { + this.OnShowBlurb?.Invoke("Error: " + r.Error); + logger.Debug("ERROR: {0} : {1}", r.Message, r.Error); + } else { + this.OnShowBlurb?.Invoke("Frequency Saved"); + this.CloseEdit(); + } + logger.Info("Got response from update frequency task : {0}", r); + } catch (DataStructures.ServiceException se) { + this.OnShowBlurb?.Invoke("Error: " + se.Message); + logger.Error(se, "service exception in update frequency check: {0}", se.Message); + } catch (Exception ex) { + this.OnShowBlurb?.Invoke("Error: " + ex.Message); + logger.Error(ex, "unexpected error in update frequency check: {0}", ex.Message); + } + } + /// /// Show the Edit Modal and blur the background /// @@ -582,5 +609,9 @@ namespace ZitiDesktopEdge { private void SaveConfig() { this.UpdateConfig(); } + + private void SaveFrequency() { + this.UpdateFrequency(); + } } } \ No newline at end of file diff --git a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs index 465182f2..75bf8c9c 100644 --- a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs +++ b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs @@ -500,4 +500,19 @@ namespace ZitiDesktopEdge.DataStructures { public ConfigPayload Payload { get; set; } } + public class NotificationFrequencyPayload { + public int NotificationFrequency { get; set; } + } + + public class NotificationFrequencyFunction: ServiceFunction { + public NotificationFrequencyFunction(int notificationFrequency) { + this.Function = ""; + this.Payload = new NotificationFrequencyPayload() { + NotificationFrequency = notificationFrequency + }; + } + + public NotificationFrequencyPayload Payload { get; set; } + } + } diff --git a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs index ecc24218..b859c69d 100644 --- a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs +++ b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs @@ -425,6 +425,30 @@ namespace ZitiDesktopEdge.ServiceClient { return resp; } + async public Task NotificationFrequencyPayloadAsync(int frequency) { + SvcResponse resp = null; + try { + + NotificationFrequencyFunction frequencyPayload = new NotificationFrequencyFunction(frequency); + + await sendAsync(frequencyPayload); + resp = await readAsync(ipcReader); + Logger.Debug("frequency update payload is sent to the ziti tunnel"); + } catch (Exception ex) { + //almost certainly a problem with the pipe - recreate the pipe... + //setupPipe(); + //throw; + Logger.Error(ex, "Unexpected error"); + CommunicationError(ex); + throw ex; + } + if (resp?.Code != 0) { + Logger.Warn("failed to update the frequency. {0} {1}", resp.Message, resp.Error); + throw new ServiceException("Failed to update the frequency", resp.Code, "Un expected error."); + } + return resp; + } + async public Task debugAsync() { try { await sendAsync(new ServiceFunction() { Function = "Debug" }); diff --git a/service/build.bat b/service/build.bat index cfaa6cd2..a2b56ffd 100644 --- a/service/build.bat +++ b/service/build.bat @@ -14,7 +14,7 @@ REM See the License for the specific language governing permissions and REM limitations under the License. REM SET REPO_URL=https://github.com/openziti/ziti-tunnel-sdk-c.git -SET ZITI_TUNNEL_REPO_BRANCH=v0.15.8 +SET ZITI_TUNNEL_REPO_BRANCH=v0.15.9 REM override the c sdk used in the build - leave blank for the same as specified in the tunneler sdk SET ZITI_SDK_C_BRANCH= REM the number of TCP connections the tunneler sdk can have at any one time diff --git a/service/ziti-tunnel/constants/consts.go b/service/ziti-tunnel/constants/consts.go index cc1c95ea..f9ae3ce5 100644 --- a/service/ziti-tunnel/constants/consts.go +++ b/service/ziti-tunnel/constants/consts.go @@ -22,4 +22,6 @@ const ( Ipv4MaxMask = 8 Ipv4MinMask = 16 Ipv4DefaultMask = 10 + MinimumFrequency = 5 + MaximumFrequency = 20 ) diff --git a/service/ziti-tunnel/dto/dtos.go b/service/ziti-tunnel/dto/dtos.go index 93f6b535..4211861a 100644 --- a/service/ziti-tunnel/dto/dtos.go +++ b/service/ziti-tunnel/dto/dtos.go @@ -126,6 +126,7 @@ type TunnelStatus struct { TunIpv4Mask int Status string AddDns bool + NotificationFrequency int } type ServiceVersion struct { diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 31567ea8..e2c8eda6 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -63,6 +63,7 @@ func (p *Pipes) Close() { } var shutdown = make(chan bool, 8) //a channel informing go routines to exit +var resetFrequency = make(chan int) func SubMain(ops chan string, changes chan<- svc.Status, winEvents <-chan WindowsEvents) error { log.Info("============================== service begins ==============================") @@ -578,6 +579,8 @@ func serveIpc(conn net.Conn) { fingerprint := cmd.Payload["Fingerprint"].(string) code := cmd.Payload["Code"].(string) removeMFA(enc, fingerprint, code) + case "UpdateFrequency": + updateNotificationFrequency(enc, cmd.Payload["NotificationFrequency"].(int)) case "Debug": dbg() respond(enc, dto.Response{ @@ -1116,7 +1119,7 @@ func handleEvents(isInitialized chan struct{}) { events.run() d := 5 * time.Second every5s := time.NewTicker(d) - notificationFrequency := time.NewTicker(time.Duration(5) * time.Minute) + notificationFrequency := time.NewTicker(time.Duration(5) * time.Second) defer log.Debugf("exiting handleEvents. loops were set for %v", d) <-isInitialized @@ -1209,6 +1212,9 @@ func handleEvents(isInitialized chan struct{}) { Notification: cleanNotifications, }) } + + case newFrequency := <- resetFrequency: + notificationFrequency.Reset(time.Duration(newFrequency) * time.Minute) } } } @@ -1316,3 +1322,18 @@ func sendIdentityAndNotifyUI(enc *json.Encoder, fingerprint string) { resp := dto.Response{Message: "", Code: ERROR, Error: "Could not find id matching fingerprint " + fingerprint, Payload: ""} respond(enc, resp) } + +func updateNotificationFrequency(out *json.Encoder, notificationFreq int) { + + if notificationFreq != rts.state.NotificationFrequency { + err := rts.UpdateNotificationFrequency(notificationFreq) + if err != nil { + respondWithError(out, "Could not set notification frequency", UNKNOWN_ERROR, err) + return + } + + resetFrequency <- notificationFreq + } + respond(out, dto.Response{Message: "Notification frequency is set", Code: SUCCESS, Error: "", Payload: ""}) + +} diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index 0157a2c5..96749ba9 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -126,6 +126,7 @@ func (t *RuntimeState) ToStatus(onlyInitialized bool) dto.TunnelStatus { TunIpv4: t.state.TunIpv4, TunIpv4Mask: t.state.TunIpv4Mask, AddDns: t.state.AddDns, + NotificationFrequency: t.state.NotificationFrequency, } i := 0 @@ -160,6 +161,9 @@ func (t *RuntimeState) ToMetrics() dto.TunnelStatus { Active: id.Active, MfaEnabled: id.MfaEnabled, MfaNeeded: id.MfaNeeded, + MinTimeout: id.MinTimeout, + MaxTimeout: id.MaxTimeout, + LastUpdatedTime: id.LastUpdatedTime, } i++ } @@ -321,6 +325,10 @@ func (t *RuntimeState) LoadConfig() { log.Warnf("provided mask: [%d] is smaller than the minimum permitted: [%d] and will be changed", rts.state.TunIpv4Mask, constants.Ipv4MinMask) rts.UpdateIpv4Mask(constants.Ipv4MinMask) } + + if t.state.NotificationFrequency == 0 { + rts.UpdateNotificationFrequency(constants.MinimumFrequency) + } } func (t *RuntimeState) scanForOrphanedIdentities(folder string) { @@ -544,3 +552,18 @@ func (t *RuntimeState) UpdateMfa(fingerprint string, mfaEnabled bool, mfaNeeded id.MfaNeeded = mfaNeeded } } + +func (t *RuntimeState) UpdateNotificationFrequency(notificationFreq int) error { + + log.Infof("setting notification frequency : %d", notificationFreq) + + if notificationFreq < constants.MinimumFrequency || notificationFreq > constants.MaximumFrequency { + return errors.New(fmt.Sprintf("Notification frequency should be between %d and %d minutes", constants.MinimumFrequency, constants.MaximumFrequency)) + } + + rts.state.NotificationFrequency = notificationFreq + + rts.SaveState() + + return nil +} From 460ceb839fa5854d7a89ae27f005d00efe1cc9b2 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Tue, 20 Jul 2021 21:32:03 +0530 Subject: [PATCH 31/46] updating t-sdk version --- service/build.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/build.bat b/service/build.bat index c869a6ae..89a01469 100644 --- a/service/build.bat +++ b/service/build.bat @@ -14,7 +14,7 @@ REM See the License for the specific language governing permissions and REM limitations under the License. REM SET REPO_URL=https://github.com/openziti/ziti-tunnel-sdk-c.git -SET ZITI_TUNNEL_REPO_BRANCH=v0.15.8 +SET ZITI_TUNNEL_REPO_BRANCH=v0.15.9 REM override the c sdk used in the build - leave blank for the same as specified in the tunneler sdk SET ZITI_SDK_C_BRANCH= REM the number of TCP connections the tunneler sdk can have at any one time From 070904cd0a4586d5bed43f71b26b81d8366d89b9 Mon Sep 17 00:00:00 2001 From: ziti-ci Date: Tue, 20 Jul 2021 16:11:34 +0000 Subject: [PATCH 32/46] [ci skip] committing updated version related files --- service/ziti-tunnel/version.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/ziti-tunnel/version.go b/service/ziti-tunnel/version.go index d4988fb5..24f3ff2f 100644 --- a/service/ziti-tunnel/version.go +++ b/service/ziti-tunnel/version.go @@ -21,8 +21,8 @@ package main const ( Version = "1.9.11" - Revision = "e8ffb6b43346" + Revision = "460ceb839fa5" Branch = "release-next" BuildUser = "" - BuildDate = "2021-07-14 17:23:06" + BuildDate = "2021-07-20 16:05:41" ) From 445e9acd3765d04555534a7221748bd121979099 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Wed, 21 Jul 2021 14:14:04 +0530 Subject: [PATCH 33/46] notification frequency updates --- .../DataStructures/DataStructures.cs | 2 +- service/ziti-tunnel/service/ipc.go | 22 ++++++++++++++----- version | 2 +- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs index 75bf8c9c..54fcb91e 100644 --- a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs +++ b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs @@ -506,7 +506,7 @@ namespace ZitiDesktopEdge.DataStructures { public class NotificationFrequencyFunction: ServiceFunction { public NotificationFrequencyFunction(int notificationFrequency) { - this.Function = ""; + this.Function = "UpdateFrequency"; this.Payload = new NotificationFrequencyPayload() { NotificationFrequency = notificationFrequency }; diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index c136330a..e5299a99 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -580,7 +580,8 @@ func serveIpc(conn net.Conn) { code := cmd.Payload["Code"].(string) removeMFA(enc, fingerprint, code) case "UpdateFrequency": - updateNotificationFrequency(enc, cmd.Payload["NotificationFrequency"].(int)) + notificationFreq := cmd.Payload["NotificationFrequency"].(float64) + updateNotificationFrequency(enc, int(notificationFreq)) case "Debug": dbg() respond(enc, dto.Response{ @@ -1138,7 +1139,7 @@ func handleEvents(isInitialized chan struct{}) { events.run() d := 5 * time.Second every5s := time.NewTicker(d) - notificationFrequency := time.NewTicker(time.Duration(5) * time.Second) + notificationFrequency := time.NewTicker(time.Duration(rts.state.NotificationFrequency) * time.Minute) defer log.Debugf("exiting handleEvents. loops were set for %v", d) <-isInitialized @@ -1199,17 +1200,26 @@ func handleEvents(isInitialized chan struct{}) { notificationMessage := "" var notificationMinTimeout int32 = 0 - var notificationMaxTimeout int32 = 0 + var notificationMaxTimeout int32 = -1 if (id.CId.MaxTimeout > -1) && (id.CId.MaxTimeout-int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { notificationMessage = fmt.Sprintf("All of the services of identity %s are timed out", id.Name) } else if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { - notificationMaxTimeout = id.CId.MaxTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds()) notificationMessage = fmt.Sprintf("Some of the services of identity %s are timed out", id.Name) } else if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < int32(20*60) { - notificationMinTimeout = id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds()) - notificationMaxTimeout = id.CId.MaxTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds()) notificationMessage = fmt.Sprintf("Some of the services of identity %s are timing out in sometime", id.Name) } + if id.CId.MaxTimeout > -1 { + if (id.CId.MaxTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { + notificationMaxTimeout = 0 + } else { + notificationMaxTimeout = id.CId.MaxTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds()) + } + } + if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { + notificationMinTimeout = 0 + } else { + notificationMinTimeout = id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds()) + } if len(notificationMessage) > 0 { cleanNotifications = append(cleanNotifications, cziti.NotificationMessage{ diff --git a/version b/version index f0a2883d..81c871de 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.9.10 +1.10.0 From 4f876b220c20a6ba4bb3c7aa2ec9757df9b68bb2 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Wed, 21 Jul 2021 14:14:24 +0530 Subject: [PATCH 34/46] updating release-notes --- release-notes.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/release-notes.md b/release-notes.md index 394e875a..e222c210 100644 --- a/release-notes.md +++ b/release-notes.md @@ -1,3 +1,17 @@ +# Release 1.10.0 + +## What's New +* mfa timeout process + +## Other changes: +* none + +## Bugs fixed: +* none + +## Dependency Updates +* updated c-sdk to v0.25.2, updated t-sdk to v0.15.9 + # Release 1.9.10 ## What's New From ef32b6c096d2bf178857ed4c04020e1b871b446e Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Wed, 21 Jul 2021 17:16:22 +0530 Subject: [PATCH 35/46] formatting code --- DesktopEdge/Views/Screens/MainMenu.xaml | 11 -------- service/cziti/sdk.go | 2 +- service/ziti-tunnel/dto/dtos.go | 22 ++++++++-------- service/ziti-tunnel/service/ipc.go | 5 ++-- service/ziti-tunnel/service/state.go | 34 ++++++++++++------------- 5 files changed, 32 insertions(+), 42 deletions(-) diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml b/DesktopEdge/Views/Screens/MainMenu.xaml index 9654d16c..5f6571de 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml +++ b/DesktopEdge/Views/Screens/MainMenu.xaml @@ -181,17 +181,6 @@ - - - - - - - - - diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 9b733162..cdf19efe 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -545,6 +545,7 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { if unsafe.Pointer(added) == C.NULL { break } + svcToAdd := serviceCB(ztx, added, C.ZITI_OK, zid) if svcToAdd != nil { addAddys := svcToAdd.Addresses @@ -579,7 +580,6 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { zid.MinTimeout = minimumTimeout zid.MaxTimeout = maximumTimeout - zid.LastUpdatedTime = time.Now() svcChange := BulkServiceChange{ Fingerprint: zid.Fingerprint, diff --git a/service/ziti-tunnel/dto/dtos.go b/service/ziti-tunnel/dto/dtos.go index 4211861a..3288810d 100644 --- a/service/ziti-tunnel/dto/dtos.go +++ b/service/ziti-tunnel/dto/dtos.go @@ -116,17 +116,17 @@ func (id *Identity) Path() string { } type TunnelStatus struct { - Active bool - Duration int64 - Identities []*Identity - IpInfo *TunIpInfo `json:"IpInfo,omitempty"` - LogLevel string - ServiceVersion ServiceVersion - TunIpv4 string - TunIpv4Mask int - Status string - AddDns bool - NotificationFrequency int + Active bool + Duration int64 + Identities []*Identity + IpInfo *TunIpInfo `json:"IpInfo,omitempty"` + LogLevel string + ServiceVersion ServiceVersion + TunIpv4 string + TunIpv4Mask int + Status string + AddDns bool + NotificationFrequency int } type ServiceVersion struct { diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index e5299a99..aab297a0 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -1242,8 +1242,8 @@ func handleEvents(isInitialized chan struct{}) { }) } - case newFrequency := <- resetFrequency: - notificationFrequency.Reset(time.Duration(newFrequency) * time.Minute) + case newFrequency := <-resetFrequency: + notificationFrequency.Reset(time.Duration(newFrequency) * time.Minute) } } } @@ -1315,6 +1315,7 @@ func authMfa(out *json.Encoder, fingerprint string, code string) { result := cziti.AuthMFA(id.CId, code) if result == nil { id.CId.MfaNeeded = false + id.CId.LastUpdatedTime = time.Now() respond(out, dto.Response{Message: "AuthMFA complete", Code: SUCCESS, Error: "", Payload: fingerprint}) } else { respondWithError(out, fmt.Sprintf("AuthMFA failed. the supplied code [%s] was not valid: %s", code, result), 1, result) diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index 96749ba9..368d81c1 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -117,15 +117,15 @@ func (t *RuntimeState) ToStatus(onlyInitialized bool) dto.TunnelStatus { uptime = tunStart.Milliseconds() clean := dto.TunnelStatus{ - Active: t.state.Active, - Duration: uptime, - Identities: make([]*dto.Identity, 0), - IpInfo: t.state.IpInfo, - LogLevel: t.state.LogLevel, - ServiceVersion: Version, - TunIpv4: t.state.TunIpv4, - TunIpv4Mask: t.state.TunIpv4Mask, - AddDns: t.state.AddDns, + Active: t.state.Active, + Duration: uptime, + Identities: make([]*dto.Identity, 0), + IpInfo: t.state.IpInfo, + LogLevel: t.state.LogLevel, + ServiceVersion: Version, + TunIpv4: t.state.TunIpv4, + TunIpv4Mask: t.state.TunIpv4Mask, + AddDns: t.state.AddDns, NotificationFrequency: t.state.NotificationFrequency, } @@ -155,14 +155,14 @@ func (t *RuntimeState) ToMetrics() dto.TunnelStatus { for _, id := range t.ids { AddMetrics(id) clean.Identities[i] = &dto.Identity{ - Name: id.Name, - FingerPrint: id.FingerPrint, - Metrics: id.Metrics, - Active: id.Active, - MfaEnabled: id.MfaEnabled, - MfaNeeded: id.MfaNeeded, - MinTimeout: id.MinTimeout, - MaxTimeout: id.MaxTimeout, + Name: id.Name, + FingerPrint: id.FingerPrint, + Metrics: id.Metrics, + Active: id.Active, + MfaEnabled: id.MfaEnabled, + MfaNeeded: id.MfaNeeded, + MinTimeout: id.MinTimeout, + MaxTimeout: id.MaxTimeout, LastUpdatedTime: id.LastUpdatedTime, } i++ From cc6a1d5e53073162e01b697d2e212045c30a2284 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Wed, 21 Jul 2021 17:19:30 +0530 Subject: [PATCH 36/46] commenting unused code --- DesktopEdge/Views/Screens/MainMenu.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml.cs b/DesktopEdge/Views/Screens/MainMenu.xaml.cs index 319c2b5a..6d196237 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml.cs +++ b/DesktopEdge/Views/Screens/MainMenu.xaml.cs @@ -508,7 +508,7 @@ namespace ZitiDesktopEdge { logger.Info("updating frequency..."); DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; try { - var newFrequencyVar = Int32.Parse(FrequencyNew.Text); + var newFrequencyVar = 5; // Int32.Parse(FrequencyNew.Text); var r = await client.NotificationFrequencyPayloadAsync(newFrequencyVar); if (r.Code != 0) { From 7ff51fce9350ab8e99c7d22c2265674bb782d9d8 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Wed, 21 Jul 2021 23:28:45 +0530 Subject: [PATCH 37/46] code review changes --- DesktopEdge/MainWindow.xaml.cs | 4 +- .../DataStructures/DataStructures.cs | 4 +- service/cziti/sdk.go | 104 +++++++++--------- service/ziti-tunnel/constants/consts.go | 12 +- service/ziti-tunnel/dto/dtos.go | 28 ++--- service/ziti-tunnel/service/ipc.go | 95 +++++++--------- service/ziti-tunnel/service/state.go | 20 ++-- 7 files changed, 128 insertions(+), 139 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index ad6dd204..962e0d06 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -575,11 +575,11 @@ namespace ZitiDesktopEdge { logger.Warn($"{e.Op} event for {notification.Fingerprint} but the provided identity fingerprint was not found!"); continue; } - if (notification.MaximumTimeout == 0) { + if (notification.MfaMaximumTimeout == 0) { found.MFAInfo.IsAuthenticated = false; // display notification message - critical displayMFARequired = true; - } else if (notification.MinimumTimeout == 0) { + } else if (notification.MfaMinimumTimeout == 0) { // display notification message, only few services are timed out } else { // display notification message, only few services are about to timeout diff --git a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs index 54fcb91e..72a3049f 100644 --- a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs +++ b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs @@ -325,8 +325,8 @@ namespace ZitiDesktopEdge.DataStructures { public string IdentityName { get; set; } public string Fingerprint { get; set; } public string Message { get; set; } - public int MinimumTimeout { get; set; } - public int MaximumTimeout { get; set; } + public int MfaMinimumTimeout { get; set; } + public int MfaMaximumTimeout { get; set; } public int TimeDuration { get; set; } public string Severity { get; set; } diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index cdf19efe..704735a2 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -74,23 +74,23 @@ type ServiceChange struct { ZitiContext *ZIdentity } type BulkServiceChange struct { - Fingerprint string - HostnamesToAdd map[string]bool - HostnamesToRemove map[string]bool - ServicesToRemove []*dto.Service - ServicesToAdd []*dto.Service - MinTimeout int32 - MaxTimeout int32 - LastUpdatedTime time.Time + Fingerprint string + HostnamesToAdd map[string]bool + HostnamesToRemove map[string]bool + ServicesToRemove []*dto.Service + ServicesToAdd []*dto.Service + MfaMinTimeout int32 + MfaMaxTimeout int32 + MfaLastUpdatedTime time.Time } type NotificationMessage struct { IdentityName string Fingerprint string Message string - MinimumTimeout int32 - MaximumTimeout int32 - TimeDuration int + MfaMinimumTimeout int32 + MfaMaximumTimeout int32 + MfaTimeDuration int Severity string } @@ -139,23 +139,23 @@ type ZService struct { } type ZIdentity struct { - Options *C.ziti_options - czctx C.ziti_context - czid *C.ziti_identity - status int - statusErr error - Loaded bool - Name string - Version string - Services sync.Map - Fingerprint string - Active bool - StatusChanges func(int) - MfaNeeded bool - MfaEnabled bool - MinTimeout int32 - MaxTimeout int32 - LastUpdatedTime time.Time + Options *C.ziti_options + czctx C.ziti_context + czid *C.ziti_identity + status int + statusErr error + Loaded bool + Name string + Version string + Services sync.Map + Fingerprint string + Active bool + StatusChanges func(int) + MfaNeeded bool + MfaEnabled bool + MfaMinTimeout int32 + MfaMaxTimeout int32 + MfaLastUpdatedTime time.Time } func NewZid(statusChange func(int)) *ZIdentity { @@ -163,9 +163,9 @@ func NewZid(statusChange func(int)) *ZIdentity { zid.Services = sync.Map{} zid.Options = (*C.ziti_options)(C.calloc(1, C.sizeof_ziti_options)) zid.StatusChanges = statusChange - zid.MinTimeout = -1 - zid.MaxTimeout = -1 - zid.LastUpdatedTime = time.Now() + zid.MfaMinTimeout = -1 + zid.MfaMaxTimeout = -1 + zid.MfaLastUpdatedTime = time.Now() return zid } @@ -246,7 +246,7 @@ func (zid *ZIdentity) Shutdown() { } func (zid *ZIdentity) RefreshNeeded() bool { - return !(zid.MinTimeout == -1 && zid.MaxTimeout == -1) + return !(zid.MfaMinTimeout == -1 && zid.MfaMaxTimeout == -1) } //export doZitiShutdown @@ -561,35 +561,41 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { var maximumTimeout int32 = -1 noTimeoutSvc := false if len(servicesToAdd) > 0 { - for _, svc := range servicesToAdd { - if svc.Timeout >= 0 { - if minimumTimeout == -1 || minimumTimeout > svc.Timeout { - minimumTimeout = svc.Timeout + zid.Services.Range(func(key interface{}, value interface{}) bool { + //string, ZService + val := value.(*ZService) + + if val.Service.Timeout >= 0 { + if minimumTimeout == -1 || minimumTimeout > val.Service.Timeout { + minimumTimeout = val.Service.Timeout } - if maximumTimeout == -1 || maximumTimeout < svc.Timeout { - maximumTimeout = svc.Timeout + if maximumTimeout == -1 || maximumTimeout < val.Service.Timeout { + maximumTimeout = val.Service.Timeout } } else { noTimeoutSvc = true } - } + + return true + + }) if noTimeoutSvc { maximumTimeout = -1 } } - zid.MinTimeout = minimumTimeout - zid.MaxTimeout = maximumTimeout + zid.MfaMinTimeout = minimumTimeout + zid.MfaMaxTimeout = maximumTimeout svcChange := BulkServiceChange{ - Fingerprint: zid.Fingerprint, - HostnamesToAdd: hostnamesToAdd, - HostnamesToRemove: hostnamesToRemove, - ServicesToAdd: servicesToAdd, - ServicesToRemove: servicesToRemove, - MinTimeout: minimumTimeout, - MaxTimeout: maximumTimeout, - LastUpdatedTime: time.Now(), + Fingerprint: zid.Fingerprint, + HostnamesToAdd: hostnamesToAdd, + HostnamesToRemove: hostnamesToRemove, + ServicesToAdd: servicesToAdd, + ServicesToRemove: servicesToRemove, + MfaMinTimeout: minimumTimeout, + MfaMaxTimeout: maximumTimeout, + MfaLastUpdatedTime: time.Now(), } if len(BulkServiceChanges) == cap(BulkServiceChanges) { diff --git a/service/ziti-tunnel/constants/consts.go b/service/ziti-tunnel/constants/consts.go index f9ae3ce5..38b33090 100644 --- a/service/ziti-tunnel/constants/consts.go +++ b/service/ziti-tunnel/constants/consts.go @@ -18,10 +18,10 @@ package constants const ( - Ipv4ip = "100.64.0.1" - Ipv4MaxMask = 8 - Ipv4MinMask = 16 - Ipv4DefaultMask = 10 - MinimumFrequency = 5 - MaximumFrequency = 20 + Ipv4ip = "100.64.0.1" + Ipv4MaxMask = 10 + Ipv4MinMask = 16 + Ipv4DefaultMask = 10 + MinimumFrequency = 5 // minimum notification window + MaximumFrequency = 20 // maximum notification window ) diff --git a/service/ziti-tunnel/dto/dtos.go b/service/ziti-tunnel/dto/dtos.go index 3288810d..20c88f2c 100644 --- a/service/ziti-tunnel/dto/dtos.go +++ b/service/ziti-tunnel/dto/dtos.go @@ -71,20 +71,20 @@ type HostContext struct { } type Identity struct { - Name string - FingerPrint string - Active bool - Config idcfg.Config - ControllerVersion string - Status string - MfaEnabled bool - MfaNeeded bool - Services []*Service `json:",omitempty"` - Metrics *Metrics `json:",omitempty"` - Tags []string `json:",omitempty"` - MinTimeout int32 - MaxTimeout int32 - LastUpdatedTime time.Time + Name string + FingerPrint string + Active bool + Config idcfg.Config + ControllerVersion string + Status string + MfaEnabled bool + MfaNeeded bool + Services []*Service `json:",omitempty"` + Metrics *Metrics `json:",omitempty"` + Tags []string `json:",omitempty"` + MfaMinTimeout int32 + MfaMaxTimeout int32 + MfaLastUpdatedTime time.Time } type Metrics struct { Up int64 diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index aab297a0..23fd660d 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -63,7 +63,7 @@ func (p *Pipes) Close() { } var shutdown = make(chan bool, 8) //a channel informing go routines to exit -var resetFrequency = make(chan int) +var notificationFrequency *time.Ticker func SubMain(ops chan string, changes chan<- svc.Status, winEvents <-chan WindowsEvents) error { log.Info("============================== service begins ==============================") @@ -1139,7 +1139,7 @@ func handleEvents(isInitialized chan struct{}) { events.run() d := 5 * time.Second every5s := time.NewTicker(d) - notificationFrequency := time.NewTicker(time.Duration(rts.state.NotificationFrequency) * time.Minute) + notificationFrequency = time.NewTicker(time.Duration(rts.state.NotificationFrequency) * time.Minute) defer log.Debugf("exiting handleEvents. loops were set for %v", d) <-isInitialized @@ -1157,39 +1157,6 @@ func handleEvents(isInitialized chan struct{}) { Identities: s.Identities, }) - // refresh timeout of services - for _, id := range rts.ids { - zid := id.CId - if zid == nil || !zid.RefreshNeeded() { - continue - } - - // refresh timeout - zid.Services.Range(func(key interface{}, value interface{}) bool { - //string, ZService - val := value.(*cziti.ZService) - - if val.Service.Timeout <= 0 { - return true - } - - var svcTimeout int32 = -1 - for _, pc := range val.Service.PostureChecks { - if svcTimeout == -1 || svcTimeout > int32(pc.Timeout) { - svcTimeout = int32(pc.Timeout) - } - break - } - if (svcTimeout - int32(time.Since(zid.LastUpdatedTime).Seconds())) < 0 { - atomic.StoreInt32(&val.Service.Timeout, 0) - } else { - atomic.StoreInt32(&val.Service.Timeout, svcTimeout-int32(time.Since(zid.LastUpdatedTime).Seconds())) - } - return true - }) - - } - // notification message case <-notificationFrequency.C: cleanNotifications := make([]cziti.NotificationMessage, 0) @@ -1201,24 +1168,24 @@ func handleEvents(isInitialized chan struct{}) { var notificationMinTimeout int32 = 0 var notificationMaxTimeout int32 = -1 - if (id.CId.MaxTimeout > -1) && (id.CId.MaxTimeout-int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { + if (id.CId.MfaMaxTimeout > -1) && (id.CId.MfaMaxTimeout-int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds())) < 0 { notificationMessage = fmt.Sprintf("All of the services of identity %s are timed out", id.Name) - } else if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { + } else if (id.CId.MfaMinTimeout - int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds())) < 0 { notificationMessage = fmt.Sprintf("Some of the services of identity %s are timed out", id.Name) - } else if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < int32(20*60) { + } else if (id.CId.MfaMinTimeout - int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds())) < int32((constants.MaximumFrequency+5)*60) { notificationMessage = fmt.Sprintf("Some of the services of identity %s are timing out in sometime", id.Name) } - if id.CId.MaxTimeout > -1 { - if (id.CId.MaxTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { + if id.CId.MfaMaxTimeout > -1 { + if (id.CId.MfaMaxTimeout - int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds())) < 0 { notificationMaxTimeout = 0 } else { - notificationMaxTimeout = id.CId.MaxTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds()) + notificationMaxTimeout = id.CId.MfaMaxTimeout - int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds()) } } - if (id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds())) < 0 { + if (id.CId.MfaMinTimeout - int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds())) < 0 { notificationMinTimeout = 0 } else { - notificationMinTimeout = id.CId.MinTimeout - int32(time.Since(id.CId.LastUpdatedTime).Seconds()) + notificationMinTimeout = id.CId.MfaMinTimeout - int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds()) } if len(notificationMessage) > 0 { @@ -1226,10 +1193,10 @@ func handleEvents(isInitialized chan struct{}) { Fingerprint: id.FingerPrint, IdentityName: id.Name, Severity: "major", - MinimumTimeout: notificationMinTimeout, - MaximumTimeout: notificationMaxTimeout, + MfaMinimumTimeout: notificationMinTimeout, + MfaMaximumTimeout: notificationMaxTimeout, Message: notificationMessage, - TimeDuration: int(time.Since(id.CId.LastUpdatedTime).Seconds()), + MfaTimeDuration: int(time.Since(id.CId.MfaLastUpdatedTime).Seconds()), }) } } @@ -1241,13 +1208,14 @@ func handleEvents(isInitialized chan struct{}) { Notification: cleanNotifications, }) } - - case newFrequency := <-resetFrequency: - notificationFrequency.Reset(time.Duration(newFrequency) * time.Minute) } } } +func ResetFrequency(newFrequency int) { + notificationFrequency.Reset(time.Duration(newFrequency) * time.Minute) +} + //Removes the Config from the provided identity and returns a 'cleaned' id func Clean(src *Id) dto.Identity { mfaNeeded := false @@ -1279,16 +1247,31 @@ func Clean(src *Id) dto.Identity { //string, ZService val := value.(*cziti.ZService) + if src.CId.RefreshNeeded() && val.Service.Timeout > 0 { + var svcTimeout int32 = -1 + for _, pc := range val.Service.PostureChecks { + if svcTimeout == -1 || svcTimeout > int32(pc.Timeout) { + svcTimeout = int32(pc.Timeout) + } + break + } + if (svcTimeout - int32(time.Since(src.CId.MfaLastUpdatedTime).Seconds())) < 0 { + atomic.StoreInt32(&val.Service.Timeout, 0) + } else { + atomic.StoreInt32(&val.Service.Timeout, svcTimeout-int32(time.Since(src.CId.MfaLastUpdatedTime).Seconds())) + } + } + nid.Services = append(nid.Services /*svcToDto(val)*/, val.Service) return true }) - nid.MinTimeout = src.CId.MinTimeout - nid.MaxTimeout = src.CId.MaxTimeout + nid.MfaMinTimeout = src.CId.MfaMinTimeout + nid.MfaMaxTimeout = src.CId.MfaMaxTimeout if !src.CId.RefreshNeeded() { - nid.LastUpdatedTime = time.Now() + nid.MfaLastUpdatedTime = time.Now() } else { - nid.LastUpdatedTime = src.CId.LastUpdatedTime - if (nid.MaxTimeout-int32(time.Since(nid.LastUpdatedTime).Seconds())) < 0 && nid.MfaEnabled { + nid.MfaLastUpdatedTime = src.CId.MfaLastUpdatedTime + if (nid.MfaMaxTimeout-int32(time.Since(nid.MfaLastUpdatedTime).Seconds())) < 0 && nid.MfaEnabled { nid.MfaNeeded = true } } @@ -1315,7 +1298,7 @@ func authMfa(out *json.Encoder, fingerprint string, code string) { result := cziti.AuthMFA(id.CId, code) if result == nil { id.CId.MfaNeeded = false - id.CId.LastUpdatedTime = time.Now() + id.CId.MfaLastUpdatedTime = time.Now() respond(out, dto.Response{Message: "AuthMFA complete", Code: SUCCESS, Error: "", Payload: fingerprint}) } else { respondWithError(out, fmt.Sprintf("AuthMFA failed. the supplied code [%s] was not valid: %s", code, result), 1, result) @@ -1362,7 +1345,7 @@ func updateNotificationFrequency(out *json.Encoder, notificationFreq int) { return } - resetFrequency <- notificationFreq + ResetFrequency(notificationFreq) } respond(out, dto.Response{Message: "Notification frequency is set", Code: SUCCESS, Error: "", Payload: ""}) diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index 368d81c1..d53419b3 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -155,15 +155,15 @@ func (t *RuntimeState) ToMetrics() dto.TunnelStatus { for _, id := range t.ids { AddMetrics(id) clean.Identities[i] = &dto.Identity{ - Name: id.Name, - FingerPrint: id.FingerPrint, - Metrics: id.Metrics, - Active: id.Active, - MfaEnabled: id.MfaEnabled, - MfaNeeded: id.MfaNeeded, - MinTimeout: id.MinTimeout, - MaxTimeout: id.MaxTimeout, - LastUpdatedTime: id.LastUpdatedTime, + Name: id.Name, + FingerPrint: id.FingerPrint, + Metrics: id.Metrics, + Active: id.Active, + MfaEnabled: id.MfaEnabled, + MfaNeeded: id.MfaNeeded, + MfaMinTimeout: id.MfaMinTimeout, + MfaMaxTimeout: id.MfaMaxTimeout, + MfaLastUpdatedTime: id.MfaLastUpdatedTime, } i++ } @@ -326,7 +326,7 @@ func (t *RuntimeState) LoadConfig() { rts.UpdateIpv4Mask(constants.Ipv4MinMask) } - if t.state.NotificationFrequency == 0 { + if t.state.NotificationFrequency < constants.MinimumFrequency { rts.UpdateNotificationFrequency(constants.MinimumFrequency) } } From 8ecb6c65165c957da6331d64ccff9f56302a2068 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Thu, 22 Jul 2021 12:13:17 +0530 Subject: [PATCH 38/46] fixing timing issue --- service/ziti-tunnel/service/ipc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 23fd660d..63c6acc4 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -1172,7 +1172,7 @@ func handleEvents(isInitialized chan struct{}) { notificationMessage = fmt.Sprintf("All of the services of identity %s are timed out", id.Name) } else if (id.CId.MfaMinTimeout - int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds())) < 0 { notificationMessage = fmt.Sprintf("Some of the services of identity %s are timed out", id.Name) - } else if (id.CId.MfaMinTimeout - int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds())) < int32((constants.MaximumFrequency+5)*60) { + } else if (id.CId.MfaMinTimeout - int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds())) < int32((constants.MaximumFrequency+rts.state.NotificationFrequency)*60) { notificationMessage = fmt.Sprintf("Some of the services of identity %s are timing out in sometime", id.Name) } if id.CId.MfaMaxTimeout > -1 { From de6561f812698ad8c56581d667fc0d4593a41fd6 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Thu, 22 Jul 2021 14:24:47 +0530 Subject: [PATCH 39/46] updating startup folder in the aip package --- Installer/ZitiDesktopEdge.aip | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Installer/ZitiDesktopEdge.aip b/Installer/ZitiDesktopEdge.aip index a8a6864e..9b560bb2 100644 --- a/Installer/ZitiDesktopEdge.aip +++ b/Installer/ZitiDesktopEdge.aip @@ -23,10 +23,10 @@ - + - + @@ -45,6 +45,7 @@ + @@ -336,6 +337,7 @@ + From 39ec07ec71ea79cbebd5112f96af5fe88d97d4d1 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Thu, 22 Jul 2021 21:18:30 +0530 Subject: [PATCH 40/46] code review changes --- service/cziti/sdk.go | 27 +++++++++- service/ziti-tunnel/constants/consts.go | 4 ++ service/ziti-tunnel/service/ipc.go | 65 +++++++++++++++++-------- 3 files changed, 75 insertions(+), 21 deletions(-) diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 704735a2..431a8743 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -47,6 +47,7 @@ import ( "encoding/json" "errors" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/api" + "github.com/openziti/desktop-edge-win/service/ziti-tunnel/constants" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/util/logging" "net" @@ -245,10 +246,34 @@ func (zid *ZIdentity) Shutdown() { C.uv_async_send((*C.uv_async_t)(unsafe.Pointer(async))) } -func (zid *ZIdentity) RefreshNeeded() bool { +func (zid *ZIdentity) MfaRefreshNeeded() bool { return !(zid.MfaMinTimeout == -1 && zid.MfaMaxTimeout == -1) } +func (zid *ZIdentity) GetRemainingTime(timeout int32) int32 { + var remainingTimeout int32 + if (timeout - int32(time.Since(zid.MfaLastUpdatedTime).Seconds())) <= 0 { + remainingTimeout = 0 + } else { + remainingTimeout = timeout - int32(time.Since(zid.MfaLastUpdatedTime).Seconds()) + } + return remainingTimeout +} + +func (zid *ZIdentity) GetMFAState(interval int32) int { + var mfaState int + if (zid.MfaMaxTimeout > -1) && (zid.MfaMaxTimeout-int32(time.Since(zid.MfaLastUpdatedTime).Seconds())) < 0 { + mfaState = constants.MfaAllSvcTimeout + } else if (zid.MfaMinTimeout - int32(time.Since(zid.MfaLastUpdatedTime).Seconds())) < 0 { + mfaState = constants.MfaFewSvcTimeout + } else if (zid.MfaMinTimeout - int32(time.Since(zid.MfaLastUpdatedTime).Seconds())) < interval { + mfaState = constants.MfaNearingTimeout + } else { + mfaState = -1 + } + return mfaState +} + //export doZitiShutdown func doZitiShutdown(async *C.uv_async_t) { ctx := C.ziti_context(async.data) diff --git a/service/ziti-tunnel/constants/consts.go b/service/ziti-tunnel/constants/consts.go index 38b33090..4496b4f1 100644 --- a/service/ziti-tunnel/constants/consts.go +++ b/service/ziti-tunnel/constants/consts.go @@ -24,4 +24,8 @@ const ( Ipv4DefaultMask = 10 MinimumFrequency = 5 // minimum notification window MaximumFrequency = 20 // maximum notification window + + MfaAllSvcTimeout = 0 + MfaFewSvcTimeout = 1 + MfaNearingTimeout = 2 ) diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 63c6acc4..7ee17ce4 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -38,6 +38,7 @@ import ( "golang.zx2c4.com/wireguard/tun" "io" "io/ioutil" + "math" "math/rand" "net" "os" @@ -1135,6 +1136,33 @@ func handleBulkServiceChange(sc cziti.BulkServiceChange) { rts.BroadcastEvent(m) } +func addUnit(count int, unit string) (result string) { + if (count == 1) || (count == 0) { + result = strconv.Itoa(count) + " " + unit + " " + } else { + result = strconv.Itoa(count) + " " + unit + "s " + } + return +} + +func secondsToReadableFmt(input int32) (result string) { + seconds := input % (60 * 60 * 24) + hours := math.Floor(float64(seconds) / 60 / 60) + seconds = input % (60 * 60) + minutes := math.Floor(float64(seconds) / 60) + seconds = input % 60 + + if hours > 0 { + result = addUnit(int(hours), "hour") + addUnit(int(minutes), "minute") + addUnit(int(seconds), "second") + } else if minutes > 0 { + result = addUnit(int(minutes), "minute") + addUnit(int(seconds), "second") + } else { + result = addUnit(int(seconds), "second") + } + + return +} + func handleEvents(isInitialized chan struct{}) { events.run() d := 5 * time.Second @@ -1161,34 +1189,31 @@ func handleEvents(isInitialized chan struct{}) { case <-notificationFrequency.C: cleanNotifications := make([]cziti.NotificationMessage, 0) for _, id := range rts.ids { - if id.CId == nil || !id.CId.RefreshNeeded() { + if id.CId == nil || !id.CId.MfaRefreshNeeded() { continue } notificationMessage := "" var notificationMinTimeout int32 = 0 var notificationMaxTimeout int32 = -1 - if (id.CId.MfaMaxTimeout > -1) && (id.CId.MfaMaxTimeout-int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds())) < 0 { + switch mfaState := id.CId.GetMFAState(int32((constants.MaximumFrequency+rts.state.NotificationFrequency)*60)); mfaState { + case constants.MfaAllSvcTimeout: notificationMessage = fmt.Sprintf("All of the services of identity %s are timed out", id.Name) - } else if (id.CId.MfaMinTimeout - int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds())) < 0 { + case constants.MfaFewSvcTimeout: notificationMessage = fmt.Sprintf("Some of the services of identity %s are timed out", id.Name) - } else if (id.CId.MfaMinTimeout - int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds())) < int32((constants.MaximumFrequency+rts.state.NotificationFrequency)*60) { - notificationMessage = fmt.Sprintf("Some of the services of identity %s are timing out in sometime", id.Name) + case constants.MfaNearingTimeout: + notificationMinTimeout = id.CId.GetRemainingTime(id.CId.MfaMinTimeout) + notificationMessage = fmt.Sprintf("Some of the services of identity %s are timing out in %s", id.Name, secondsToReadableFmt(notificationMinTimeout)) + default: + // do nothing } - if id.CId.MfaMaxTimeout > -1 { - if (id.CId.MfaMaxTimeout - int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds())) < 0 { - notificationMaxTimeout = 0 - } else { - notificationMaxTimeout = id.CId.MfaMaxTimeout - int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds()) - } - } - if (id.CId.MfaMinTimeout - int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds())) < 0 { - notificationMinTimeout = 0 - } else { - notificationMinTimeout = id.CId.MfaMinTimeout - int32(time.Since(id.CId.MfaLastUpdatedTime).Seconds()) - } - if len(notificationMessage) > 0 { + + if id.CId.MfaMaxTimeout > -1 { + notificationMaxTimeout = id.CId.GetRemainingTime(id.CId.MfaMaxTimeout) + } + notificationMinTimeout = id.CId.GetRemainingTime(id.CId.MfaMinTimeout) + cleanNotifications = append(cleanNotifications, cziti.NotificationMessage{ Fingerprint: id.FingerPrint, IdentityName: id.Name, @@ -1247,7 +1272,7 @@ func Clean(src *Id) dto.Identity { //string, ZService val := value.(*cziti.ZService) - if src.CId.RefreshNeeded() && val.Service.Timeout > 0 { + if src.CId.MfaRefreshNeeded() && val.Service.Timeout > 0 { var svcTimeout int32 = -1 for _, pc := range val.Service.PostureChecks { if svcTimeout == -1 || svcTimeout > int32(pc.Timeout) { @@ -1267,7 +1292,7 @@ func Clean(src *Id) dto.Identity { }) nid.MfaMinTimeout = src.CId.MfaMinTimeout nid.MfaMaxTimeout = src.CId.MfaMaxTimeout - if !src.CId.RefreshNeeded() { + if !src.CId.MfaRefreshNeeded() { nid.MfaLastUpdatedTime = time.Now() } else { nid.MfaLastUpdatedTime = src.CId.MfaLastUpdatedTime From f84befef193b1704d645108a80507da2a730a261 Mon Sep 17 00:00:00 2001 From: ziti-ci Date: Thu, 22 Jul 2021 15:58:25 +0000 Subject: [PATCH 41/46] [ci skip] committing updated version related files --- DesktopEdge/Properties/AssemblyInfo.cs | 6 +++--- ZitiUpdateService/Properties/AssemblyInfo.cs | 6 +++--- service/ziti-tunnel/version.go | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/DesktopEdge/Properties/AssemblyInfo.cs b/DesktopEdge/Properties/AssemblyInfo.cs index 745f32e5..4b76b04f 100644 --- a/DesktopEdge/Properties/AssemblyInfo.cs +++ b/DesktopEdge/Properties/AssemblyInfo.cs @@ -50,6 +50,6 @@ using System.Windows; // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -// [assembly: AssemblyVersion("1.9.10.0")] -[assembly: AssemblyVersion("1.9.10.0")] -[assembly: AssemblyFileVersion("1.9.10.0")] +// [assembly: AssemblyVersion("1.10.0.0")] +[assembly: AssemblyVersion("1.10.0.0")] +[assembly: AssemblyFileVersion("1.10.0.0")] diff --git a/ZitiUpdateService/Properties/AssemblyInfo.cs b/ZitiUpdateService/Properties/AssemblyInfo.cs index 26778098..fbe51c90 100644 --- a/ZitiUpdateService/Properties/AssemblyInfo.cs +++ b/ZitiUpdateService/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -// [assembly: AssemblyVersion("1.9.10.0")] -[assembly: AssemblyVersion("1.9.10.0")] -[assembly: AssemblyFileVersion("1.9.10.0")] +// [assembly: AssemblyVersion("1.10.0.0")] +[assembly: AssemblyVersion("1.10.0.0")] +[assembly: AssemblyFileVersion("1.10.0.0")] diff --git a/service/ziti-tunnel/version.go b/service/ziti-tunnel/version.go index 24f3ff2f..a3919eb2 100644 --- a/service/ziti-tunnel/version.go +++ b/service/ziti-tunnel/version.go @@ -20,9 +20,9 @@ package main const ( - Version = "1.9.11" - Revision = "460ceb839fa5" + Version = "1.10.0" + Revision = "efac1fb0a5f2" Branch = "release-next" BuildUser = "" - BuildDate = "2021-07-20 16:05:41" + BuildDate = "2021-07-22 15:53:14" ) From 30e8d630cf643bb18fdedf2192bb398bc38b5137 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Fri, 23 Jul 2021 14:00:55 +0530 Subject: [PATCH 42/46] install immediately if the installer is marked as critical --- ZitiUpdateService/App.config | 2 +- ZitiUpdateService/UpdateService.cs | 30 ++++++++++++++++-------------- release-notes.md | 2 +- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/ZitiUpdateService/App.config b/ZitiUpdateService/App.config index d933c958..355a075b 100644 --- a/ZitiUpdateService/App.config +++ b/ZitiUpdateService/App.config @@ -11,7 +11,7 @@ This operation is should probably remain high such as "1:0:0" (every hour) or "1:0:0:0" (every day) --> - + diff --git a/ZitiUpdateService/UpdateService.cs b/ZitiUpdateService/UpdateService.cs index 90a91436..48d7ba03 100644 --- a/ZitiUpdateService/UpdateService.cs +++ b/ZitiUpdateService/UpdateService.cs @@ -668,22 +668,13 @@ namespace ZitiUpdateService { } if (sender == null && e == null) { - Logger.Info("package is in {0} - moving to install phase", fileDestination); - - if (!check.HashIsValid(updateFolder, filename)) { - Logger.Warn("The file was downloaded but the hash is not valid. The file will be removed: {0}", fileDestination); - File.Delete(fileDestination); - semaphore.Release(); - return; - } - Logger.Debug("downloaded file hash was correct. update can continue."); - new SignedFileValidator(fileDestination).Verify(); - - installZDE(fileDestination); + installZDE(fileDestination, filename); } else { Checkers.ZDEInstallerInfo info = check.GetZDEInstallerInfo(fileDestination); - if (info.IsCritical && _installationReminder == null) { + if (info.IsCritical) { + installZDE(fileDestination, filename); + } else if (!info.IsCritical && _installationReminder == null) { // Timer for installation reminder var installationReminderInterval = ConfigurationManager.AppSettings.Get("InstallationReminder"); var instInt = TimeSpan.Zero; @@ -724,7 +715,18 @@ namespace ZitiUpdateService { semaphore.Release(); } - private void installZDE(string fileDestination) { + private void installZDE(string fileDestination, string filename) { + Logger.Info("package is in {0} - moving to install phase", fileDestination); + + if (!check.HashIsValid(updateFolder, filename)) { + Logger.Warn("The file was downloaded but the hash is not valid. The file will be removed: {0}", fileDestination); + File.Delete(fileDestination); + semaphore.Release(); + return; + } + Logger.Debug("downloaded file hash was correct. update can continue."); + new SignedFileValidator(fileDestination).Verify(); + try { StopZiti(); StopUI().Wait(); diff --git a/release-notes.md b/release-notes.md index 180a07da..8913fceb 100644 --- a/release-notes.md +++ b/release-notes.md @@ -4,7 +4,7 @@ * none ## Other changes: -* [#278](https://github.com/openziti/desktop-edge-win/issues/278) inform the user an update is available before automatically updating. So user can manually install the latest version anytime within 1 week after the release is published. If a major/minor version has changed or if the client is missing 5 updates, then the auto installation will start in 4 hours. If the user does not initiate manual installation within the given time, a warning will be displayed for 4 hours and ZDE will auto update. +* [#278](https://github.com/openziti/desktop-edge-win/issues/278) inform the user an update is available before automatically updating. So user can manually install the latest version anytime within 1 week after the release is published. If a major/minor version has changed or if the client is missing 5 updates, then the auto installation will start immediately. If the user does not initiate manual installation within the given time, a warning will be displayed for 2 hours and ZDE will auto update. * mfa timeout process ## Other changes: From 35e914e08748621e5f169cc376e77d2209ea8b6d Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Fri, 23 Jul 2021 14:02:10 +0530 Subject: [PATCH 43/46] uncommenting code --- ZitiUpdateService/UpdateService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZitiUpdateService/UpdateService.cs b/ZitiUpdateService/UpdateService.cs index 48d7ba03..45c70b44 100644 --- a/ZitiUpdateService/UpdateService.cs +++ b/ZitiUpdateService/UpdateService.cs @@ -582,7 +582,7 @@ namespace ZitiUpdateService { ConfigureCheck(); - // for testing checkUpdateImmediately(); + checkUpdateImmediately(); try { dataClient.ConnectAsync().Wait(); From b2e3c8eac48bbdbceadb9b556a100dd861fe53a8 Mon Sep 17 00:00:00 2001 From: mary-dcouto Date: Fri, 23 Jul 2021 14:16:10 +0530 Subject: [PATCH 44/46] send notification only once --- DesktopEdge/MainWindow.xaml.cs | 2 +- ZitiUpdateService/UpdateService.cs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index c9e3a71f..83b468d8 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -688,7 +688,7 @@ namespace ZitiDesktopEdge { IsUpdateAvailable = true; MainMenu.ShowUpdateAvailable(evt.TimeRemaining, evt.InstallTime); AlertCanvas.Visibility = Visibility.Visible; - ShowToast("An Update is Available for Ziti Desktop Edge"); + ShowToast("An Update is Available for Ziti Desktop Edge, will initiate auto installation by " + evt.InstallTime); SetNotifyIcon(""); // display a tag in UI and a button for the update software } diff --git a/ZitiUpdateService/UpdateService.cs b/ZitiUpdateService/UpdateService.cs index 45c70b44..a9a18e59 100644 --- a/ZitiUpdateService/UpdateService.cs +++ b/ZitiUpdateService/UpdateService.cs @@ -689,6 +689,10 @@ namespace ZitiUpdateService { _installationReminder = new CustomTimer(callback, state, instInt, instInt); state._timer = _installationReminder; Logger.Info("Installation reminder for ZDE version {0} is set to {1}", info.Version, instInt); + + info.TimeRemaining = _installationReminder.DueTime.TotalMilliseconds / 1000; // converting to seconds + info.InstallTime = DateTime.Now.AddMilliseconds(_installationReminder.DueTime.TotalMilliseconds); + NotifyInstallationUpdates(info, 0, ""); } if (_installationReminder != null) { @@ -696,9 +700,6 @@ namespace ZitiUpdateService { info.InstallTime = DateTime.Now.AddMilliseconds(_installationReminder.DueTime.TotalMilliseconds); Logger.Info("Installation of ZDE version {0} will be initiated in {1} seconds, approximately at {2}", info.Version, info.TimeRemaining, info.InstallTime); } - if (info.Version != null) { - NotifyInstallationUpdates(info, 0, ""); - } } } catch (Exception ex) { try { From 4023454ad5fb1dd672fedc6cede10ca534324f9b Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 26 Jul 2021 20:45:23 +0530 Subject: [PATCH 45/46] add notifications library into installer --- Installer/ZitiDesktopEdge.aip | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Installer/ZitiDesktopEdge.aip b/Installer/ZitiDesktopEdge.aip index 9b560bb2..1c3c8f44 100644 --- a/Installer/ZitiDesktopEdge.aip +++ b/Installer/ZitiDesktopEdge.aip @@ -23,7 +23,7 @@ - + @@ -53,6 +53,7 @@ + @@ -95,6 +96,7 @@ + @@ -261,6 +263,7 @@ + From 9fd0a11816af69bc5c159add212cff607695e964 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 26 Jul 2021 21:09:49 +0530 Subject: [PATCH 46/46] updating t-sdk version --- ZitiUpdateService/checkers/GithubCheck.cs | 5 +---- service/build.bat | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/ZitiUpdateService/checkers/GithubCheck.cs b/ZitiUpdateService/checkers/GithubCheck.cs index 0d2b215b..a1b495e4 100644 --- a/ZitiUpdateService/checkers/GithubCheck.cs +++ b/ZitiUpdateService/checkers/GithubCheck.cs @@ -181,10 +181,7 @@ namespace ZitiUpdateService.Checkers { } else { Logger.Debug("Comparing Version {0}, with current {1}", info.Version.ToString(), assemblyVersion.ToString()); - if (info.Version.Build - assemblyVersion.Build >= 5) { - info.IsCritical = true; - Logger.Info("ZDEInstaller is marked as critical because the client is behind 5 updates"); - } else if ((info.Version.Major - assemblyVersion.Major >= 1) || (info.Version.Minor - assemblyVersion.Minor >= 1)) { + if ((info.Version.Major - assemblyVersion.Major >= 1) || (info.Version.Minor - assemblyVersion.Minor >= 1)) { info.IsCritical = true; Logger.Info("ZDEInstaller is marked as critical because the major/minor version has changed"); } else { diff --git a/service/build.bat b/service/build.bat index 89a01469..799c976e 100644 --- a/service/build.bat +++ b/service/build.bat @@ -14,7 +14,7 @@ REM See the License for the specific language governing permissions and REM limitations under the License. REM SET REPO_URL=https://github.com/openziti/ziti-tunnel-sdk-c.git -SET ZITI_TUNNEL_REPO_BRANCH=v0.15.9 +SET ZITI_TUNNEL_REPO_BRANCH=v0.15.10 REM override the c sdk used in the build - leave blank for the same as specified in the tunneler sdk SET ZITI_SDK_C_BRANCH= REM the number of TCP connections the tunneler sdk can have at any one time