From 6ef72b86e94308c59a91d88becb5491f03cbbdb5 Mon Sep 17 00:00:00 2001 From: Jeremy Tellier - ROG Date: Thu, 8 Apr 2021 12:10:16 +0100 Subject: [PATCH 01/19] Auth Loading, Clickable fields, Easier AuthUX, Paging, Sorting, Max Service Load --- DesktopEdge/App.xaml | 18 ++++ DesktopEdge/MainWindow.xaml.cs | 19 +++-- DesktopEdge/Views/Controls/Toggler.xaml.cs | 7 ++ .../Views/ItemRenderers/IdentityItem.xaml | 17 +++- .../Views/ItemRenderers/IdentityItem.xaml.cs | 12 +++ .../Views/Screens/IdentityDetails.xaml | 39 ++++++++- .../Views/Screens/IdentityDetails.xaml.cs | 84 +++++++++++++++++-- DesktopEdge/Views/Screens/MFAScreen.xaml | 34 ++++---- DesktopEdge/Views/Screens/MFAScreen.xaml.cs | 75 +++++++++-------- DesktopEdge/ZitiDesktopEdge.csproj | 1 + 10 files changed, 235 insertions(+), 71 deletions(-) diff --git a/DesktopEdge/App.xaml b/DesktopEdge/App.xaml index 4137cd29..bcd9158d 100644 --- a/DesktopEdge/App.xaml +++ b/DesktopEdge/App.xaml @@ -149,5 +149,23 @@ + + + diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index f46d31e8..d1cc038b 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -174,7 +174,7 @@ namespace ZitiDesktopEdge { /// The Ziti Identity to Authenticate public void ShowMFARecoveryCodes(ZitiIdentity identity) { if (identity.MFAInfo!=null) { - if (identity.MFAInfo.RecoveryCodes?.Length > 0) { + if (identity.MFAInfo.IsAuthenticated&& identity.MFAInfo.RecoveryCodes!=null) { MFASetup.Opacity = 0; MFASetup.Visibility = Visibility.Visible; MFASetup.Margin = new Thickness(0, 0, 0, 0); @@ -252,11 +252,7 @@ namespace ZitiDesktopEdge { if (IdentityMenu.IsVisible) { if (isComplete) { if (MFASetup.Type == 2) { - if (IdentityMenu.Identity.MFAInfo?.RecoveryCodes?.Length > 0) { - ShowRecovery(IdentityMenu.Identity); - } else { - ShowBlurbAsync("You do not have anymore recovery codes", this.RECOVER); - } + ShowRecovery(IdentityMenu.Identity); } else if (MFASetup.Type == 3) { IdentityMenu.Identity.IsMFAEnabled = false; IdentityMenu.Identity.MFAInfo.IsAuthenticated = false; @@ -346,9 +342,15 @@ namespace ZitiDesktopEdge { this.IdentityMenu.MainWindow = this; SetNotifyIcon("white"); + MFASetup.OnLoad += MFASetup_OnLoad; IdentityMenu.OnMessage += IdentityMenu_OnMessage; } + private void MFASetup_OnLoad(bool isComplete, string title, string message) { + if (isComplete) HideLoad(); + else ShowLoad(title, message); + } + private void Current_SessionEnding(object sender, SessionEndingCancelEventArgs e) { if (notifyIcon != null) { notifyIcon.Visible = false; @@ -698,6 +700,9 @@ namespace ZitiDesktopEdge { private void ServiceClient_OnClientDisconnected(object sender, object e) { this.Dispatcher.Invoke(() => { + IdentityMenu.Visibility = Visibility.Collapsed; + MFASetup.Visibility = Visibility.Collapsed; + HideModal(); IdList.Children.Clear(); if (e != null) { logger.Debug(e.ToString()); @@ -772,6 +777,8 @@ namespace ZitiDesktopEdge { this.Dispatcher.Invoke(() => { var found = identities.Find(id => id.Fingerprint == e.Fingerprint); + Debug.WriteLine(e.Action+" Calling Service Appender"); + if (found == null) { Debug.WriteLine($"{e.Action} service event for {e.Service.Name} but the provided identity fingerprint {e.Fingerprint} is not found!"); return; diff --git a/DesktopEdge/Views/Controls/Toggler.xaml.cs b/DesktopEdge/Views/Controls/Toggler.xaml.cs index db20d222..dd0dc4f8 100644 --- a/DesktopEdge/Views/Controls/Toggler.xaml.cs +++ b/DesktopEdge/Views/Controls/Toggler.xaml.cs @@ -54,6 +54,13 @@ namespace ZitiDesktopEdge { } } } + + public void Toggle() { + Enabled = !Enabled; + if (OnToggled != null) { + OnToggled(Enabled); + } + } private void OnToggle(object sender, RoutedEventArgs e) { e.Handled = true; diff --git a/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml b/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml index fdef3fd4..e0d7ff4e 100644 --- a/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml +++ b/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml @@ -12,7 +12,7 @@ - + @@ -24,22 +24,31 @@ + - + + diff --git a/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml.cs b/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml.cs index fb7ef1a9..1b75ed8e 100644 --- a/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml.cs +++ b/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml.cs @@ -115,5 +115,17 @@ namespace ZitiDesktopEdge { private void MFAAuthenticate(object sender, MouseButtonEventArgs e) { this.Authenticate?.Invoke(_identity); } + + private void ToggledSwitch(object sender, MouseButtonEventArgs e) { + ToggleSwitch.Toggle(); + } + + private void DoMFAOrOpen(object sender, MouseButtonEventArgs e) { + if (MfaRequired.Visibility==Visibility.Visible) { + MFAAuthenticate(sender, e); + } else { + OpenDetails(sender, e); + } + } } } diff --git a/DesktopEdge/Views/Screens/IdentityDetails.xaml b/DesktopEdge/Views/Screens/IdentityDetails.xaml index 748816b4..408e801a 100644 --- a/DesktopEdge/Views/Screens/IdentityDetails.xaml +++ b/DesktopEdge/Views/Screens/IdentityDetails.xaml @@ -50,7 +50,7 @@ - + @@ -78,10 +78,41 @@ - - + + + + + + + + + + + + + + + - + + + Name + Address + Protocol + Port + + + + + + + Asc + Desc + + + + + diff --git a/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs b/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs index f15ce065..ebaa8140 100644 --- a/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs +++ b/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs @@ -35,6 +35,10 @@ namespace ZitiDesktopEdge { public event OnAuthenticate Authenticate; public delegate void OnRecovery(ZitiIdentity identity); public event OnRecovery Recovery; + public int Page = 1; + public int PerPage = 50; + public string SortBy = "Name"; + public string SortWay = "Asc"; internal MainWindow MainWindow { get; set; } @@ -53,6 +57,11 @@ namespace ZitiDesktopEdge { set { _identity = value; this.IdDetailToggle.Enabled = _identity.IsEnabled; + Page = 1; + SortBy = "Name"; + SortWay = "Asc"; + SortByField.SelectedIndex = 0; + SortWayField.SelectedIndex = 0; UpdateView(); IdentityArea.Opacity = 1.0; IdentityArea.Visibility = Visibility.Visible; @@ -117,17 +126,45 @@ namespace ZitiDesktopEdge { IdentityMFA.RecoveryButton.Visibility = Visibility.Collapsed; } ServiceList.Children.Clear(); + PageSortArea.Visibility = Visibility.Collapsed; if (_identity.Services.Count>0) { - foreach(var zitiSvc in _identity.Services.OrderBy(s => s.Name.ToLower())) { - if (zitiSvc.Name.ToLower().IndexOf(filter.ToLower()) >=0||zitiSvc.ToString().ToLower().IndexOf(filter.ToLower()) >=0) { - Logger.Trace("painting: " + zitiSvc.Name); - ServiceInfo info = new ServiceInfo(); - info.Info = zitiSvc; - info.OnMessage += Info_OnMessage; - info.OnDetails += ShowDetails; - ServiceList.Children.Add(info); + PageSortArea.Visibility = Visibility.Visible; + int index = 0; + int total = 0; + ZitiService[] services = new ZitiService[0]; + if (SortBy == "Name") services = _identity.Services.OrderBy(s => s.Name.ToLower()).ToArray(); + else if (SortBy == "Address") services = _identity.Services.OrderBy(s => s.Addresses.ToString()).ToArray(); + else if (SortBy == "Protocol") services = _identity.Services.OrderBy(s => s.Protocols.ToString()).ToArray(); + else if (SortBy == "Port") services = _identity.Services.OrderBy(s => s.Ports.ToString()).ToArray(); + if (SortWay == "Desc") services = services.Reverse().ToArray(); + int startIndex = (Page - 1) * PerPage; + for (int i= startIndex; i= 0 || zitiSvc.ToString().ToLower().IndexOf(filter.ToLower()) >= 0) { + Logger.Trace("painting: " + zitiSvc.Name); + ServiceInfo info = new ServiceInfo(); + info.Info = zitiSvc; + info.OnMessage += Info_OnMessage; + info.OnDetails += ShowDetails; + ServiceList.Children.Add(info); + index++; + } } } + + if (Page==1) { + Pages.Items.Clear(); + int totalPages = (total / PerPage) + 1; + for (int i = 1; i <= totalPages; i++) { + ComboBoxItem item = new ComboBoxItem(); + if (i == Page) item.IsSelected = true; + item.Content = i.ToString(); + Pages.Items.Add(item); + } + } + double newHeight = MainHeight - 330; ServiceRow.Height = new GridLength((double)newHeight); MainDetailScroll.MaxHeight = newHeight; @@ -326,5 +363,36 @@ namespace ZitiDesktopEdge { private void AuthFromMessage(object sender, MouseButtonEventArgs e) { this.Authenticate.Invoke(this.Identity); } + + private void Pages_SelectionChanged(object sender, SelectionChangedEventArgs e) { + ComboBoxItem selected = (ComboBoxItem)Pages.SelectedValue; + if (selected!=null) { + int value = Int32.Parse(selected.Content.ToString()); + if (value!=Page) { + Page = value; + UpdateView(); + } + } + } + + private void SortByField_SelectionChanged(object sender, SelectionChangedEventArgs e) { + ComboBoxItem selected = (ComboBoxItem)SortByField.SelectedValue; + if (selected != null && selected.Content!=null) { + if (selected.Content.ToString()!=SortBy) { + SortBy = selected.Content.ToString(); + UpdateView(); + } + } + } + + private void SortWayField_SelectionChanged(object sender, SelectionChangedEventArgs e) { + ComboBoxItem selected = (ComboBoxItem)SortWayField.SelectedValue; + if (selected != null && selected.Content != null) { + if (selected.Content.ToString() != SortWay) { + SortWay = selected.Content.ToString(); + UpdateView(); + } + } + } } } diff --git a/DesktopEdge/Views/Screens/MFAScreen.xaml b/DesktopEdge/Views/Screens/MFAScreen.xaml index 26d15bcf..d71f88d2 100644 --- a/DesktopEdge/Views/Screens/MFAScreen.xaml +++ b/DesktopEdge/Views/Screens/MFAScreen.xaml @@ -13,11 +13,19 @@ - + + + + + + + + + @@ -51,7 +59,7 @@ - + - - - - - - - - + - + + diff --git a/DesktopEdge/Views/Screens/MFAScreen.xaml.cs b/DesktopEdge/Views/Screens/MFAScreen.xaml.cs index 9563833d..e626d46d 100644 --- a/DesktopEdge/Views/Screens/MFAScreen.xaml.cs +++ b/DesktopEdge/Views/Screens/MFAScreen.xaml.cs @@ -31,6 +31,8 @@ namespace ZitiDesktopEdge { public partial class MFAScreen : UserControl { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + public delegate void LoadEvent(bool isComplete, string title, string message); + public event LoadEvent OnLoad; public delegate void CloseAction(bool isComplete); public event CloseAction OnClose; private string _url = ""; @@ -83,10 +85,14 @@ namespace ZitiDesktopEdge { this._identity = identity; MFAImage.Visibility = Visibility.Visible; SecretCode.Visibility = Visibility.Collapsed; + CloseBlack.Visibility = Visibility.Visible; + CloseWhite.Visibility = Visibility.Collapsed; SecretButton.Content = "Show Secret"; IdName.Content = identity.Name; Logger.Debug($"MFA Url: {url}"); - + AuthBrush.Visibility = Visibility.Collapsed; + MainBrush.Visibility = Visibility.Visible; + MFAImage.Source = CreateQRFromUrl(url); SecretCode.Text = secret; @@ -107,24 +113,39 @@ namespace ZitiDesktopEdge { MFARecoveryArea.Visibility = Visibility.Visible; RecoveryList.Children.Clear(); _codes = codes; + AuthBrush.Visibility = Visibility.Collapsed; + MainBrush.Visibility = Visibility.Visible; + CloseBlack.Visibility = Visibility.Visible; + CloseWhite.Visibility = Visibility.Collapsed; MFAArea.Height = 380; - for (int i=0; i0) { + for (int i = 0; i < codes.Length; i++) { + TextBox label = new TextBox(); + label.Text = codes[i]; + label.BorderThickness = new Thickness(0); + label.Background = new SolidColorBrush(); + label.Background.Opacity = 0; + label.HorizontalAlignment = HorizontalAlignment.Center; + label.HorizontalContentAlignment = HorizontalAlignment.Center; + label.VerticalAlignment = VerticalAlignment.Center; + label.VerticalContentAlignment = VerticalAlignment.Center; + RecoveryList.Children.Add(label); + } + RecoveryList.Visibility = Visibility.Visible; + NoRecovery.Visibility = Visibility.Collapsed; + } else { + RecoveryList.Visibility = Visibility.Collapsed; + NoRecovery.Visibility = Visibility.Visible; } } public void ShowMFA(ZitiIdentity identity, int type) { this.Type = type; AuthCode.Text = ""; + AuthBrush.Visibility = Visibility.Visible; + MainBrush.Visibility = Visibility.Collapsed; + CloseBlack.Visibility = Visibility.Collapsed; + CloseWhite.Visibility = Visibility.Visible; this._identity = identity; MFASetupArea.Visibility = Visibility.Collapsed; MFARecoveryArea.Visibility = Visibility.Collapsed; @@ -152,21 +173,6 @@ namespace ZitiDesktopEdge { } } - private void ToggleRecovery(object sender, MouseButtonEventArgs e) { - AuthCode.Text = ""; - if (AuthCode.MaxLength==6) { - GenerateMFACodes(null, null); - AuthCode.MaxLength = 8; - ToggleType.Content = "Use Auth Code"; - AuthSubTitle.Content = "Enter a recovery code"; - AuthCode.Focus(); - } else { - AuthCode.MaxLength = 6; - ToggleType.Content = "Use Recovery Code"; - AuthSubTitle.Content = "Enter your authorization code"; - AuthCode.Focus(); - } - } async private void ReturnMFACodes(object sender, MouseButtonEventArgs e) { DataClient serviceClient = serviceClient = (DataClient)Application.Current.Properties["ServiceClient"]; string code = AuthCode.Text; @@ -214,17 +220,14 @@ namespace ZitiDesktopEdge { } } - async private void DoAuthenticate(object sender, MouseButtonEventArgs e) { + async private void DoAuthenticate() { if (!this._executing) { + this._executing = true; string code = AuthCode.Text; - if (AuthCode.MaxLength == 8) { - if (code.Length != 8) this.ShowError("You must enter a valid recovery code"); - } else { - if (code.Length != 6) this.ShowError("You must enter a valid code"); - } DataClient serviceClient = (DataClient)Application.Current.Properties["ServiceClient"]; + this.OnLoad?.Invoke(false, "Authentication", "One Moment Please..."); if (this.Type == 1) { SvcResponse authResult = await serviceClient.AuthMFA(this._identity.Fingerprint, code); if (authResult?.Code != 0) { @@ -238,6 +241,7 @@ namespace ZitiDesktopEdge { this.OnClose?.Invoke(true); this._executing = false; } + this.OnLoad?.Invoke(true, "", ""); } else if (this.Type == 2) { MfaRecoveryCodesResponse codeResponse = await serviceClient.ReturnMFACodes(this._identity.Fingerprint, code); if (codeResponse?.Code != 0) { @@ -250,6 +254,7 @@ namespace ZitiDesktopEdge { this.OnClose?.Invoke(true); this._executing = false; } + this.OnLoad?.Invoke(true, "", ""); } else if (this.Type == 3) { SvcResponse authResult = await serviceClient.RemoveMFA(this._identity.Fingerprint, code); if (authResult?.Code != 0) { @@ -261,6 +266,7 @@ namespace ZitiDesktopEdge { this.OnClose?.Invoke(true); this._executing = false; } + this.OnLoad?.Invoke(true, "", ""); } else if (this.Type == 4) { MfaRecoveryCodesResponse codeResponse = await serviceClient.GenerateMFACodes(this._identity.Fingerprint, code); if (codeResponse?.Code != 0) { @@ -273,6 +279,7 @@ namespace ZitiDesktopEdge { this.OnClose?.Invoke(true); this._executing = false; } + this.OnLoad?.Invoke(true, "", ""); } } } @@ -301,7 +308,7 @@ namespace ZitiDesktopEdge { private void AuthCode_KeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.Return) { - DoAuthenticate(sender, null); + DoAuthenticate(); } } } diff --git a/DesktopEdge/ZitiDesktopEdge.csproj b/DesktopEdge/ZitiDesktopEdge.csproj index fd06e0a6..b406e57b 100644 --- a/DesktopEdge/ZitiDesktopEdge.csproj +++ b/DesktopEdge/ZitiDesktopEdge.csproj @@ -91,6 +91,7 @@ ..\packages\NLog.4.7.8\lib\net45\NLog.dll + ..\packages\QRCoder.1.4.1\lib\net40\QRCoder.dll From 6f157ad20b0205d884c98dad1995b046fe68bda2 Mon Sep 17 00:00:00 2001 From: Jeremy Tellier - ROG Date: Thu, 8 Apr 2021 13:00:01 +0100 Subject: [PATCH 02/19] Release Notes and Number size fix --- DesktopEdge/Views/ItemRenderers/IdentityItem.xaml | 2 +- release-notes.md | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml b/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml index e0d7ff4e..a3d74706 100644 --- a/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml +++ b/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml @@ -40,7 +40,7 @@ - + diff --git a/release-notes.md b/release-notes.md index 065de977..68996869 100644 --- a/release-notes.md +++ b/release-notes.md @@ -1,3 +1,13 @@ +# Release 1.9.3 + +## What's New +* Page Service List +* Sort Service on Identity Details Page +* Consistent UX for MFA Screens + +## Bugs fixed: +* [#343](https://github.com/openziti/desktop-edge-win/issues/343) MFA Code Regeneration, UI Clickable Areas, Service Crash Handling + # Release 1.9.1 ## What's New From 338cd43b9c92e8558bbf7fba723b553daf463a41 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 8 Apr 2021 14:29:43 -0400 Subject: [PATCH 03/19] initial implementation of bulk service update event --- service/cziti/sdk.go | 125 +++++++++++++---------------- service/ziti-tunnel/dto/dtos.go | 7 ++ service/ziti-tunnel/dto/events.go | 5 ++ service/ziti-tunnel/service/ipc.go | 42 +++++++++- 4 files changed, 111 insertions(+), 68 deletions(-) diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 28b01c73..2bb47273 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -53,7 +53,6 @@ port_range_t* stailq_next_port_range(port_range_t* cur); import "C" import ( "errors" - "github.com/openziti/desktop-edge-win/service/windns" "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" @@ -72,6 +71,7 @@ var log = logging.Logger() var noFileLog = logging.NoFilenameLogger() var Version dto.ServiceVersion var ServiceChanges = make(chan dto.ServiceEvent, 256) +var BulkServiceChanges = make(chan BulkServiceChange, 32) type sdk struct { libuvCtx *C.libuv_ctx @@ -81,6 +81,13 @@ type ServiceChange struct { Service *ZService ZitiContext *ZIdentity } +type BulkServiceChange struct { + Fingerprint string + HostnamesToAdd map[string]bool + HostnamesToRemove map[string]bool + ServicesToRemove []*dto.Service + ServicesToAdd []*dto.Service +} var _impl sdk @@ -253,10 +260,10 @@ func doZitiShutdown(async *C.uv_async_t) { C.ziti_shutdown(ctx) } -func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, zid *ZIdentity) []dto.Address { +func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, zid *ZIdentity) *dto.Service { if zid == nil { log.Errorf("in serviceCB with nil zid??? ") - return make([]dto.Address, 0) + return nil } name := C.GoString(service.name) @@ -269,8 +276,24 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z portRanges := getTunneledServicePortRanges(ts) log.Infof("service update: %s, id: %s, portocols:%s, addresses:%v, portRanges: %v", name, svcId, protocols, addresses, portRanges) + var svc *dto.Service + if status == C.ZITI_SERVICE_UNAVAILABLE { - serviceUnavailable(zid, svcId, name) + log.Debugf("serivce has become unavailalbe: %s [%s]", name, svcId) + f, ok := zid.Services.Load(svcId) + if ok { + svc = &dto.Service{ + Name: name, + Id: svcId, + } + found := f.(*ZService) + if found != nil { + found.Service = nil + } + zid.Services.Delete(svcId) + } else { + log.Warnf("could not remove service? service not found with id: %s, name: %s in context %d", svcId, name, &zid) + } } else if status == C.ZITI_OK { pcIds := make(map[string]bool) var postureChecks []dto.PostureCheck @@ -315,7 +338,7 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z } } - svc := &dto.Service{ + svc = &dto.Service{ Name: name, Id: svcId, Protocols: protocols, @@ -325,46 +348,9 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z PostureChecks: postureChecks, IsAccessable: hasAccess, } - - added := ZService{ - Name: name, - Id: svcId, - Service: svc, - Czctx: ziti_ctx, - } - - se := dto.ServiceEvent{ - ActionEvent: dto.SERVICE_ADDED, - Fingerprint: zid.Fingerprint, - Service: svc, - } - - zid.Services.Store(svcId, &added) - go func() {ServiceChanges <- se}() //do this in a go routine just in case it gets blocked so the uv loop doesn't block } - return addresses -} -func serviceUnavailable(ctx *ZIdentity, svcId string, name string) { - log.Debugf("serivce has become unavailalbe: %s [%s]", name, svcId) - f, ok := ctx.Services.Load(svcId) - if ok { - found := f.(*ZService) - found.Service = nil - ctx.Services.Delete(svcId) - se := dto.ServiceEvent{ - ActionEvent: dto.SERVICE_REMOVED, - Fingerprint: ctx.Fingerprint, - Service: &dto.Service{ - Name: name, - Id: svcId, - }, - } - ServiceChanges <- se - log.Debugf("dispatched serivce has become unavailalbe to ui: %s [%s]", name, svcId) - } else { - log.Warnf("could not remove service? service not found with id: %s, name: %s in context %d", svcId, name, &ctx) - } + return svc } //export eventCB @@ -402,6 +388,9 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { case C.ZitiServiceEvent: hostnamesToAdd := make(map[string]bool) hostnamesToRemove := make(map[string]bool) + servicesToRemove := make([]*dto.Service, 0) + servicesToAdd := make([]*dto.Service, 0) + srvEvent := C.ziti_event_service_event(event) for i := 0; true; i++ { @@ -409,12 +398,14 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { if unsafe.Pointer(removed) == C.NULL { break } - addys := serviceCB(ztx, removed, C.ZITI_SERVICE_UNAVAILABLE, zid) - for _, toRemove := range addys { + svcToRemove := serviceCB(ztx, removed, C.ZITI_SERVICE_UNAVAILABLE, zid) + remAddys := svcToRemove.Addresses + for _, toRemove := range remAddys { if toRemove.IsHost { hostnamesToRemove[toRemove.HostName] = true } } + servicesToRemove = append(servicesToRemove, svcToRemove) } for i := 0; true; i++ { changed := C.ziti_service_array_get(srvEvent.changed, C.int(i)) @@ -422,52 +413,52 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { break } log.Info("service changed remove the service then add it back immediately", C.GoString(changed.name)) - addys := serviceCB(ztx, changed, C.ZITI_SERVICE_UNAVAILABLE, zid) - for _, toRemove := range addys { + svcToRemove := serviceCB(ztx, changed, C.ZITI_SERVICE_UNAVAILABLE, zid) + remAddys := svcToRemove.Addresses + for _, toRemove := range remAddys { if toRemove.IsHost { hostnamesToRemove[toRemove.HostName] = true } } + servicesToRemove = append(servicesToRemove, svcToRemove) - addys = serviceCB(ztx, changed, C.ZITI_OK, zid) - for _, toAdd := range addys { + svcToAdd := serviceCB(ztx, changed, C.ZITI_OK, zid) + addAddys := svcToAdd.Addresses + for _, toAdd := range addAddys { if toAdd.IsHost { hostnamesToAdd[toAdd.HostName] = true } } + servicesToAdd = append(servicesToAdd, svcToAdd) } for i := 0; true; i++ { added := C.ziti_service_array_get(srvEvent.added, C.int(i)) if unsafe.Pointer(added) == C.NULL { break } - addys := serviceCB(ztx, added, C.ZITI_OK, zid) - for _, toAdd := range addys { + svcToAdd := serviceCB(ztx, added, C.ZITI_OK, zid) + addAddys := svcToAdd.Addresses + for _, toAdd := range addAddys { if toAdd.IsHost { hostnamesToAdd[toAdd.HostName] = true } } + servicesToAdd = append(servicesToAdd, svcToAdd) } - if len(hostnamesToAdd) > 0 { - windns.AddNrptRules(hostnamesToAdd, dnsip.String()) - log.Infof("mapped the following hostnames: %v", hostnamesToAdd) + svcChange := BulkServiceChange{ + Fingerprint: zid.Fingerprint, + HostnamesToAdd: hostnamesToAdd, + HostnamesToRemove: hostnamesToRemove, + ServicesToRemove: servicesToRemove, + ServicesToAdd: servicesToAdd, } - if len(hostnamesToRemove) > 0 { - windns.RemoveNrptRules(hostnamesToRemove) - log.Infof("unmapped the following hostnames: %v", hostnamesToRemove) + if len(BulkServiceChanges) == cap(BulkServiceChanges) { + log.Warn("Service changes are not being processed fast enough. This client is out of date from the controller! This is unexpected. If you see this warning please report") + } else { + BulkServiceChanges <- svcChange } - - var m = dto.IdentityEvent{ - ActionEvent: dto.IdentityUpdateComplete, - Id: dto.Identity{ - FingerPrint: zid.Fingerprint, - }, - } - - goapi.BroadcastEvent(m) - default: log.Infof("event %d not handled", event._type) } diff --git a/service/ziti-tunnel/dto/dtos.go b/service/ziti-tunnel/dto/dtos.go index d63105f6..c814763b 100644 --- a/service/ziti-tunnel/dto/dtos.go +++ b/service/ziti-tunnel/dto/dtos.go @@ -158,6 +158,13 @@ type ServiceEvent struct { Service *Service } +type BulkServiceEvent struct { + ActionEvent + Fingerprint string + AddedServices []*Service + RemovedServices []*Service +} + type IdentityEvent struct { ActionEvent Id Identity diff --git a/service/ziti-tunnel/dto/events.go b/service/ziti-tunnel/dto/events.go index c216ced3..96a9c7a9 100644 --- a/service/ziti-tunnel/dto/events.go +++ b/service/ziti-tunnel/dto/events.go @@ -18,6 +18,7 @@ package dto const ( ADDED = "added" + BULK = "bulk" REMOVED = "removed" ERROR = "error" UPDATED = "updated" @@ -45,6 +46,10 @@ var SERVICE_REMOVED = ActionEvent{ StatusEvent: StatusEvent{Op: SERVICE_OP}, Action: REMOVED, } +var SERVICE_BULK = ActionEvent{ + StatusEvent: StatusEvent{Op: SERVICE_OP}, + Action: BULK, +} var IDENTITY_ADDED = ActionEvent{ StatusEvent: StatusEvent{Op: IDENTITY_OP}, diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 04aca3fd..573ed250 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -1005,13 +1005,53 @@ func acceptServices() { return case serviceChange := <-cziti.ServiceChanges: log.Debugf("processing service change event. id:%s name:%s", serviceChange.Service.Id, serviceChange.Service.Name) - change := dto.ServiceEvent(serviceChange) + change := serviceChange events.broadcast <- change log.Debugf("dispatched %s service change event", serviceChange.Op) + case bulkServiceChange := <-cziti.BulkServiceChanges: + log.Debugf("processing a bulk service change event. Hostnames to add/remove:[%d/%d] service notifications added/removed: [%d/%d]", + len(bulkServiceChange.HostnamesToAdd), + len(bulkServiceChange.HostnamesToRemove), + len(bulkServiceChange.ServicesToAdd), + len(bulkServiceChange.ServicesToRemove)) + handleBulkServiceChange(bulkServiceChange) } } } +func handleBulkServiceChange(sc cziti.BulkServiceChange) { + if len(sc.HostnamesToRemove) > 0 { + log.Debug("removing rules from NRPT") + windns.RemoveNrptRules(sc.HostnamesToRemove) + log.Infof("removed NRPT rules for: %v", sc.HostnamesToRemove) + } else { + log.Debug("bulk service change had no hostnames to remove") + } + + if len(sc.HostnamesToAdd) > 0 { + log.Debug("adding rules to NRPT") + windns.AddNrptRules(sc.HostnamesToAdd, rts.state.TunIpv4) + log.Infof("mapped the following hostnames: %v", sc.HostnamesToAdd) + } + + be := dto.BulkServiceEvent{ + ActionEvent: dto.SERVICE_BULK, + Fingerprint: sc.Fingerprint, + AddedServices: sc.ServicesToAdd, + RemovedServices: sc.ServicesToRemove, + } + + rts.BroadcastEvent(be) + + var m = dto.IdentityEvent{ + ActionEvent: dto.IdentityUpdateComplete, + Id: dto.Identity{ + FingerPrint: sc.Fingerprint, + }, + } + rts.BroadcastEvent(m) +} + func handleEvents(isInitialized chan struct{}) { events.run() d := 5 * time.Second From 8376ff529e7790426aba88bd505c7e14f74d2083 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 8 Apr 2021 15:28:47 -0400 Subject: [PATCH 04/19] checkpoint commit before rebasing from release-next --- DesktopEdge/MainWindow.xaml.cs | 86 ++++++++++++------- .../DataStructures/DataStructures.cs | 9 +- .../ServiceClient/DataClient.cs | 16 +++- service/cziti/sdk.go | 57 +++++++----- service/ziti-tunnel/dto/events.go | 13 +-- service/ziti-tunnel/service/ipc.go | 4 +- 6 files changed, 123 insertions(+), 62 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index 6fa98883..fc8d3cfb 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -490,6 +490,7 @@ namespace ZitiDesktopEdge { serviceClient.OnTunnelStatusEvent += ServiceClient_OnTunnelStatusEvent; serviceClient.OnMfaEvent += ServiceClient_OnMfaEvent; serviceClient.OnLogLevelEvent += ServiceClient_OnLogLevelEvent; + serviceClient.OnBulkServiceEvent += ServiceClient_OnBulkServiceEvent; Application.Current.Properties.Add("ServiceClient", serviceClient); monitorClient = new MonitorClient(); @@ -523,6 +524,28 @@ namespace ZitiDesktopEdge { Placement(); } + private void ServiceClient_OnBulkServiceEvent(object sender, BulkServiceEvent e) { + var found = identities.Find(id => id.Fingerprint == e.Fingerprint); + if (found == null) { + logger.Warn($"{e.Action} service event for {e.Fingerprint} but the provided identity fingerprint was not found!"); + return; + } else { + foreach (var removed in e.RemovedServices) { + removeService(found, removed); + } + foreach (var removed in e.AddedServices) { + addService(found, removed); + } + LoadIdentities(false); + 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) { @@ -775,36 +798,20 @@ namespace ZitiDesktopEdge { private void ServiceClient_OnServiceEvent(object sender, ServiceEvent e) { if (e == null) return; - Debug.WriteLine($"==== ServiceEvent : action:{e.Action} fingerprint:{e.Fingerprint} name:{e.Service.Name} "); + logger.Debug($"==== ServiceEvent : action:{e.Action} fingerprint:{e.Fingerprint} name:{e.Service.Name} "); + var found = identities.Find(id => id.Fingerprint == e.Fingerprint); + if (found == null) { + logger.Debug($"{e.Action} service event for {e.Service.Name} but the provided identity fingerprint {e.Fingerprint} is not found!"); + return; + } + + if (e.Action == "added") { + addService(found, e.Service); + } else { + removeService(found, e.Service); + } + LoadIdentities(false); this.Dispatcher.Invoke(() => { - var found = identities.Find(id => id.Fingerprint == e.Fingerprint); - - Debug.WriteLine(e.Action+" Calling Service Appender"); - - if (found == null) { - Debug.WriteLine($"{e.Action} service event for {e.Service.Name} but the provided identity fingerprint {e.Fingerprint} is not found!"); - return; - } - - if (e.Action == "added") { - ZitiService zs = new ZitiService(e.Service); - var svc = found.Services.Find(s => s.Name == zs.Name); - if (svc == null) { - found.Services.Add(zs); - if (zs.HasFailingPostureCheck()) { - found.HasServiceFailingPostureCheck = true; - if (zs.PostureChecks.Any(p => !p.IsPassing && p.QueryType == "MFA")) { - found.MFAInfo.IsAuthenticated = false; - } - } - } else { - logger.Debug("the service named " + zs.Name + " is already accounted for on this identity."); - } - } else { - logger.Debug("removing the service named: " + e.Service.Name); - found.Services.RemoveAll(s => s.Name == e.Service.Name); - } - LoadIdentities(false); IdentityDetails deets = ((MainWindow)Application.Current.MainWindow).IdentityMenu; if (deets.IsVisible) { deets.UpdateView(); @@ -812,6 +819,27 @@ namespace ZitiDesktopEdge { }); } + private void addService(ZitiIdentity found, Service added) { + ZitiService zs = new ZitiService(added); + var svc = found.Services.Find(s => s.Name == zs.Name); + if (svc == null) { + found.Services.Add(zs); + if (zs.HasFailingPostureCheck()) { + found.HasServiceFailingPostureCheck = true; + if (zs.PostureChecks.Any(p => !p.IsPassing && p.QueryType == "MFA")) { + found.MFAInfo.IsAuthenticated = false; + } + } + } else { + logger.Debug("the service named " + zs.Name + " is already accounted for on this identity."); + } + } + + private void removeService(ZitiIdentity found, Service removed) { + logger.Debug("removing the service named: {0}", removed.Name); + found.Services.RemoveAll(s => s.Name == removed.Name); + } + private void ServiceClient_OnTunnelStatusEvent(object sender, TunnelStatusEvent e) { if (e == null) return; //just skip it for now... logger.Debug($"==== TunnelStatusEvent: "); diff --git a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs index 2d9ade78..e26ad46b 100644 --- a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs +++ b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs @@ -408,12 +408,17 @@ namespace ZitiDesktopEdge.DataStructures { public List Identities { get; set; } } - public class ServiceEvent : ActionEvent - { + public class ServiceEvent : ActionEvent { public string Fingerprint { get; set; } public Service Service { get; set; } } + public class BulkServiceEvent : ActionEvent { + public string Fingerprint { get; set; } + public List AddedServices { get; set; } + public List RemovedServices { get; set; } + } + public class IdentityEvent : ActionEvent { public Identity Id { get; set; } diff --git a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs index 8e628be6..5d8dad4a 100644 --- a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs +++ b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs @@ -35,6 +35,7 @@ namespace ZitiDesktopEdge.ServiceClient { public event EventHandler OnServiceEvent; public event EventHandler OnLogLevelEvent; public event EventHandler OnMfaEvent; + public event EventHandler OnBulkServiceEvent; protected override void ShutdownEvent(StatusEvent e) { Logger.Debug("Clean shutdown detected from ziti"); @@ -57,12 +58,15 @@ namespace ZitiDesktopEdge.ServiceClient { protected virtual void ServiceEvent(ServiceEvent e) { OnServiceEvent?.Invoke(this, e); } - + + protected virtual void BulkServiceEvent(BulkServiceEvent e) { + OnBulkServiceEvent?.Invoke(this, e); + } + protected virtual void LogLevelEvent(LogLevelEvent e) { OnLogLevelEvent?.Invoke(this, e); } - protected virtual void MfaEvent(MfaEvent e) { OnMfaEvent?.Invoke(this, e); } @@ -351,6 +355,14 @@ namespace ZitiDesktopEdge.ServiceClient { ServiceEvent(svc); } break; + case "bulkservice": + //dbg comment Logger.Warn("SERVICE EVENT: \n" + respAsString); + BulkServiceEvent bsvc = serializer.Deserialize(jsonReader); + + if (bsvc != null) { + BulkServiceEvent(bsvc); + } + break; case "logLevel": LogLevelEvent ll = serializer.Deserialize(jsonReader); diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 2bb47273..6983274d 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -70,7 +70,7 @@ const ( var log = logging.Logger() var noFileLog = logging.NoFilenameLogger() var Version dto.ServiceVersion -var ServiceChanges = make(chan dto.ServiceEvent, 256) +var aServiceChanges = make(chan dto.ServiceEvent, 256) var BulkServiceChanges = make(chan BulkServiceChange, 32) type sdk struct { @@ -348,6 +348,13 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z PostureChecks: postureChecks, IsAccessable: hasAccess, } + added := ZService{ + Name: name, + Id: svcId, + Service: svc, + Czctx: ziti_ctx, + } + zid.Services.Store(svcId, &added) } return svc @@ -399,13 +406,15 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { break } svcToRemove := serviceCB(ztx, removed, C.ZITI_SERVICE_UNAVAILABLE, zid) - remAddys := svcToRemove.Addresses - for _, toRemove := range remAddys { - if toRemove.IsHost { - hostnamesToRemove[toRemove.HostName] = true + if svcToRemove != nil { + remAddys := svcToRemove.Addresses + for _, toRemove := range remAddys { + if toRemove.IsHost { + hostnamesToRemove[toRemove.HostName] = true + } } + servicesToRemove = append(servicesToRemove, svcToRemove) } - servicesToRemove = append(servicesToRemove, svcToRemove) } for i := 0; true; i++ { changed := C.ziti_service_array_get(srvEvent.changed, C.int(i)) @@ -414,22 +423,26 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { } log.Info("service changed remove the service then add it back immediately", C.GoString(changed.name)) svcToRemove := serviceCB(ztx, changed, C.ZITI_SERVICE_UNAVAILABLE, zid) - remAddys := svcToRemove.Addresses - for _, toRemove := range remAddys { - if toRemove.IsHost { - hostnamesToRemove[toRemove.HostName] = true + if svcToRemove != nil { + remAddys := svcToRemove.Addresses + for _, toRemove := range remAddys { + if toRemove.IsHost { + hostnamesToRemove[toRemove.HostName] = true + } } + servicesToRemove = append(servicesToRemove, svcToRemove) } - servicesToRemove = append(servicesToRemove, svcToRemove) svcToAdd := serviceCB(ztx, changed, C.ZITI_OK, zid) - addAddys := svcToAdd.Addresses - for _, toAdd := range addAddys { - if toAdd.IsHost { - hostnamesToAdd[toAdd.HostName] = true + if svcToAdd != nil { + addAddys := svcToAdd.Addresses + for _, toAdd := range addAddys { + if toAdd.IsHost { + hostnamesToAdd[toAdd.HostName] = true + } } + servicesToAdd = append(servicesToAdd, svcToAdd) } - servicesToAdd = append(servicesToAdd, svcToAdd) } for i := 0; true; i++ { added := C.ziti_service_array_get(srvEvent.added, C.int(i)) @@ -437,13 +450,15 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { break } svcToAdd := serviceCB(ztx, added, C.ZITI_OK, zid) - addAddys := svcToAdd.Addresses - for _, toAdd := range addAddys { - if toAdd.IsHost { - hostnamesToAdd[toAdd.HostName] = true + if svcToAdd != nil { + addAddys := svcToAdd.Addresses + for _, toAdd := range addAddys { + if toAdd.IsHost { + hostnamesToAdd[toAdd.HostName] = true + } } + servicesToAdd = append(servicesToAdd, svcToAdd) } - servicesToAdd = append(servicesToAdd, svcToAdd) } svcChange := BulkServiceChange{ diff --git a/service/ziti-tunnel/dto/events.go b/service/ziti-tunnel/dto/events.go index 96a9c7a9..e2e43379 100644 --- a/service/ziti-tunnel/dto/events.go +++ b/service/ziti-tunnel/dto/events.go @@ -25,11 +25,12 @@ const ( CHANGED = "changed" NORMAL = "Normal" - SERVICE_OP = "service" - IDENTITY_OP = "identity" - LOGLEVEL_OP = "logLevel" - FEEDBACK_OP = "CaptureLogs" - MFA_OP = "mfa" + SERVICE_OP = "service" + BULK_SERVICE_OP = "bulkservice" + IDENTITY_OP = "identity" + LOGLEVEL_OP = "logLevel" + FEEDBACK_OP = "CaptureLogs" + MFA_OP = "mfa" MFAEnrollmentChallengAtion = "enrollment_challenge" MFAEnrollmentVerificationAction = "enrollment_verification" @@ -47,7 +48,7 @@ var SERVICE_REMOVED = ActionEvent{ Action: REMOVED, } var SERVICE_BULK = ActionEvent{ - StatusEvent: StatusEvent{Op: SERVICE_OP}, + StatusEvent: StatusEvent{Op: BULK_SERVICE_OP}, Action: BULK, } diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 573ed250..a79eadad 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -1003,11 +1003,11 @@ func acceptServices() { select { case <-shutdown: return - case serviceChange := <-cziti.ServiceChanges: +/*xxxxx case serviceChange := <-cziti.ServiceChanges: log.Debugf("processing service change event. id:%s name:%s", serviceChange.Service.Id, serviceChange.Service.Name) change := serviceChange events.broadcast <- change - log.Debugf("dispatched %s service change event", serviceChange.Op) + log.Debugf("dispatched %s service change event", serviceChange.Op)*/ case bulkServiceChange := <-cziti.BulkServiceChanges: log.Debugf("processing a bulk service change event. Hostnames to add/remove:[%d/%d] service notifications added/removed: [%d/%d]", len(bulkServiceChange.HostnamesToAdd), From 0b50b5e6e6a3854be1120f2b8e25dcbe43d41ebf Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 8 Apr 2021 16:30:24 -0400 Subject: [PATCH 05/19] small changes after code review --- DesktopEdge/MainWindow.xaml.cs | 4 ++-- .../ServiceClient/DataClient.cs | 2 +- service/cziti/sdk.go | 1 - service/ziti-tunnel/dto/dtos.go | 6 ------ service/ziti-tunnel/service/debug.go | 16 ---------------- service/ziti-tunnel/service/ipc.go | 5 ----- 6 files changed, 3 insertions(+), 31 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index fc8d3cfb..43a79f9d 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -489,8 +489,8 @@ namespace ZitiDesktopEdge { serviceClient.OnServiceEvent += ServiceClient_OnServiceEvent; serviceClient.OnTunnelStatusEvent += ServiceClient_OnTunnelStatusEvent; serviceClient.OnMfaEvent += ServiceClient_OnMfaEvent; - serviceClient.OnLogLevelEvent += ServiceClient_OnLogLevelEvent; - serviceClient.OnBulkServiceEvent += ServiceClient_OnBulkServiceEvent; + serviceClient.OnLogLevelEvent += ServiceClient_OnLogLevelEvent; + serviceClient.OnBulkServiceEvent += ServiceClient_OnBulkServiceEvent; Application.Current.Properties.Add("ServiceClient", serviceClient); monitorClient = new MonitorClient(); diff --git a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs index 5d8dad4a..852b6590 100644 --- a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs +++ b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs @@ -356,7 +356,7 @@ namespace ZitiDesktopEdge.ServiceClient { } break; case "bulkservice": - //dbg comment Logger.Warn("SERVICE EVENT: \n" + respAsString); + //dbg comment Logger.Warn("BULKSERVICE EVENT: \n" + respAsString); BulkServiceEvent bsvc = serializer.Deserialize(jsonReader); if (bsvc != null) { diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 6983274d..387e2ec4 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -70,7 +70,6 @@ const ( var log = logging.Logger() var noFileLog = logging.NoFilenameLogger() var Version dto.ServiceVersion -var aServiceChanges = make(chan dto.ServiceEvent, 256) var BulkServiceChanges = make(chan BulkServiceChange, 32) type sdk struct { diff --git a/service/ziti-tunnel/dto/dtos.go b/service/ziti-tunnel/dto/dtos.go index c814763b..bad800ee 100644 --- a/service/ziti-tunnel/dto/dtos.go +++ b/service/ziti-tunnel/dto/dtos.go @@ -152,12 +152,6 @@ type MetricsEvent struct { Identities []*Identity } -type ServiceEvent struct { - ActionEvent - Fingerprint string - Service *Service -} - type BulkServiceEvent struct { ActionEvent Fingerprint string diff --git a/service/ziti-tunnel/service/debug.go b/service/ziti-tunnel/service/debug.go index 47f87435..9448a4c9 100644 --- a/service/ziti-tunnel/service/debug.go +++ b/service/ziti-tunnel/service/debug.go @@ -54,22 +54,6 @@ func dbg() { }, } - events.broadcast <- dto.ServiceEvent{ - ActionEvent: dto.SERVICE_ADDED, - Service: &dto.Service{ - Name: "New Service", - }, - Fingerprint: "new_id_fingerprint", - } - - events.broadcast <- dto.ServiceEvent{ - ActionEvent: dto.SERVICE_REMOVED, - Service: &dto.Service{ - Name: "New Service", - }, - Fingerprint: "new_id_fingerprint", - } - events.broadcast <- dto.IdentityEvent{ ActionEvent: dto.IDENTITY_REMOVED, Id: dto.Identity{ diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index a79eadad..4282591e 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -1003,11 +1003,6 @@ func acceptServices() { select { case <-shutdown: return -/*xxxxx case serviceChange := <-cziti.ServiceChanges: - log.Debugf("processing service change event. id:%s name:%s", serviceChange.Service.Id, serviceChange.Service.Name) - change := serviceChange - events.broadcast <- change - log.Debugf("dispatched %s service change event", serviceChange.Op)*/ case bulkServiceChange := <-cziti.BulkServiceChanges: log.Debugf("processing a bulk service change event. Hostnames to add/remove:[%d/%d] service notifications added/removed: [%d/%d]", len(bulkServiceChange.HostnamesToAdd), From e736306209c247280dedc6aa652cdda780130719 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 8 Apr 2021 16:44:13 -0400 Subject: [PATCH 06/19] update release-notes and bump to latest sdk/tsdk --- release-notes.md | 4 ++-- service/build.bat | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/release-notes.md b/release-notes.md index b2bc9f31..2529177b 100644 --- a/release-notes.md +++ b/release-notes.md @@ -6,13 +6,13 @@ * Consistent UX for MFA Screens ## Other changes: -* none +* Service to UI interaction is now with one bulk update of services instead of one event per service update ## Bugs fixed: * none ## Dependency Updates -* none +* Tunneler SDK to v0.16.0 (CSDK 0.22.1) # Release 1.9.2 diff --git a/service/build.bat b/service/build.bat index 006f4305..4ebe7d51 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.1 +SET ZITI_TUNNEL_REPO_BRANCH=v0.16.0 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 4f39c984f6674732b35fdf1275f7db2d0dde39b0 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 8 Apr 2021 17:12:30 -0400 Subject: [PATCH 07/19] rollback change to 0.16.0 of the sdk as it's not api compatible for now --- release-notes.md | 2 +- service/build.bat | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/release-notes.md b/release-notes.md index 2529177b..40ec5824 100644 --- a/release-notes.md +++ b/release-notes.md @@ -12,7 +12,7 @@ * none ## Dependency Updates -* Tunneler SDK to v0.16.0 (CSDK 0.22.1) +* none # Release 1.9.2 diff --git a/service/build.bat b/service/build.bat index 4ebe7d51..006f4305 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.16.0 +SET ZITI_TUNNEL_REPO_BRANCH=v0.15.1 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 ed6f7b7f2acb143e4c5ec1eb6bde3835cb68c511 Mon Sep 17 00:00:00 2001 From: ziti-ci Date: Thu, 8 Apr 2021 21:25:57 +0000 Subject: [PATCH 08/19] [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 | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/DesktopEdge/Properties/AssemblyInfo.cs b/DesktopEdge/Properties/AssemblyInfo.cs index 0ad08d87..ec3cefc3 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.2.0")] -[assembly: AssemblyVersion("1.9.2.0")] -[assembly: AssemblyFileVersion("1.9.2.0")] +// [assembly: AssemblyVersion("1.9.3.0")] +[assembly: AssemblyVersion("1.9.3.0")] +[assembly: AssemblyFileVersion("1.9.3.0")] diff --git a/Installer/ZitiDesktopEdge.aip b/Installer/ZitiDesktopEdge.aip index 31f61afb..fff0961b 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 8c145f2d..6c15d9ab 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.2.0")] -[assembly: AssemblyVersion("1.9.2.0")] -[assembly: AssemblyFileVersion("1.9.2.0")] +// [assembly: AssemblyVersion("1.9.3.0")] +[assembly: AssemblyVersion("1.9.3.0")] +[assembly: AssemblyFileVersion("1.9.3.0")] diff --git a/service/ziti-tunnel/version.go b/service/ziti-tunnel/version.go index f80071c9..a1243675 100644 --- a/service/ziti-tunnel/version.go +++ b/service/ziti-tunnel/version.go @@ -20,9 +20,9 @@ package main const ( - Version = "1.9.2" - Revision = "4e9875920983" - Branch = "main" + Version = "1.9.3" + Revision = "4f39c984f667" + Branch = "release-next" BuildUser = "" - BuildDate = "2021-04-08 11:05:00" + BuildDate = "2021-04-08 21:19:34" ) From f7ef35f64b8edd7d16f76d5d921d4539574fec8d Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Fri, 9 Apr 2021 21:13:01 -0400 Subject: [PATCH 09/19] initial commit of moving toi refcounting and using the config for addresses/ports/protocols --- .../DataStructures/DataStructures.cs | 6 +- service/cziti/sdk.c | 29 --- service/cziti/sdk.go | 215 +++++++++++++----- service/debug.bat | 2 +- service/windns/windns.go | 79 +++++-- 5 files changed, 216 insertions(+), 115 deletions(-) diff --git a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs index e26ad46b..d86c7f80 100644 --- a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs +++ b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs @@ -264,7 +264,11 @@ namespace ZitiDesktopEdge.DataStructures { public int Prefix { get; set; } public override string ToString() { - return Hostname; + if (IsHost) { + return Hostname; + } else { + return IP + "/" + Prefix; + } } } diff --git a/service/cziti/sdk.c b/service/cziti/sdk.c index eff88112..251cec2f 100644 --- a/service/cziti/sdk.c +++ b/service/cziti/sdk.c @@ -151,35 +151,6 @@ dns_manager* get_dns_mgr_from_c() { return &dns_mgr_c; } -/* functions allowing go to iterate tunneleed_service_t* */ -protocol_t* stailq_first_protocol(tunneled_service_t* ts) { - if(ts == NULL || ts->intercept == NULL ) { - return NULL; - } - return STAILQ_FIRST(&ts->intercept->protocols); -} -address_t* stailq_first_address(tunneled_service_t* ts) { - if(ts == NULL || ts->intercept == NULL ) { - return NULL; - } - return STAILQ_FIRST(&ts->intercept->addresses); -} -port_range_t* stailq_first_port_range(tunneled_service_t* ts) { - if(ts == NULL || ts->intercept == NULL ) { - return NULL; - } - return STAILQ_FIRST(&ts->intercept->port_ranges); -} -protocol_t* stailq_next_protocol(protocol_t* cur) { - return STAILQ_NEXT(cur, entries); -} -address_t* stailq_next_address(address_t* cur) { - return STAILQ_NEXT(cur, entries); -} -port_range_t* stailq_next_port_range(port_range_t* cur) { - return STAILQ_NEXT(cur, entries); -} - char* ziti_char_array_get(char** arr, int idx) { return arr ? arr[idx] : NULL; } diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 387e2ec4..a66047ed 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -41,37 +41,29 @@ void ziti_dump_to_file(void *ctx, char* outputPath); int ziti_dump_to_log(void *ctx, void* stringsBuilder); void* stailq_first_forgo(void* entries); -protocol_t* stailq_first_protocol(tunneled_service_t* ts); -address_t* stailq_first_address(tunneled_service_t* ts); -port_range_t* stailq_first_port_range(tunneled_service_t* ts); - -protocol_t* stailq_next_protocol(protocol_t* cur); -address_t* stailq_next_address(address_t* cur); -port_range_t* stailq_next_port_range(port_range_t* cur); - */ import "C" import ( + "encoding/json" "errors" "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" + "net" "os" "strings" "sync" "unsafe" ) -const ( - ADDED = "added" - REMOVED = "removed" -) - var log = logging.Logger() var noFileLog = logging.NoFilenameLogger() var Version dto.ServiceVersion var BulkServiceChanges = make(chan BulkServiceChange, 32) +var cCfgZitiTunnelerClientV1 = C.CString("ziti-tunneler-client.v1") +var cCfgInterceptV1 = C.CString("intercept.v1") + type sdk struct { libuvCtx *C.libuv_ctx } @@ -156,54 +148,54 @@ func NewZid(statusChange func(int)) *ZIdentity { return zid } -func (c *ZIdentity) GetMetrics() (int64, int64, bool) { - if c == nil { +func (zid *ZIdentity) GetMetrics() (int64, int64, bool) { + if zid == nil { return 0, 0, false } - if unsafe.Pointer(c.czctx) == C.NULL { - log.Debugf("ziti context is still null. the identity is probably not initialized yet: %s", c.Fingerprint) + if unsafe.Pointer(zid.czctx) == C.NULL { + log.Debugf("ziti context is still null. the identity is probably not initialized yet: %s", zid.Fingerprint) return 0, 0, false } var up, down C.double - C.ziti_get_transfer_rates(c.czctx, &up, &down) + C.ziti_get_transfer_rates(zid.czctx, &up, &down) return int64(up), int64(down), true } -func (c *ZIdentity) UnsafePointer() unsafe.Pointer { - return unsafe.Pointer(c.czctx) +func (zid *ZIdentity) UnsafePointer() unsafe.Pointer { + return unsafe.Pointer(zid.czctx) } -func (c *ZIdentity) AsKey() string { +func (zid *ZIdentity) AsKey() string { return "marker askey" } -func (c *ZIdentity) Status() (int, error) { - return c.status, c.statusErr +func (zid *ZIdentity) Status() (int, error) { + return zid.status, zid.statusErr } -func (c *ZIdentity) setVersionFromId() string { - if len(c.Version) > 0 { - return c.Version +func (zid *ZIdentity) setVersionFromId() string { + if len(zid.Version) > 0 { + return zid.Version } - c.Version = "" - if c != nil { - if c.czctx != nil { - v1 := C.ziti_get_controller_version(c.czctx) + zid.Version = "" + if zid != nil { + if zid.czctx != nil { + v1 := C.ziti_get_controller_version(zid.czctx) return C.GoString(v1.version) } } - return c.Version + return zid.Version } -func (c *ZIdentity) setNameFromId() string { - if len(c.Name) > 0 { - return c.Name +func (zid *ZIdentity) setNameFromId() string { + if len(zid.Name) > 0 { + return zid.Name } - c.Name = "" - if c != nil { - if c.czid != nil { - if c.czid.name != nil { - c.Name = C.GoString(c.czid.name) + zid.Name = "" + if zid != nil { + if zid.czid != nil { + if zid.czid.name != nil { + zid.Name = C.GoString(zid.czid.name) } else { log.Debug("in Name - c.zid.name was nil") } @@ -213,12 +205,12 @@ func (c *ZIdentity) setNameFromId() string { } else { log.Debug("in Name - c was nil") } - return c.Name + return zid.Name } -func (c *ZIdentity) Tags() []string { - if c.czctx != nil && c.czid != nil { - C.c_mapiter(&c.czid.tags) +func (zid *ZIdentity) Tags() []string { + if zid.czctx != nil && zid.czid != nil { + C.c_mapiter(&zid.czid.tags) /* it := C.model_map_iterator(&c.zid.tags) for { @@ -236,11 +228,11 @@ func (c *ZIdentity) Tags() []string { return nil } -func (c *ZIdentity) Controller() string { - if c.czctx != nil { - return C.GoString(C.ziti_get_controller(c.czctx)) +func (zid *ZIdentity) Controller() string { + if zid.czctx != nil { + return C.GoString(C.ziti_get_controller(zid.czctx)) } - return C.GoString(c.Options.controller) + return C.GoString(zid.Options.controller) } func (zid *ZIdentity) Shutdown() { @@ -259,6 +251,18 @@ func doZitiShutdown(async *C.uv_async_t) { C.ziti_shutdown(ctx) } +type clientV1Cfg struct { + //{"addresses":["eth0.ziti.ranged","eth0.second","eth0.third"],"portRanges":[{"high":80,"low":80},{"high":443,"low":443}],"protocols":["tcp"]} + Addresses []string `json:"addresses"` + PortRanges []dto.PortRange `json:"portRanges"` + Protocols []string `json:"protocols"` +} +type v1ClientCfg struct { + //{"hostname":"192.168.15.15","port":80} + Hostname string `json:"hostname"` + Port int `json:"port"` +} + func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, zid *ZIdentity) *dto.Service { if zid == nil { log.Errorf("in serviceCB with nil zid??? ") @@ -268,28 +272,65 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z name := C.GoString(service.name) svcId := C.GoString(service.id) log.Debugf("============ INSIDE serviceCB - status: %s:%s - %v, %v ============", name, svcId, status, service.perm_flags) - ts := C.ziti_sdk_c_on_service(ziti_ctx, service, status, unsafe.Pointer(theTun.tunCtx)) + C.ziti_sdk_c_on_service(ziti_ctx, service, status, unsafe.Pointer(theTun.tunCtx)) - protocols := getTunneledServiceProtocols(ts) - addresses := getTunneledServiceAddresses(ts) - portRanges := getTunneledServicePortRanges(ts) + var protocols []string + var portRanges []dto.PortRange + var addresses []dto.Address + + strClientV1cfg := C.GoString(C.ziti_service_get_raw_config(service, cCfgInterceptV1)) + if strClientV1cfg != "" { + log.Warnf("xxx: %s", strClientV1cfg) + var obj clientV1Cfg + uerr := json.Unmarshal([]byte(strClientV1cfg), &obj) + if uerr != nil { + log.Errorf("could not marshall json? %v", uerr) + } + protocols = obj.Protocols + portRanges = obj.PortRanges + a := make([]dto.Address, len(obj.Addresses)) + for idx, add := range obj.Addresses { + a[idx] = toAddy(add) + } + + addresses = append(a) + } else { + strZitiTunnelerClientV1 := C.GoString(C.ziti_service_get_raw_config(service, cCfgZitiTunnelerClientV1)) + log.Warnf("xxx: %s", strZitiTunnelerClientV1) + var obj v1ClientCfg + uerr := json.Unmarshal([]byte(strZitiTunnelerClientV1), &obj) + if uerr != nil { + log.Errorf("could not marshall json? %v", uerr) + } + protocols = []string{"UDP", "TCP"} + portRanges = []dto.PortRange{{Low: obj.Port, High: obj.Port}} + addresses = []dto.Address{toAddy(obj.Hostname)} + } + + /* + protocols := getTunneledServiceProtocols(ts) + addresses := getTunneledServiceAddresses(ts) + portRanges := getTunneledServicePortRanges(ts) + */ log.Infof("service update: %s, id: %s, portocols:%s, addresses:%v, portRanges: %v", name, svcId, protocols, addresses, portRanges) var svc *dto.Service if status == C.ZITI_SERVICE_UNAVAILABLE { - log.Debugf("serivce has become unavailalbe: %s [%s]", name, svcId) + log.Debugf("serivce has become unavailable: %s [%s]", name, svcId) f, ok := zid.Services.Load(svcId) if ok { svc = &dto.Service{ - Name: name, - Id: svcId, + Name: name, + Id: svcId, + Addresses: addresses, } found := f.(*ZService) if found != nil { found.Service = nil } zid.Services.Delete(svcId) + return svc } else { log.Warnf("could not remove service? service not found with id: %s, name: %s in context %d", svcId, name, &zid) } @@ -359,6 +400,37 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z return svc } +func toAddy(hostOrIpOrCidr string) dto.Address { + addy := dto.Address{ + IsHost: false, + HostName: "", + IP: "", + Prefix: 0, + } + + log.Debugf("parsing %s to address", hostOrIpOrCidr) + ip, ipnet, err := net.ParseCIDR(hostOrIpOrCidr) + if err != nil { + //must not be an CIDR... try IP parse + ip = net.ParseIP(hostOrIpOrCidr) + if ip == nil { + log.Debugf("%s does not appear to be an ip/cidr combination. considering it a hostname", hostOrIpOrCidr) + addy.HostName = hostOrIpOrCidr + addy.IsHost = true + } else { + log.Debugf("%s determined to be ip", hostOrIpOrCidr) + addy.IP = ip.String() + } + } else { + log.Debugf("%s appears to be a proper CIDR", hostOrIpOrCidr) + ones, _ := ipnet.Mask.Size() + addy.IP = ip.String() + addy.Prefix = ones + } + log.Warnf("ADDY: %v", addy) + return addy +} + //export eventCB func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { log.Tracef("events received. type: %d for ztx(%p)", event._type, ztx) @@ -404,11 +476,12 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { if unsafe.Pointer(removed) == C.NULL { break } + svcToRemove := serviceCB(ztx, removed, C.ZITI_SERVICE_UNAVAILABLE, zid) if svcToRemove != nil { remAddys := svcToRemove.Addresses for _, toRemove := range remAddys { - if toRemove.IsHost { + if toRemove.IsHost && hostnameRemoved(toRemove.HostName) == 0 { hostnamesToRemove[toRemove.HostName] = true } } @@ -420,12 +493,14 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { if unsafe.Pointer(changed) == C.NULL { break } + log.Info("service changed remove the service then add it back immediately", C.GoString(changed.name)) svcToRemove := serviceCB(ztx, changed, C.ZITI_SERVICE_UNAVAILABLE, zid) if svcToRemove != nil { + remAddys := svcToRemove.Addresses for _, toRemove := range remAddys { - if toRemove.IsHost { + if toRemove.IsHost && hostnameRemoved(toRemove.HostName) == 0 { hostnamesToRemove[toRemove.HostName] = true } } @@ -436,7 +511,7 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { if svcToAdd != nil { addAddys := svcToAdd.Addresses for _, toAdd := range addAddys { - if toAdd.IsHost { + if toAdd.IsHost && hostnameAdded(toAdd.HostName) == 1 { hostnamesToAdd[toAdd.HostName] = true } } @@ -452,7 +527,7 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { if svcToAdd != nil { addAddys := svcToAdd.Addresses for _, toAdd := range addAddys { - if toAdd.IsHost { + if toAdd.IsHost && hostnameAdded(toAdd.HostName) == 1 { hostnamesToAdd[toAdd.HostName] = true } } @@ -614,6 +689,7 @@ func ZitiDumpOnShutdown(zid *ZIdentity, sb *strings.Builder) { C.ziti_dump_to_log(unsafe.Pointer(zid.czctx), unsafe.Pointer(sb)) } +/* func getTunneledServiceProtocols(ts *C.tunneled_service_t) []string { var protocols []string next := C.stailq_first_protocol(ts) @@ -684,7 +760,28 @@ func getTunneledServiceAddresses(ts *C.tunneled_service_t) []dto.Address { } return values } - +*/ func InitTunnelerDns(ipBase uint32, mask int) { C.ziti_tunneler_init_dns(C.uint32_t(ipBase), C.int(mask)) } + +var addressCount = make(map[string]int) + +func hostnameAdded(host string) int { + count := 1 + if cur, ok := addressCount[host]; ok { + count = cur + 1 + } + addressCount[host] = count + log.Warnf("hostname added. count now: %d", count) + return count +} +func hostnameRemoved(host string) int { + count := 1 + if cur, ok := addressCount[host]; ok { + count = cur - 1 + } + addressCount[host] = count + log.Warnf("hostname removed. count now: %d", count) + return count +} diff --git a/service/debug.bat b/service/debug.bat index 0775e9bd..bb99fe88 100644 --- a/service/debug.bat +++ b/service/debug.bat @@ -1 +1 @@ -cls & "c:\Program Files\JetBrains\GoLand 2020.1.1\plugins\go\lib\dlv\windows\dlv.exe" --listen=localhost:50000 --headless=true --api-version=2 --check-go-version=false --only-same-user=false exec c:\git\github\openziti\desktop-edge-win\service\ziti-tunnel.exe debug +cls & "c:\Program Files\JetBrains\GoLand 2020.1.1\plugins\go\lib\dlv\windows\dlv.exe" --listen=localhost:50000 --headless=true --api-version=2 --check-go-version=false --only-same-user=false exec ziti-tunnel.exe debug diff --git a/service/windns/windns.go b/service/windns/windns.go index 54dd0cbf..c98082f6 100644 --- a/service/windns/windns.go +++ b/service/windns/windns.go @@ -28,6 +28,7 @@ import ( ) var log = logging.Logger() +var exeName = "ziti-tunnel" func GetConnectionSpecificDomains() []string { script := `Get-DnsClient | Select-Object ConnectionSpecificSuffix -Unique | ForEach-Object { $_.ConnectionSpecificSuffix }; (Get-DnsClientGlobalSetting).SuffixSearchList` @@ -103,7 +104,7 @@ func FlushDNS() { } func RemoveAllNrptRules() { - script := fmt.Sprintf(`Get-DnsClientNrptRule | Where { $_.Comment.StartsWith("Added by ziti-tunnel") } | Remove-DnsClientNrptRule -ErrorAction SilentlyContinue -Force`) + script := fmt.Sprintf(`Get-DnsClientNrptRule | Where { $_.Comment.StartsWith("Added by %s") } | Remove-DnsClientNrptRule -ErrorAction SilentlyContinue -Force`, exeName) log.Debugf("removing all nrpt rules with: %s", script) cmd := exec.Command("powershell", "-Command", script) @@ -116,24 +117,26 @@ func RemoveAllNrptRules() { } } +var namespaceTemplate = `%s@{n="%s";}` +var namespaceTemplatePadding = len(namespaceTemplate) func AddNrptRules(domainsToMap map[string]bool, dnsServer string) { if len(domainsToMap) == 0 { log.Debug("no domains to map specified to AddNrptRules. exiting early") return } - blockSize := 50 - if len(domainsToMap) > blockSize { - log.Debugf("domainsToMap is too long [%d] and may fail on some systems. splitting the requested entries into blocks of %d", len(domainsToMap), blockSize) - } + maxBucketSize := 500 currentSize := 0 - hostnames := make([]string, blockSize) + hostnames := make([]string, maxBucketSize) + ruleSize := 0 for hostname := range domainsToMap { - if currentSize >= blockSize { + ruleSize = ruleSize + len(hostname) + namespaceTemplatePadding + if ruleSize > 7500 || currentSize >= maxBucketSize { log.Debugf("sending chunk of domains to be added to NRPT") - chunkedAddNrptRules(hostnames, dnsServer) - hostnames = make([]string, blockSize) + chunkedAddNrptRules(hostnames[:currentSize], dnsServer) + hostnames = make([]string, maxBucketSize) currentSize = 0 + ruleSize = len(hostname) + namespaceTemplatePadding } hostnames[currentSize] = hostname currentSize++ @@ -146,21 +149,23 @@ func AddNrptRules(domainsToMap map[string]bool, dnsServer string) { func chunkedAddNrptRules(domainsToAdd []string, dnsServer string) { sb := strings.Builder{} - sb.WriteString(`$Rules = @( + sb.WriteString(`$Namespaces = @( `) for _, hostname := range domainsToAdd { - sb.WriteString(fmt.Sprintf(`@{ Namespace ="%s"; NameServers = @("%s"); Comment = "Added by ziti-tunnel"; DisplayName = "ziti-tunnel:%s"; }%s`, hostname, dnsServer, hostname, "\n")) + sb.WriteString(fmt.Sprintf(namespaceTemplate, "\n", hostname)) } sb.WriteString(fmt.Sprintf(`) -ForEach ($Rule in $Rules) { - Add-DnsClientNrptRule @Rule -}`)) +ForEach ($Namespace in $Namespaces) { + $ns=$Namespace["n"] + $Rule = @{Namespace="${ns}"; NameServers=@("%s"); Comment="Added by %s"; DisplayName="%s:${ns}"; } + Add-DnsClientNrptRule @Rule +}`, dnsServer, exeName, exeName)) script := sb.String() - log.Debugf("Executing NRPT script containing %d domains:\n%s", len(domainsToAdd), script) + log.Debugf("Executing ADD NRPT script containing %d domains. total script size: %d\n%s", len(domainsToAdd), len(script), script) cmd := exec.Command("powershell", "-Command", script) cmd.Stderr = os.Stdout @@ -172,27 +177,51 @@ ForEach ($Rule in $Rules) { } } -func RemoveNrptRules(domainsToMap map[string]bool) { - if len(domainsToMap) == 0 { +func RemoveNrptRules(domainsToRemove map[string]bool) { + if len(domainsToRemove) == 0 { log.Debug("no domains to map specified to RemoveNrptRules. exiting early") return } - sb := strings.Builder{} - sb.WriteString(`$toRemove = @( -`) + maxBucketSize := 500 + currentSize := 0 + hostnames := make([]string, maxBucketSize) + ruleSize := 0 + for hostname := range domainsToRemove { + ruleSize = ruleSize + len(hostname) + namespaceTemplatePadding + if ruleSize > 7500 || currentSize >= maxBucketSize { + log.Debugf("sending chunk of domains to be added to NRPT") + chunkedRemoveNrptRules(hostnames[:currentSize]) + hostnames = make([]string, maxBucketSize) + currentSize = 0 + ruleSize = len(hostname) + namespaceTemplatePadding + } + hostnames[currentSize] = hostname + currentSize++ + } + if currentSize > 0 { + //means there's a chunk still to add.... + chunkedRemoveNrptRules(hostnames[:currentSize]) + } +} - for hostname := range domainsToMap { - sb.WriteString(fmt.Sprintf(`"%s"%s`, hostname, "\n")) +func chunkedRemoveNrptRules(domainsToRemove []string) { + sb := strings.Builder{} + sb.WriteString(`$toRemove = @(`) + + for hostname := range domainsToRemove { + sb.WriteString(fmt.Sprintf(namespaceTemplate, "\n", hostname)) } sb.WriteString(fmt.Sprintf(`) - -Get-DnsClientNrptRule | Where { $toRemove -contains $_.DisplayName } | Remove-DnsClientNrptRule -ErrorAction SilentlyContinue -Force +ForEach ($ns in $toRemove) { + $nrpt = Get-DnsClientNrptRule | Where {$_.Namespace -contains "${ns}"} + foreach ($n in $nrpt){Remove-DnsClientNrptRule -Name $n.Name -PassThru -Force -ErrorAction SilentlyContinue} +} `)) script := sb.String() - log.Debugf("Executing NRPT script:\n%s", script) + log.Debugf("Executing REMOVE NRPT script containing %d domains. total script size: %d\n%s", len(domainsToRemove), len(script), script) cmd := exec.Command("powershell", "-Command", script) cmd.Stderr = os.Stdout From 4ef60a3428d764cdd9b88d5c1cea052e31d0e83d Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Sat, 10 Apr 2021 15:51:30 -0400 Subject: [PATCH 10/19] add warning if channel is going to block. add an attach.bat file to attach dlv when already running --- service/attach.bat | 7 +++++ service/cziti/sdk.go | 6 ++--- service/ziti-tunnel/service/debug.go | 12 ++++----- service/ziti-tunnel/service/ipc.go | 38 ++++++++++++++++------------ service/ziti-tunnel/service/state.go | 7 +++-- service/ziti-tunnel/service/topic.go | 13 ++++++---- 6 files changed, 51 insertions(+), 32 deletions(-) create mode 100644 service/attach.bat diff --git a/service/attach.bat b/service/attach.bat new file mode 100644 index 00000000..8d7607dc --- /dev/null +++ b/service/attach.bat @@ -0,0 +1,7 @@ +@echo off +powershell "Get-Process | where -Property Name -eq "ziti-tunnel" | select -ExpandProperty id" > zid +set /p zid= < zid +del zid +echo %zid% + +"c:\Program Files\JetBrains\GoLand 2020.1.1\plugins\go\lib\dlv\windows\dlv.exe" attach %zid% --headless --log --only-same-user=false --api-version=2 --accept-multiclient --listen=localhost:50000 diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index a66047ed..c9bf3185 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -280,7 +280,7 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z strClientV1cfg := C.GoString(C.ziti_service_get_raw_config(service, cCfgInterceptV1)) if strClientV1cfg != "" { - log.Warnf("xxx: %s", strClientV1cfg) + log.Tracef("intercept.v1: %s", strClientV1cfg) var obj clientV1Cfg uerr := json.Unmarshal([]byte(strClientV1cfg), &obj) if uerr != nil { @@ -296,7 +296,7 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z addresses = append(a) } else { strZitiTunnelerClientV1 := C.GoString(C.ziti_service_get_raw_config(service, cCfgZitiTunnelerClientV1)) - log.Warnf("xxx: %s", strZitiTunnelerClientV1) + log.Warnf("ziti-tunneler-client.v1: %s", strZitiTunnelerClientV1) var obj v1ClientCfg uerr := json.Unmarshal([]byte(strZitiTunnelerClientV1), &obj) if uerr != nil { @@ -427,7 +427,7 @@ func toAddy(hostOrIpOrCidr string) dto.Address { addy.IP = ip.String() addy.Prefix = ones } - log.Warnf("ADDY: %v", addy) + log.Tracef("parsed address: %v from %s", addy, hostOrIpOrCidr) return addy } diff --git a/service/ziti-tunnel/service/debug.go b/service/ziti-tunnel/service/debug.go index 9448a4c9..2050ff80 100644 --- a/service/ziti-tunnel/service/debug.go +++ b/service/ziti-tunnel/service/debug.go @@ -25,11 +25,11 @@ import ( func dbg() { r := rts.ToStatus(true) - events.broadcast <- dto.TunnelStatusEvent{ + rts.BroadcastEvent(dto.TunnelStatusEvent{ StatusEvent: dto.StatusEvent{Op: "status"}, Status: r, ApiVersion: API_VERSION, - } + }) svcs := make([]*dto.Service, 2) svcs[0] = &dto.Service{ @@ -39,7 +39,7 @@ func dbg() { Name: "Second Fake Service", } - events.broadcast <- dto.IdentityEvent{ + rts.BroadcastEvent(dto.IdentityEvent{ ActionEvent: dto.IDENTITY_ADDED, Id: dto.Identity{ Name: "NewIdentity", @@ -52,9 +52,9 @@ func dbg() { Services: svcs, Metrics: nil, }, - } + }) - events.broadcast <- dto.IdentityEvent{ + rts.BroadcastEvent(dto.IdentityEvent{ ActionEvent: dto.IDENTITY_REMOVED, Id: dto.Identity{ Name: "", @@ -65,5 +65,5 @@ func dbg() { Services: nil, Metrics: nil, }, - } + }) } diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 4282591e..fa188c64 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -129,9 +129,9 @@ func SubMain(ops chan string, changes chan<- svc.Status) error { requestShutdown("service shutdown") // signal to any connected consumers that the service is shutting down normally - events.broadcast <- dto.StatusEvent{ + rts.BroadcastEvent(dto.StatusEvent{ Op: "shutdown", - } + }) // wait 1 second for the shutdown to send to clients shutdownDelay := make(chan bool) @@ -681,8 +681,9 @@ func serveEvents(conn net.Conn) { log.Debugf("accepting a new client for serveEvents. total connection count: %d", eventsConnections) consumer := make(chan interface{}, 8) - events.register(randomInt, consumer) - defer events.unregister(randomInt) + id := fmt.Sprintf("serveEvents:%d", randomInt) + events.register(id, consumer) + defer events.unregister(id) w := bufio.NewWriter(conn) o := json.NewEncoder(w) @@ -704,12 +705,17 @@ loop: for { select { case msg := <-consumer: - err := o.Encode(msg) - if err != nil { - log.Debugf("exiting from serveEvents - %v", err) + log.Tracef("sending event to id: %s [%v]", id, msg) + eerr := o.Encode(msg) + if eerr != nil { + log.Warnf("exiting from serveEvents due to error: %v", eerr) break loop } - _ = w.Flush() + ferr := w.Flush() + if ferr != nil { + log.Warnf("flush error: %v", ferr) + } + log.Tracef("sent event to id: %s [%v]", id, msg) case <-interrupt: break loop } @@ -901,10 +907,10 @@ func connectIdentity(id *Id) { return true }) - events.broadcast <- dto.IdentityEvent{ + rts.BroadcastEvent(dto.IdentityEvent{ ActionEvent: dto.IDENTITY_ADDED, Id: id.Identity, - } + }) log.Infof("connecting identity completed: %s[%s] %t/%t", id.Name, id.FingerPrint, id.MfaEnabled, id.MfaNeeded) } } @@ -1062,10 +1068,10 @@ func handleEvents(isInitialized chan struct{}) { case <-every5s.C: s := rts.ToMetrics() - events.broadcast <- dto.MetricsEvent{ + rts.BroadcastEvent(dto.MetricsEvent{ StatusEvent: dto.StatusEvent{Op: "metrics"}, Identities: s.Identities, - } + }) } } } @@ -1133,10 +1139,10 @@ func authMfa(out *json.Encoder, fingerprint string, code string) { // when the log level is updated through command line, the message is broadcasted to UI and update service as well func sendLogLevelAndNotify(enc *json.Encoder, loglevel string) { - events.broadcast <- dto.LogLevelEvent{ + rts.BroadcastEvent(dto.LogLevelEvent{ ActionEvent: dto.LOGLEVEL_CHANGED, LogLevel: loglevel, - } + }) message := fmt.Sprintf("Loglevel %s is sent to the events channel", loglevel) log.Info(message) resp := dto.Response{Message: "success", Code: SUCCESS, Error: "", Payload: message} @@ -1147,10 +1153,10 @@ func sendLogLevelAndNotify(enc *json.Encoder, loglevel string) { func sendIdentityAndNotifyUI(enc *json.Encoder, fingerprint string) { for _, id := range rts.ids { if id.FingerPrint == fingerprint { - events.broadcast <- dto.IdentityEvent{ + rts.BroadcastEvent(dto.IdentityEvent{ ActionEvent: dto.IDENTITY_ADDED, Id: id.Identity, - } + }) message := fmt.Sprintf("Identity %s - %s updated message is sent to the events channel", id.Identity.Name, id.Identity.FingerPrint) log.Info(message) resp := dto.Response{Message: "success", Code: SUCCESS, Error: "", Payload: message} diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index 26933a70..45a5619f 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -262,10 +262,10 @@ func (t *RuntimeState) LoadIdentity(id *Id, refreshInterval int) { id.MfaEnabled = id.CId.MfaEnabled id.MfaNeeded = id.CId.MfaNeeded - events.broadcast <- dto.IdentityEvent{ + rts.BroadcastEvent(dto.IdentityEvent{ ActionEvent: dto.IDENTITY_ADDED, Id: id.Identity, - } + }) log.Infof("connecting identity completed: %s[%s] %t/%t", id.Name, id.FingerPrint, id.MfaEnabled, id.MfaNeeded) } @@ -477,6 +477,9 @@ func (t *RuntimeState) ReleaseIP() { } func (t *RuntimeState) BroadcastEvent(event interface{}) { + if len(events.broadcast) == cap(events.broadcast) { + log.Warn("event channel is full and is about to block!") + } events.broadcast <- event } diff --git a/service/ziti-tunnel/service/topic.go b/service/ziti-tunnel/service/topic.go index c6d95897..beb5dbd5 100644 --- a/service/ziti-tunnel/service/topic.go +++ b/service/ziti-tunnel/service/topic.go @@ -19,23 +19,23 @@ package service type topic struct { broadcast chan interface{} - channels map[int]chan interface{} + channels map[string]chan interface{} done chan bool } func newTopic(cap int16) topic { return topic{ broadcast: make(chan interface{}, cap), - channels: make(map[int]chan interface{}, cap), + channels: make(map[string]chan interface{}, cap), done: make(chan bool, cap), } } -func (t *topic) register(id int, c chan interface{}) { +func (t *topic) register(id string, c chan interface{}) { t.channels[id] = c } -func (t *topic) unregister(id int) { +func (t *topic) unregister(id string) { delete(t.channels, id) } @@ -48,7 +48,10 @@ func (t *topic) run() { for { select { case msg := <-t.broadcast: - for _, c := range t.channels { + for id, c := range t.channels { + if len(c) == cap(c) { + log.Warnf("channel with id [%s] is about to block!", id) + } c <- msg } break From 533ec9178d37cd6fbca8698f5131a07583d4ff9a Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Sun, 11 Apr 2021 11:44:34 -0400 Subject: [PATCH 11/19] add an option to specifiy a config value that applies DNS back to the TUN --- service/cziti/sdk.go | 3 +-- service/ziti-tunnel/cli/ipcClient.go | 2 +- service/ziti-tunnel/dto/dtos.go | 1 + service/ziti-tunnel/service/ipc.go | 7 ++++++- service/ziti-tunnel/service/state.go | 8 +++++++- 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index c9bf3185..d287f4b9 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -296,7 +296,7 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z addresses = append(a) } else { strZitiTunnelerClientV1 := C.GoString(C.ziti_service_get_raw_config(service, cCfgZitiTunnelerClientV1)) - log.Warnf("ziti-tunneler-client.v1: %s", strZitiTunnelerClientV1) + log.Tracef("ziti-tunneler-client.v1: %s", strZitiTunnelerClientV1) var obj v1ClientCfg uerr := json.Unmarshal([]byte(strZitiTunnelerClientV1), &obj) if uerr != nil { @@ -554,7 +554,6 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { } func zitiContextEvent(ztx C.ziti_context, status C.int, zid *ZIdentity) { - zid.status = int(status) zid.statusErr = zitiError(status) zid.czctx = ztx diff --git a/service/ziti-tunnel/cli/ipcClient.go b/service/ziti-tunnel/cli/ipcClient.go index c2316fe3..50a87b94 100644 --- a/service/ziti-tunnel/cli/ipcClient.go +++ b/service/ziti-tunnel/cli/ipcClient.go @@ -18,9 +18,9 @@ package cli */ import ( - "fmt" "bufio" "encoding/json" + "fmt" "io" "net" "strings" diff --git a/service/ziti-tunnel/dto/dtos.go b/service/ziti-tunnel/dto/dtos.go index bad800ee..c8930d43 100644 --- a/service/ziti-tunnel/dto/dtos.go +++ b/service/ziti-tunnel/dto/dtos.go @@ -119,6 +119,7 @@ type TunnelStatus struct { TunIpv4 string TunIpv4Mask int Status string + AddDns bool } type ServiceVersion struct { diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index fa188c64..e64d0940 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -282,7 +282,7 @@ func initialize(cLogLevel int) error { dnsIpAsUint32 := binary.BigEndian.Uint32(ipnet.IP) cziti.InitTunnelerDns(dnsIpAsUint32, len(ipnet.Mask)) - assignedIp, t, err := rts.CreateTun(rts.state.TunIpv4, rts.state.TunIpv4Mask) + assignedIp, t, err := rts.CreateTun(rts.state.TunIpv4, rts.state.TunIpv4Mask, rts.state.AddDns) if err != nil { return err } @@ -714,6 +714,7 @@ loop: ferr := w.Flush() if ferr != nil { log.Warnf("flush error: %v", ferr) + return } log.Tracef("sent event to id: %s [%v]", id, msg) case <-interrupt: @@ -723,6 +724,10 @@ loop: log.Info("a connected event client has disconnected") } +func writerFlush(writer bufio.Writer) { + writer.Flush() +} + func reportStatus(out *json.Encoder) { s := rts.ToStatus(true) respond(out, dto.ZitiTunnelStatus{ diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index 45a5619f..fd0f0c8e 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -21,6 +21,7 @@ import ( "bufio" "encoding/json" "fmt" + "golang.org/x/sys/windows" "io" "io/ioutil" "net" @@ -162,7 +163,7 @@ func (t *RuntimeState) ToMetrics() dto.TunnelStatus { return clean } -func (t *RuntimeState) CreateTun(ipv4 string, ipv4mask int) (net.IP, *tun.Device, error) { +func (t *RuntimeState) CreateTun(ipv4 string, ipv4mask int, applyDns bool) (net.IP, *tun.Device, error) { log.Infof("creating TUN device: %s", TunName) tunDevice, err := tun.CreateTUN(TunName, 64*1024-1) if err == nil { @@ -219,6 +220,11 @@ func (t *RuntimeState) CreateTun(ipv4 string, ipv4mask int) (net.IP, *tun.Device } log.Info("routing applied") + if applyDns { + //for windows 10+ this might be able to replace NRPT? + luid.SetDNS(windows.AF_INET, []net.IP{ip}, nil) + } + return ip, t.tun, nil } From 12147ba41e02c564d76d41093b0d351a45976cc1 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Sun, 11 Apr 2021 12:23:12 -0400 Subject: [PATCH 12/19] clean a bunch of async/await warnings --- DesktopEdge/MainWindow.xaml.cs | 18 +++++++++--------- DesktopEdge/Models/MessageCount.cs | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index 43a79f9d..a3c92b5e 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -68,8 +68,8 @@ namespace ZitiDesktopEdge { ExpectedLogPathServices = Path.Combine(ExpectedLogPathRoot, "service", $"ziti-tunneler.log"); } - private void IdentityMenu_OnMessage(string message) { - ShowBlurbAsync(message, ""); + async private void IdentityMenu_OnMessage(string message) { + await ShowBlurbAsync(message, ""); } private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e) { @@ -105,14 +105,14 @@ namespace ZitiDesktopEdge { /// The MFA Event private void ServiceClient_OnMfaEvent(object sender, MfaEvent mfa) { HideLoad(); - this.Dispatcher.Invoke(() => { + this.Dispatcher.Invoke(async () => { if (mfa.Action == "enrollment_challenge") { string url = HttpUtility.UrlDecode(mfa.ProvisioningUrl); string secret = HttpUtility.ParseQueryString(url)["secret"]; this.IdentityMenu.Identity.MFAInfo.RecoveryCodes = mfa?.RecoveryCodes?.ToArray(); SetupMFA(this.IdentityMenu.Identity, url, secret); } else if (mfa.Action == "auth_challenge") { - ShowBlurbAsync("Setting Up auth_challenge", ""); + await ShowBlurbAsync("Setting Up auth_challenge", ""); } else if (mfa.Action == "enrollment_verification") { if (mfa.Successful) { ShowMFARecoveryCodes(this.IdentityMenu.Identity); @@ -127,7 +127,7 @@ namespace ZitiDesktopEdge { } else if (mfa.Action == "enrollment_remove") { // ShowBlurb("removed mfa: " + mfa.Successful, ""); } else { - ShowBlurbAsync("Unexpected error when processing MFA", ""); + await ShowBlurbAsync ("Unexpected error when processing MFA", ""); logger.Error("unexpected action: " + mfa.Action); } LoadIdentities(true); @@ -172,7 +172,7 @@ namespace ZitiDesktopEdge { /// Show the MFA Recovery Codes /// /// The Ziti Identity to Authenticate - public void ShowMFARecoveryCodes(ZitiIdentity identity) { + async public void ShowMFARecoveryCodes(ZitiIdentity identity) { if (identity.MFAInfo!=null) { if (identity.MFAInfo.IsAuthenticated&& identity.MFAInfo.RecoveryCodes!=null) { MFASetup.Opacity = 0; @@ -188,7 +188,7 @@ namespace ZitiDesktopEdge { this.ShowMFA(IdentityMenu.Identity, 2); } } else { - ShowBlurbAsync("MFA is not setup on this Identity", ""); + await ShowBlurbAsync("MFA is not setup on this Identity", ""); } } @@ -232,7 +232,7 @@ namespace ZitiDesktopEdge { /// /// Close the MFA Screen with animation /// - private void DoClose(bool isComplete) { + async private void DoClose(bool isComplete) { DoubleAnimation animation = new DoubleAnimation(0, TimeSpan.FromSeconds(.3)); ThicknessAnimation animateThick = new ThicknessAnimation(new Thickness(0, 0, 0, 0), TimeSpan.FromSeconds(.3)); animation.Completed += CloseComplete; @@ -256,7 +256,7 @@ namespace ZitiDesktopEdge { } else if (MFASetup.Type == 3) { IdentityMenu.Identity.IsMFAEnabled = false; IdentityMenu.Identity.MFAInfo.IsAuthenticated = false; - ShowBlurbAsync("MFA Disabled, Service Access Can Be Limited", ""); + await ShowBlurbAsync("MFA Disabled, Service Access Can Be Limited", ""); } else if (MFASetup.Type == 4) { ShowRecovery(IdentityMenu.Identity); } diff --git a/DesktopEdge/Models/MessageCount.cs b/DesktopEdge/Models/MessageCount.cs index c4f76a72..a006f4a7 100644 --- a/DesktopEdge/Models/MessageCount.cs +++ b/DesktopEdge/Models/MessageCount.cs @@ -9,7 +9,7 @@ namespace ZitiDesktopEdge.Models { public int Total { get; set; } public string Message { get; set; } - public string ToString() { + public override string ToString() { return Total + " " + Message; } } From 52d59ac89a2063b49c91442b9c261a4982caab66 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Mon, 12 Apr 2021 13:03:43 -0400 Subject: [PATCH 13/19] add AddDns to the tunnelconfig and display it accordingly --- DesktopEdge/MainWindow.xaml.cs | 3 +++ DesktopEdge/Views/Screens/MainMenu.xaml.cs | 2 +- .../DataStructures/DataStructures.cs | 1 + .../ServiceClient/DataClient.cs | 15 --------------- 4 files changed, 5 insertions(+), 16 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index a3c92b5e..5eeb1769 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -924,6 +924,9 @@ namespace ZitiDesktopEdge { if (!Application.Current.Properties.Contains("dns")) { Application.Current.Properties.Add("dns", status?.IpInfo?.DNS); } + if (!Application.Current.Properties.Contains("dnsenabled")) { + Application.Current.Properties.Add("dnsenabled", status?.AddDns); + } foreach (var id in status.Identities) { updateViewWithIdentity(id); diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml.cs b/DesktopEdge/Views/Screens/MainMenu.xaml.cs index 95ce1a79..aeb5726e 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml.cs +++ b/DesktopEdge/Views/Screens/MainMenu.xaml.cs @@ -230,7 +230,7 @@ namespace ZitiDesktopEdge { ConfigIp.Value = Application.Current.Properties["ip"]?.ToString(); ConfigSubnet.Value = Application.Current.Properties["subnet"]?.ToString(); ConfigMtu.Value = Application.Current.Properties["mtu"]?.ToString(); - ConfigDns.Value = Application.Current.Properties["dns"]?.ToString(); + ConfigDns.Value = (bool)Application.Current.Properties["dnsenabled"] ? Application.Current.Properties["dns"]?.ToString() : "disabled"; } else if (menuState == "Identities") { MenuTitle.Content = "Identities"; IdListScrollView.Visibility = Visibility.Visible; diff --git a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs index d86c7f80..c64191bc 100644 --- a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs +++ b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs @@ -337,6 +337,7 @@ namespace ZitiDesktopEdge.DataStructures { public string LogLevel { get; set; } public ServiceVersion ServiceVersion { get; set; } + public bool AddDns { get; set; } public void Dump(System.IO.TextWriter writer) { diff --git a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs index 852b6590..af87b68d 100644 --- a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs +++ b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs @@ -203,21 +203,6 @@ namespace ZitiDesktopEdge.ServiceClient { return; } - async public Task SetLogLevelAsync(LogLevelEnum level) { - try { - await sendAsync(new SetLogLevelFunction(Enum.GetName(level.GetType(), level))); - SvcResponse resp = await readAsync(ipcReader); - return; - } catch (Exception ioe) { - //almost certainly a problem with the pipe - recreate the pipe... - //setupPipe(); - //throw ioe; - Logger.Error(ioe, "Unexpected error"); - CommunicationError(ioe); - } - return; - } - async public Task IdentityOnOffAsync(string fingerprint, bool onOff) { try { await sendAsync(new IdentityToggleFunction(fingerprint, onOff)); From 6dadf9c5f4ffce8230e4112f88d3e11e6d04c5a6 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Mon, 12 Apr 2021 13:11:42 -0400 Subject: [PATCH 14/19] remove NRPT rules properly by refcounting hostnames --- service/cziti/sdk.go | 95 ++++------------------------ service/windns/windns.go | 18 +++--- service/ziti-tunnel/service/ipc.go | 6 +- service/ziti-tunnel/service/state.go | 1 + 4 files changed, 24 insertions(+), 96 deletions(-) diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index d287f4b9..62a44bbe 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -307,11 +307,6 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z addresses = []dto.Address{toAddy(obj.Hostname)} } - /* - protocols := getTunneledServiceProtocols(ts) - addresses := getTunneledServiceAddresses(ts) - portRanges := getTunneledServicePortRanges(ts) - */ log.Infof("service update: %s, id: %s, portocols:%s, addresses:%v, portRanges: %v", name, svcId, protocols, addresses, portRanges) var svc *dto.Service @@ -539,8 +534,8 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { Fingerprint: zid.Fingerprint, HostnamesToAdd: hostnamesToAdd, HostnamesToRemove: hostnamesToRemove, - ServicesToRemove: servicesToRemove, ServicesToAdd: servicesToAdd, + ServicesToRemove: servicesToRemove, } if len(BulkServiceChanges) == cap(BulkServiceChanges) { @@ -684,82 +679,12 @@ func ziti_dump_go_to_log_cb(stringsBuilder unsafe.Pointer, charData *C.char) { sb := (*strings.Builder)(stringsBuilder) sb.WriteString(C.GoString(charData)) } -func ZitiDumpOnShutdown(zid *ZIdentity, sb *strings.Builder) { - C.ziti_dump_to_log(unsafe.Pointer(zid.czctx), unsafe.Pointer(sb)) +func ZitiDumpOnShutdown(zid *ZIdentity) { + sb := strings.Builder{} + C.ziti_dump_to_log(unsafe.Pointer(zid.czctx), unsafe.Pointer(&sb)) + log.Infof("working around the c sdk's limitation of embedding newlines on calling ziti_shutdown\n %s", sb.String()) } -/* -func getTunneledServiceProtocols(ts *C.tunneled_service_t) []string { - var protocols []string - next := C.stailq_first_protocol(ts) - if unsafe.Pointer(next) != C.NULL { - protocols = append(protocols, C.GoString(next.protocol)) - for { - next = C.stailq_next_protocol(next) - if unsafe.Pointer(next) != C.NULL { - protocols = append(protocols, C.GoString(next.protocol)) - } else { - break - } - } - } - return protocols -} - -func getTunneledServicePortRanges(ts *C.tunneled_service_t) []dto.PortRange { - var values []dto.PortRange - next := C.stailq_first_port_range(ts) - if unsafe.Pointer(next) != C.NULL { - p := dto.PortRange{ - High: int(next.high), - Low: int(next.low), - } - values = append(values, p) - for { - next = C.stailq_next_port_range(next) - if unsafe.Pointer(next) != C.NULL { - p := dto.PortRange{ - High: int(next.high), - Low: int(next.low), - } - values = append(values, p) - } else { - break - } - } - } - return values -} - -func getTunneledServiceAddresses(ts *C.tunneled_service_t) []dto.Address { - var values []dto.Address - next := C.stailq_first_address(ts) - if unsafe.Pointer(next) != C.NULL { - p := dto.Address{ - IsHost: bool(next.is_hostname), - HostName: C.GoString(&next.str[0]), - IP: C.GoString(C.ipaddr_ntoa(&next.ip)), - Prefix: int(next.prefix_len), - } - values = append(values, p) - for { - next = C.stailq_next_address(next) - if unsafe.Pointer(next) != C.NULL { - p := dto.Address{ - IsHost: bool(next.is_hostname), - HostName: C.GoString(&next.str[0]), - IP: C.GoString(C.ipaddr_ntoa(&next.ip)), - Prefix: int(next.prefix_len), - } - values = append(values, p) - } else { - break - } - } - } - return values -} -*/ func InitTunnelerDns(ipBase uint32, mask int) { C.ziti_tunneler_init_dns(C.uint32_t(ipBase), C.int(mask)) } @@ -772,15 +697,17 @@ func hostnameAdded(host string) int { count = cur + 1 } addressCount[host] = count - log.Warnf("hostname added. count now: %d", count) + log.Debugf("hostname added: %s. count now: %d", host, count) return count } func hostnameRemoved(host string) int { - count := 1 + count := 0 if cur, ok := addressCount[host]; ok { - count = cur - 1 + if cur > 0 { + count = cur - 1 + } } addressCount[host] = count - log.Warnf("hostname removed. count now: %d", count) + log.Debugf("hostname removed %s. count now: %d", host, count) return count } diff --git a/service/windns/windns.go b/service/windns/windns.go index c98082f6..dda083df 100644 --- a/service/windns/windns.go +++ b/service/windns/windns.go @@ -28,7 +28,7 @@ import ( ) var log = logging.Logger() -var exeName = "ziti-tunnel" +var exeName = "ziti-tunnel" func GetConnectionSpecificDomains() []string { script := `Get-DnsClient | Select-Object ConnectionSpecificSuffix -Unique | ForEach-Object { $_.ConnectionSpecificSuffix }; (Get-DnsClientGlobalSetting).SuffixSearchList` @@ -105,7 +105,7 @@ func FlushDNS() { func RemoveAllNrptRules() { script := fmt.Sprintf(`Get-DnsClientNrptRule | Where { $_.Comment.StartsWith("Added by %s") } | Remove-DnsClientNrptRule -ErrorAction SilentlyContinue -Force`, exeName) - log.Debugf("removing all nrpt rules with: %s", script) + log.Tracef("removing all nrpt rules with: %s", script) cmd := exec.Command("powershell", "-Command", script) cmd.Stderr = os.Stdout @@ -119,6 +119,7 @@ func RemoveAllNrptRules() { var namespaceTemplate = `%s@{n="%s";}` var namespaceTemplatePadding = len(namespaceTemplate) + func AddNrptRules(domainsToMap map[string]bool, dnsServer string) { if len(domainsToMap) == 0 { log.Debug("no domains to map specified to AddNrptRules. exiting early") @@ -165,7 +166,7 @@ ForEach ($Namespace in $Namespaces) { }`, dnsServer, exeName, exeName)) script := sb.String() - log.Debugf("Executing ADD NRPT script containing %d domains. total script size: %d\n%s", len(domainsToAdd), len(script), script) + log.Tracef("Executing ADD NRPT script containing %d domains. total script size: %d\n%s", len(domainsToAdd), len(script), script) cmd := exec.Command("powershell", "-Command", script) cmd.Stderr = os.Stdout @@ -199,6 +200,7 @@ func RemoveNrptRules(domainsToRemove map[string]bool) { hostnames[currentSize] = hostname currentSize++ } + if currentSize > 0 { //means there's a chunk still to add.... chunkedRemoveNrptRules(hostnames[:currentSize]) @@ -209,19 +211,19 @@ func chunkedRemoveNrptRules(domainsToRemove []string) { sb := strings.Builder{} sb.WriteString(`$toRemove = @(`) - for hostname := range domainsToRemove { + for _, hostname := range domainsToRemove { sb.WriteString(fmt.Sprintf(namespaceTemplate, "\n", hostname)) } sb.WriteString(fmt.Sprintf(`) -ForEach ($ns in $toRemove) { - $nrpt = Get-DnsClientNrptRule | Where {$_.Namespace -contains "${ns}"} - foreach ($n in $nrpt){Remove-DnsClientNrptRule -Name $n.Name -PassThru -Force -ErrorAction SilentlyContinue} + +ForEach ($ns in $toRemove){ + Get-DnsClientNrptRule | where Namespace -eq $ns["n"] | Remove-DnsClientNrptRule -Force -ErrorAction SilentlyContinue } `)) script := sb.String() - log.Debugf("Executing REMOVE NRPT script containing %d domains. total script size: %d\n%s", len(domainsToRemove), len(script), script) + log.Tracef("Executing REMOVE NRPT script containing %d domains. total script size: %d\n%s", len(domainsToRemove), len(script), script) cmd := exec.Command("powershell", "-Command", script) cmd.Stderr = os.Stdout diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index e64d0940..4bd5cf49 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -119,9 +119,7 @@ func SubMain(ops chan string, changes chan<- svc.Status) error { log.Debug("shutting down. start a ZitiDump") for _, id := range rts.ids { if id.CId != nil { - sb := strings.Builder{} - cziti.ZitiDumpOnShutdown(id.CId, &sb) - log.Infof("working around the c sdk's limitation of embedding newlines on calling ziti_shutdown\n %s", sb.String()) + cziti.ZitiDumpOnShutdown(id.CId) } } log.Debug("shutting down. ZitiDump complete") @@ -1029,7 +1027,7 @@ func handleBulkServiceChange(sc cziti.BulkServiceChange) { if len(sc.HostnamesToRemove) > 0 { log.Debug("removing rules from NRPT") windns.RemoveNrptRules(sc.HostnamesToRemove) - log.Infof("removed NRPT rules for: %v", sc.HostnamesToRemove) + log.Info("removed NRPT rules for: %v", sc.HostnamesToRemove) } else { log.Debug("bulk service change had no hostnames to remove") } diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index fd0f0c8e..234e729a 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -122,6 +122,7 @@ func (t *RuntimeState) ToStatus(onlyInitialized bool) dto.TunnelStatus { ServiceVersion: Version, TunIpv4: t.state.TunIpv4, TunIpv4Mask: t.state.TunIpv4Mask, + AddDns: t.state.AddDns, } i := 0 From 4d27f15fcaf1be373b39642be9e4da84d70a77e5 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Mon, 12 Apr 2021 13:15:59 -0400 Subject: [PATCH 15/19] update a comment to be more clear --- service/ziti-tunnel/service/state.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index 234e729a..cb5b06a3 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -222,7 +222,7 @@ func (t *RuntimeState) CreateTun(ipv4 string, ipv4mask int, applyDns bool) (net. log.Info("routing applied") if applyDns { - //for windows 10+ this might be able to replace NRPT? + //for windows 10+, could 'domains' be able to replace NRPT? dunno - didn't test it luid.SetDNS(windows.AF_INET, []net.IP{ip}, nil) } From 2e4787b1d0a5197357ddbde77d104fccb12b7613 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Mon, 12 Apr 2021 13:20:37 -0400 Subject: [PATCH 16/19] fix name of variable from removed->added --- DesktopEdge/MainWindow.xaml.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index 5eeb1769..c67c738d 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -533,8 +533,8 @@ namespace ZitiDesktopEdge { foreach (var removed in e.RemovedServices) { removeService(found, removed); } - foreach (var removed in e.AddedServices) { - addService(found, removed); + foreach (var added in e.AddedServices) { + addService(found, added); } LoadIdentities(false); this.Dispatcher.Invoke(() => { From 339d1abb3d053c2169148593c71f778be2439676 Mon Sep 17 00:00:00 2001 From: ziti-ci Date: Mon, 12 Apr 2021 17:25:04 +0000 Subject: [PATCH 17/19] [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 a1243675..3fed4615 100644 --- a/service/ziti-tunnel/version.go +++ b/service/ziti-tunnel/version.go @@ -21,8 +21,8 @@ package main const ( Version = "1.9.3" - Revision = "4f39c984f667" + Revision = "b6361cdb1b8d" Branch = "release-next" BuildUser = "" - BuildDate = "2021-04-08 21:19:34" + BuildDate = "2021-04-12 17:20:21" ) From 6fb4a99aabe88cf08e809bed81584a3a0ce71752 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Mon, 12 Apr 2021 13:25:21 -0400 Subject: [PATCH 18/19] extract constant --- service/windns/windns.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/service/windns/windns.go b/service/windns/windns.go index dda083df..ae2897c0 100644 --- a/service/windns/windns.go +++ b/service/windns/windns.go @@ -27,6 +27,10 @@ import ( "strings" ) +const ( + MAX_POWERSHELL_SCRIPT_LEN = 7500 //represents how long the powershell script can be. as of apr 2021 the limit was 8k (8192). leaves a little room for the rest of the script +) + var log = logging.Logger() var exeName = "ziti-tunnel" @@ -132,7 +136,7 @@ func AddNrptRules(domainsToMap map[string]bool, dnsServer string) { ruleSize := 0 for hostname := range domainsToMap { ruleSize = ruleSize + len(hostname) + namespaceTemplatePadding - if ruleSize > 7500 || currentSize >= maxBucketSize { + if ruleSize > MAX_POWERSHELL_SCRIPT_LEN || currentSize >= maxBucketSize { log.Debugf("sending chunk of domains to be added to NRPT") chunkedAddNrptRules(hostnames[:currentSize], dnsServer) hostnames = make([]string, maxBucketSize) @@ -190,7 +194,7 @@ func RemoveNrptRules(domainsToRemove map[string]bool) { ruleSize := 0 for hostname := range domainsToRemove { ruleSize = ruleSize + len(hostname) + namespaceTemplatePadding - if ruleSize > 7500 || currentSize >= maxBucketSize { + if ruleSize > MAX_POWERSHELL_SCRIPT_LEN || currentSize >= maxBucketSize { log.Debugf("sending chunk of domains to be added to NRPT") chunkedRemoveNrptRules(hostnames[:currentSize]) hostnames = make([]string, maxBucketSize) From ae81f13279f34c144ca72f7dcc083cfcb4836f45 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Mon, 12 Apr 2021 13:28:41 -0400 Subject: [PATCH 19/19] minor release notes tweak --- release-notes.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/release-notes.md b/release-notes.md index 40ec5824..67b66a3f 100644 --- a/release-notes.md +++ b/release-notes.md @@ -5,6 +5,23 @@ * Sort Service on Identity Details Page * Consistent UX for MFA Screens +## Other changes: +* Service to UI interaction is now with one bulk update of services instead of one event per service update +* Added a configuration option to control if DNS is applied to the TUN. Some users are having issues with NRPT-only working. For now we'll add a boolean that allows the user to control if DNS should be added to the TUN + +## Bugs fixed: +* none + +## Dependency Updates +* none + +# Release 1.9.3 + +## What's New +* Page Service List +* Sort Service on Identity Details Page +* Consistent UX for MFA Screens + ## Other changes: * Service to UI interaction is now with one bulk update of services instead of one event per service update