From 5532e4e205067db355453e93aba047d9591d21d4 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Tue, 17 Nov 2020 07:32:13 -0500 Subject: [PATCH 01/25] target dotnet 4.7.2 vs 4.8 due to many users not havin 4.8 yet --- DesktopEdge/App.config | 12 +- DesktopEdge/Properties/Resources.Designer.cs | 126 +++++++++---------- DesktopEdge/Properties/Settings.Designer.cs | 52 ++++---- DesktopEdge/ZitiDesktopEdge.csproj | 10 +- DesktopEdge/packages.config | 8 +- Installer/ZitiDesktopEdge.aip | 6 +- 6 files changed, 102 insertions(+), 112 deletions(-) diff --git a/DesktopEdge/App.config b/DesktopEdge/App.config index 1451e8e03..de277144e 100644 --- a/DesktopEdge/App.config +++ b/DesktopEdge/App.config @@ -1,6 +1,6 @@ - - - - - - \ No newline at end of file + + + + + + diff --git a/DesktopEdge/Properties/Resources.Designer.cs b/DesktopEdge/Properties/Resources.Designer.cs index e73a18ffe..d8f00c553 100644 --- a/DesktopEdge/Properties/Resources.Designer.cs +++ b/DesktopEdge/Properties/Resources.Designer.cs @@ -1,63 +1,63 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Ziti.Desktop.Edge.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Ziti.Desktop.Edge.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Ziti.Desktop.Edge.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Ziti.Desktop.Edge.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/DesktopEdge/Properties/Settings.Designer.cs b/DesktopEdge/Properties/Settings.Designer.cs index bd88d5245..c70068f11 100644 --- a/DesktopEdge/Properties/Settings.Designer.cs +++ b/DesktopEdge/Properties/Settings.Designer.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Ziti.Desktop.Edge.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Ziti.Desktop.Edge.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.7.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/DesktopEdge/ZitiDesktopEdge.csproj b/DesktopEdge/ZitiDesktopEdge.csproj index 88fec2a3d..188d44eda 100644 --- a/DesktopEdge/ZitiDesktopEdge.csproj +++ b/DesktopEdge/ZitiDesktopEdge.csproj @@ -8,7 +8,7 @@ WinExe Ziti.Desktop.Edge ZitiDesktopEdge - v4.8 + v4.7.2 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 @@ -94,16 +94,8 @@ - - ..\packages\System.Management.Automation.dll.10.0.10586.0\lib\net40\System.Management.Automation.dll - - - ..\packages\System.Net.NetworkInformation.4.3.0\lib\net46\System.Net.NetworkInformation.dll - True - True - diff --git a/DesktopEdge/packages.config b/DesktopEdge/packages.config index d4d1038f5..b38f3c783 100644 --- a/DesktopEdge/packages.config +++ b/DesktopEdge/packages.config @@ -1,6 +1,4 @@ - - - - - + + + \ No newline at end of file diff --git a/Installer/ZitiDesktopEdge.aip b/Installer/ZitiDesktopEdge.aip index bf4eaabc4..7a60a08ef 100644 --- a/Installer/ZitiDesktopEdge.aip +++ b/Installer/ZitiDesktopEdge.aip @@ -290,12 +290,12 @@ - + - + - + From 4e39b1e2414aba108e0545d9a67d80dcef49b3de Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Tue, 17 Nov 2020 07:32:32 -0500 Subject: [PATCH 02/25] target dotnet 4.7.2 vs 4.8 due to many users not havin 4.8 yet --- DesktopEdge/MainMenu.xaml.cs | 1 - DesktopEdge/Models/ZitiService.cs | 109 +++++++++++++++--------------- 2 files changed, 54 insertions(+), 56 deletions(-) diff --git a/DesktopEdge/MainMenu.xaml.cs b/DesktopEdge/MainMenu.xaml.cs index 678c29e00..09770e786 100644 --- a/DesktopEdge/MainMenu.xaml.cs +++ b/DesktopEdge/MainMenu.xaml.cs @@ -4,7 +4,6 @@ using System.Diagnostics; using System; using System.Threading; -using System.Management.Automation; using ZitiDesktopEdge.Models; using System.Reflection; using System.Web; diff --git a/DesktopEdge/Models/ZitiService.cs b/DesktopEdge/Models/ZitiService.cs index 9b8f75ebd..97daf0a2c 100644 --- a/DesktopEdge/Models/ZitiService.cs +++ b/DesktopEdge/Models/ZitiService.cs @@ -1,55 +1,54 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Management.Automation.Language; -using System.Text; -using System.Threading.Tasks; - -namespace ZitiDesktopEdge.Models { - public class ZitiService { - public string Name { get; set; } - public string AssignedIP { get; set; } - public string Host { get; set; } - public string Port { get; set; } - public bool OwnsIntercept { get; set; } - public string Url - { - get - { - if (this.OwnsIntercept) - { - return Host + ":" + Port; - } else - { - return AssignedIP + ":" + Port; - } - } - } - public string Warning - { - get - { - if (this.OwnsIntercept) - { - return ""; - } - else - { - return $"Another identity already mapped the specified hostname: {Host}.\nThis service is only available via IP"; - } - } - } - - public ZitiService() { - } - - public ZitiService(ZitiDesktopEdge.ServiceClient.Service svc) - { - this.Name = svc.Name; - this.AssignedIP = svc.AssignedIP; - this.Host = svc.InterceptHost; - this.Port = svc.InterceptPort.ToString(); - this.OwnsIntercept = svc.OwnsIntercept; - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ZitiDesktopEdge.Models { + public class ZitiService { + public string Name { get; set; } + public string AssignedIP { get; set; } + public string Host { get; set; } + public string Port { get; set; } + public bool OwnsIntercept { get; set; } + public string Url + { + get + { + if (this.OwnsIntercept) + { + return Host + ":" + Port; + } else + { + return AssignedIP + ":" + Port; + } + } + } + public string Warning + { + get + { + if (this.OwnsIntercept) + { + return ""; + } + else + { + return $"Another identity already mapped the specified hostname: {Host}.\nThis service is only available via IP"; + } + } + } + + public ZitiService() { + } + + public ZitiService(ZitiDesktopEdge.ServiceClient.Service svc) + { + this.Name = svc.Name; + this.AssignedIP = svc.AssignedIP; + this.Host = svc.InterceptHost; + this.Port = svc.InterceptPort.ToString(); + this.OwnsIntercept = svc.OwnsIntercept; + } + } +} From c4123ada4272eb734132b42c342242d536deab21 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Tue, 17 Nov 2020 07:33:49 -0500 Subject: [PATCH 03/25] downgrade to dotnet 4.7.2 - add initial server stub for 'big button' --- ZitiUpdateService/App.config | 18 +++--- ZitiUpdateService/IPC/IPCServer.cs | 65 ++++++++++++++++++++++ ZitiUpdateService/Program.cs | 13 +++-- ZitiUpdateService/ZitiUpdateService.csproj | 4 +- 4 files changed, 86 insertions(+), 14 deletions(-) create mode 100644 ZitiUpdateService/IPC/IPCServer.cs diff --git a/ZitiUpdateService/App.config b/ZitiUpdateService/App.config index 29658eee5..c3a5ec29b 100644 --- a/ZitiUpdateService/App.config +++ b/ZitiUpdateService/App.config @@ -1,7 +1,7 @@ - + - + - + - - + + - + - + - + - \ No newline at end of file + diff --git a/ZitiUpdateService/IPC/IPCServer.cs b/ZitiUpdateService/IPC/IPCServer.cs new file mode 100644 index 000000000..5846b0951 --- /dev/null +++ b/ZitiUpdateService/IPC/IPCServer.cs @@ -0,0 +1,65 @@ +using System; +using System.Threading.Tasks; +using System.IO; +using System.IO.Pipes; +using Newtonsoft.Json; + +namespace ZitiUpdateService.IPC { + public class IPCServer { + /* + InteractivelyLoggedInUser = "(A;;GRGW;;;IU)" //generic read/write. We will want to tune this to a specific group but that is not working with Windows 10 home at the moment + System = "(A;;FA;;;SY)" + BuiltinAdmins = "(A;;FA;;;BA)" + LocalService = "(A;;FA;;;LS)" + */ + private string pipeName; + public IPCServer(string pipeName) { + this.pipeName = pipeName; + } + + async public Task acceptAsync() { + int idx = 0; + while (true) { + var namedPipeServer = new NamedPipeServerStream(pipeName, PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte); + await namedPipeServer.WaitForConnectionAsync(); + var t = Task.Run(async ()=>{ + await handleClientAsync(namedPipeServer, idx); + idx--; + }); + idx++; + } + } + + async public Task handleClientAsync(NamedPipeServerStream ss, int clientIndex) { + using (ss) { + try { + var streamReader = new StreamReader(ss); + var line = await streamReader.ReadLineAsync(); + + var writer = new StreamWriter(ss); + for (int i = 0; i < 10; i++) { + writer.Write($"Hello from c# : {clientIndex}:{i} - Thread:{System.Threading.Thread.CurrentThread.ManagedThreadId}" ); + writer.Write("\n"); + writer.Flush(); + } + ss.WaitForPipeDrain(); + + Console.WriteLine($"read from pipe client: {streamReader.ReadLine()}"); + ss.Dispose(); + } catch(Exception e) { + Console.WriteLine("meh - error: " + e.Message); + } + } + } + + public static object DeserializeFromStream(Stream stream) { + var serializer = new JsonSerializer(); + + using (var sr = new StreamReader(stream)) + using (var jsonTextReader = new JsonTextReader(sr)) { + + return serializer.Deserialize(jsonTextReader); + } + } + } +} diff --git a/ZitiUpdateService/Program.cs b/ZitiUpdateService/Program.cs index 47b17a830..53a18ec01 100644 --- a/ZitiUpdateService/Program.cs +++ b/ZitiUpdateService/Program.cs @@ -8,6 +8,8 @@ namespace ZitiUpdateService { static class Program { + private static string PipeName = @"OpenZiti\tunneler\ipc"; + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); /// @@ -42,19 +44,22 @@ static void Main() { LogManager.Configuration = config; } Logger.Info("service started - logger initialized"); + + IPC.IPCServer svr = new IPC.IPCServer(PipeName); + svr.acceptAsync().Wait(); + UpdateService updateSvc = new UpdateService(); + updateSvc.AutoLog = true; #if DEBUG - updateSvc.Debug(); System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite); #else - ServiceBase[] ServicesToRun; - ServicesToRun = new ServiceBase[] + ServiceBase[] ServicesToRun = new ServiceBase[] { updateSvc }; ServiceBase.Run(ServicesToRun); #endif } - } + } } diff --git a/ZitiUpdateService/ZitiUpdateService.csproj b/ZitiUpdateService/ZitiUpdateService.csproj index 52a43b791..e57efc065 100644 --- a/ZitiUpdateService/ZitiUpdateService.csproj +++ b/ZitiUpdateService/ZitiUpdateService.csproj @@ -8,7 +8,7 @@ WinExe ZitiUpdateService ZitiUpdateService - v4.8 + v4.7.2 512 true true @@ -28,6 +28,7 @@ false true true + AnyCPU @@ -103,6 +104,7 @@ + From 57a6fe4913b685d8823ee5e0ae23464d66a0317f Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Tue, 17 Nov 2020 10:48:32 -0500 Subject: [PATCH 04/25] wip commit --- ZitiUpdateService/App.config | 24 ++++++++++----- ZitiUpdateService/IPC/IPCServer.cs | 34 ++++++++++++---------- ZitiUpdateService/UpdateCheckers.cs | 16 +++++----- ZitiUpdateService/ZitiUpdateService.csproj | 26 +++++++++++++++-- ZitiUpdateService/packages.config | 10 ++++++- 5 files changed, 77 insertions(+), 33 deletions(-) diff --git a/ZitiUpdateService/App.config b/ZitiUpdateService/App.config index c3a5ec29b..d795b592e 100644 --- a/ZitiUpdateService/App.config +++ b/ZitiUpdateService/App.config @@ -1,7 +1,7 @@ - + - + - + - - + + - + - + - + + + + + + + + + diff --git a/ZitiUpdateService/IPC/IPCServer.cs b/ZitiUpdateService/IPC/IPCServer.cs index 5846b0951..9f3a8d236 100644 --- a/ZitiUpdateService/IPC/IPCServer.cs +++ b/ZitiUpdateService/IPC/IPCServer.cs @@ -2,10 +2,13 @@ using System.Threading.Tasks; using System.IO; using System.IO.Pipes; -using Newtonsoft.Json; +using NLog; +using System.Text.Json; namespace ZitiUpdateService.IPC { public class IPCServer { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + /* InteractivelyLoggedInUser = "(A;;GRGW;;;IU)" //generic read/write. We will want to tune this to a specific group but that is not working with Windows 10 home at the moment System = "(A;;FA;;;SY)" @@ -32,34 +35,35 @@ async public Task acceptAsync() { async public Task handleClientAsync(NamedPipeServerStream ss, int clientIndex) { using (ss) { - try { - var streamReader = new StreamReader(ss); - var line = await streamReader.ReadLineAsync(); + try { + //var streamReader = new StreamReader(ss); + //var line = await streamReader.ReadLineAsync(); + /* var writer = new StreamWriter(ss); for (int i = 0; i < 10; i++) { writer.Write($"Hello from c# : {clientIndex}:{i} - Thread:{System.Threading.Thread.CurrentThread.ManagedThreadId}" ); writer.Write("\n"); writer.Flush(); } + */ + JsonDocument d; + while((d = await DeserializeFromStream(ss)) != null) { + Logger.Info("json object received: " + d.ToString()); + } + ss.WaitForPipeDrain(); - Console.WriteLine($"read from pipe client: {streamReader.ReadLine()}"); - ss.Dispose(); + //Logger.Debug($"read from pipe client: {streamReader.ReadLine()}"); } catch(Exception e) { - Console.WriteLine("meh - error: " + e.Message); + Logger.Error(e, "Unexpected erorr when reading from or writing to a client pipe."); } } } - public static object DeserializeFromStream(Stream stream) { - var serializer = new JsonSerializer(); - - using (var sr = new StreamReader(stream)) - using (var jsonTextReader = new JsonTextReader(sr)) { - - return serializer.Deserialize(jsonTextReader); - } + public async static Task DeserializeFromStream(Stream stream) { + JsonDocument jd = await JsonSerializer.DeserializeAsync(stream); + return jd; } } } diff --git a/ZitiUpdateService/UpdateCheckers.cs b/ZitiUpdateService/UpdateCheckers.cs index 34c265b12..f3ccff0c8 100644 --- a/ZitiUpdateService/UpdateCheckers.cs +++ b/ZitiUpdateService/UpdateCheckers.cs @@ -1,9 +1,9 @@ using System; using System.IO; using System.Net; +using System.Text.Json; using NLog; -using Newtonsoft.Json.Linq; namespace ZitiUpdateService { internal class GithubCheck : IUpdateCheck { @@ -40,8 +40,8 @@ public bool IsUpdateAvailable(Version current) { HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse(); StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()); string result = streamReader.ReadToEnd(); - JObject json = JObject.Parse(result); - string serverVersion = json.Property("tag_name").Value.ToString() + ".0"; + JsonDocument json = JsonDocument.Parse(result); + string serverVersion = json.RootElement.GetProperty("tag_name").GetString() + ".0"; Version published = new Version(serverVersion); int compare = current.CompareTo(published); @@ -54,10 +54,12 @@ public bool IsUpdateAvailable(Version current) { Logger.Debug("current version {0} is the same as the latest release {0}", current, published); return false; } - JArray assets = JArray.Parse(json.Property("assets").Value.ToString()); - foreach (JObject asset in assets.Children()) { - downloadUrl = asset.Property("browser_download_url").Value.ToString(); - break; + + foreach (JsonElement asset in json.RootElement.GetProperty("assets").EnumerateArray()) { + downloadUrl = asset.GetProperty("browser_download_url").GetString(); + if (downloadUrl != null) { + break; + } } if (downloadUrl == null) { diff --git a/ZitiUpdateService/ZitiUpdateService.csproj b/ZitiUpdateService/ZitiUpdateService.csproj index e57efc065..81fa115f1 100644 --- a/ZitiUpdateService/ZitiUpdateService.csproj +++ b/ZitiUpdateService/ZitiUpdateService.csproj @@ -75,13 +75,16 @@ bin\Releases\ - - ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll + + ..\packages\Microsoft.Bcl.AsyncInterfaces.5.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll ..\packages\NLog.4.7.5\lib\net45\NLog.dll + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + @@ -91,8 +94,27 @@ ..\packages\Microsoft.PowerShell.5.ReferenceAssemblies.1.1.0\lib\net4\System.Management.Automation.dll + + ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll + + + ..\packages\System.Text.Encodings.Web.5.0.0\lib\net461\System.Text.Encodings.Web.dll + + + ..\packages\System.Text.Json.5.0.0\lib\net461\System.Text.Json.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + diff --git a/ZitiUpdateService/packages.config b/ZitiUpdateService/packages.config index bba3d6dad..86e6bcc16 100644 --- a/ZitiUpdateService/packages.config +++ b/ZitiUpdateService/packages.config @@ -1,6 +1,14 @@  + - + + + + + + + + \ No newline at end of file From fb22f642db17f1d0f83b98f961469a206b7ebdac Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Wed, 18 Nov 2020 15:16:23 -0500 Subject: [PATCH 05/25] fixes #218 - issue when config is 0-length --- service/ziti-tunnel/config/config.go | 4 +++ service/ziti-tunnel/service/state.go | 53 ++++++++++++++++++---------- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/service/ziti-tunnel/config/config.go b/service/ziti-tunnel/config/config.go index 9b19c1505..58de2012b 100644 --- a/service/ziti-tunnel/config/config.go +++ b/service/ziti-tunnel/config/config.go @@ -31,3 +31,7 @@ func Path() string { func LogFile() string { return Path() + "ziti-tunneler.log" } + +func BackupFile() string { + return File() + ".backup" +} diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index 166a57333..c17f42f51 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -54,7 +54,7 @@ func (t *RuntimeState) SaveState() { // overwrite file if it exists _ = os.MkdirAll(config.Path(), 0644) - log.Debugf("copying original config onto config.json.backup") + log.Debugf("backing up config") backup,err := backupConfig() if err != nil { log.Warnf("could not backup config file! %v", err) @@ -252,29 +252,46 @@ func (t *RuntimeState) LoadIdentity(id *Id) { } func (t *RuntimeState) LoadConfig() { - log.Infof("reading config file located at: %s", config.File()) - file, err := os.OpenFile(config.File(), os.O_RDONLY, 0644) + err := readConfig(t, config.File()) if err != nil { - t.state = &dto.TunnelStatus{} - return + err = readConfig(t, config.BackupFile()) + if err != nil { + log.Panicf("config file is not valid nor is backup file!") + } } - r := bufio.NewReader(file) - dec := json.NewDecoder(r) + for _, id := range t.ids { + id.Active = false + } +} - err = dec.Decode(&rts.state) - if err != nil { - log.Panicf("unexpected error reading config file. %v", err) +func readConfig(t *RuntimeState, filename string) error { + log.Infof("reading config file located at: %s", filename) + info, err := os.Stat(filename) + if os.IsNotExist(err) { + log.Infof("the config file does not exist. this is normal if this is a new install or if the config file was removed manually") + return nil } - err = file.Close() + if info.Size() == 0 { + return fmt.Errorf("the config file at contains no bytes and is considered invalid: %s", filename) + } + + file, err := os.OpenFile(filename, os.O_RDONLY, 0644) if err != nil { - log.Errorf("could not close configuration file. this is not normal! %v", err) + return fmt.Errorf("unexpected error opening config file: %v", err) } - for _, id := range t.ids { - id.Active = false + r := bufio.NewReader(file) + dec := json.NewDecoder(r) + + err = dec.Decode(&t.state) + defer file.Close() + + if err != nil { + return fmt.Errorf("unexpected error reading config file: %v", err) } + return nil } func (t *RuntimeState) UpdateIpv4Mask(ipv4mask int){ @@ -312,14 +329,14 @@ func iPv6Disabled() bool { } } -func (r *RuntimeState) AddRoute(destination net.IPNet, nextHop net.IP, metric uint32) error { - nativeTunDevice := (*r.tun).(*tun.NativeTun) +func (t *RuntimeState) AddRoute(destination net.IPNet, nextHop net.IP, metric uint32) error { + nativeTunDevice := (*t.tun).(*tun.NativeTun) luid := winipcfg.LUID(nativeTunDevice.LUID()) return luid.AddRoute(destination, nextHop, metric) } -func (r *RuntimeState) RemoveRoute(destination net.IPNet, nextHop net.IP) error { - nativeTunDevice := (*r.tun).(*tun.NativeTun) +func (t *RuntimeState) RemoveRoute(destination net.IPNet, nextHop net.IP) error { + nativeTunDevice := (*t.tun).(*tun.NativeTun) luid := winipcfg.LUID(nativeTunDevice.LUID()) return luid.DeleteRoute(destination, nextHop) } From ee0a91207d611cfd8a0a86bf92061c24f6112de7 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Wed, 18 Nov 2020 18:49:33 -0500 Subject: [PATCH 06/25] wip - added separate client - refactorings --- DesktopEdge/IdentityDetails.xaml.cs | 9 +- DesktopEdge/MainMenu.xaml.cs | 10 +- DesktopEdge/MainWindow.xaml.cs | 12 +- DesktopEdge/Models/ZitiIdentity.cs | 2 +- DesktopEdge/Models/ZitiService.cs | 108 ++-- DesktopEdge/Properties/Settings.Designer.cs | 52 +- .../Views/ItemRenderers/IdentityItem.xaml.cs | 9 +- DesktopEdge/ZitiDesktopEdge.csproj | 10 +- .../DataStructures.cs | 13 +- ZitiDesktopEdge.Client/Server/IPCServer.cs | 108 ++++ .../Server/ServiceActions.cs | 30 ++ .../ServiceClient/AbstractClient.cs | 10 + .../{ClientImpl.cs => DataClient.cs} | 43 +- .../ServiceClient/MonitorClient.cs | 491 ++++++++++++++++++ .../ZitiDesktopEdge.Client.csproj | 10 +- ZitiDesktopEdge.sln | 79 ++- ZitiUpdateService/Program.cs | 12 +- ZitiUpdateService/UpdateCheckers.cs | 17 +- ZitiUpdateService/UpdateService.cs | 44 +- ZitiUpdateService/ZitiUpdateService.csproj | 30 +- ZitiUpdateService/packages.config | 10 +- service/ziti-tunnel/service/pkg-vars.go | 2 +- 22 files changed, 898 insertions(+), 213 deletions(-) rename ZitiDesktopEdge.Client/{ServiceClient => DataStructures}/DataStructures.cs (93%) create mode 100644 ZitiDesktopEdge.Client/Server/IPCServer.cs create mode 100644 ZitiDesktopEdge.Client/Server/ServiceActions.cs create mode 100644 ZitiDesktopEdge.Client/ServiceClient/AbstractClient.cs rename ZitiDesktopEdge.Client/ServiceClient/{ClientImpl.cs => DataClient.cs} (92%) create mode 100644 ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs diff --git a/DesktopEdge/IdentityDetails.xaml.cs b/DesktopEdge/IdentityDetails.xaml.cs index 68635e7d4..41819a801 100644 --- a/DesktopEdge/IdentityDetails.xaml.cs +++ b/DesktopEdge/IdentityDetails.xaml.cs @@ -14,7 +14,8 @@ using System.Windows.Navigation; using System.Windows.Shapes; using ZitiDesktopEdge.Models; - +using ZitiDesktopEdge.ServiceClient; + namespace ZitiDesktopEdge { /// /// Interaction logic for IdentityDetails.xaml @@ -110,7 +111,7 @@ public void UpdateView() { } private void IdToggle(bool on) { - ServiceClient.Client client = (ServiceClient.Client)Application.Current.Properties["ServiceClient"]; + DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; client.IdentityOnOff(_identity.Fingerprint, on); SelectedIdentity.ToggleSwitch.Enabled = on; _identity.IsEnabled = on; @@ -140,7 +141,7 @@ private void CancelConfirmButton_Click(object sender, RoutedEventArgs e) { private void ConfirmButton_Click(object sender, RoutedEventArgs e) { this.Visibility = Visibility.Collapsed; - ServiceClient.Client client = (ServiceClient.Client)Application.Current.Properties["ServiceClient"]; + DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; try { client.RemoveIdentity(_identity.Fingerprint); @@ -156,7 +157,7 @@ private void ConfirmButton_Click(object sender, RoutedEventArgs e) { if (OnForgot != null) { OnForgot(forgotten); } - } catch (ServiceClient.ServiceException se) { + } catch (DataStructures.ServiceException se) { OnError(se.Message); } catch (Exception ex) { OnError(ex.Message); diff --git a/DesktopEdge/MainMenu.xaml.cs b/DesktopEdge/MainMenu.xaml.cs index 09770e786..7520dc8bf 100644 --- a/DesktopEdge/MainMenu.xaml.cs +++ b/DesktopEdge/MainMenu.xaml.cs @@ -11,8 +11,8 @@ using System.IO; using System.Net; using Newtonsoft.Json.Linq; -using System.Threading.Tasks; - +using ZitiDesktopEdge.ServiceClient; + namespace ZitiDesktopEdge { /// @@ -149,7 +149,7 @@ private void UpdateState() { string version = ""; try { - ServiceClient.TunnelStatus s = (ServiceClient.TunnelStatus)Application.Current.Properties["CurrentTunnelStatus"]; + DataStructures.TunnelStatus s = (DataStructures.TunnelStatus)Application.Current.Properties["CurrentTunnelStatus"]; version = $"{s.ServiceVersion.Version}@{s.ServiceVersion.Revision}"; } catch (Exception e) { #if DEBUG @@ -169,7 +169,7 @@ private void UpdateState() { LicensesItems.Visibility = Visibility.Visible; BackArrow.Visibility = Visibility.Visible; } else if (menuState=="Logs") { - ServiceClient.Client client = (ServiceClient.Client)Application.Current.Properties["ServiceClient"]; + DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; MenuTitle.Content = "Service Logs"; LogsItems.Text = client.GetLogs(); LogsItems.Visibility = Visibility.Visible; @@ -218,7 +218,7 @@ private void ShowTerms(object sender, MouseButtonEventArgs e) { Process.Start(new ProcessStartInfo("https://netfoundry.io/terms") { UseShellExecute = true }); } private void ShowFeedback(object sender, MouseButtonEventArgs e) { - ServiceClient.Client client = (ServiceClient.Client)Application.Current.Properties["ServiceClient"]; + DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; var mailMessage = new MailMessage(); mailMessage.From = new MailAddress("ziti-support@netfoundry.io"); mailMessage.Subject = "Ziti Support"; diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index 07387ee49..a4cbe8205 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -4,13 +4,13 @@ using System.Windows.Input; using System.IO; using ZitiDesktopEdge.Models; -using ZitiDesktopEdge.ServiceClient; +using ZitiDesktopEdge.DataStructures; using System.ServiceProcess; using System.Linq; using System.Diagnostics; using System.Windows.Controls; using System.Drawing; - +using ZitiDesktopEdge.ServiceClient; namespace ZitiDesktopEdge { @@ -23,7 +23,7 @@ public partial class MainWindow:Window { public string Position = "Bottom"; private DateTime _startDate; private System.Windows.Forms.Timer _timer; - private Client serviceClient = null; + private DataClient serviceClient = null; private bool _isAttached = true; private bool _isServiceInError = false; private int _right = 75; @@ -150,7 +150,7 @@ private void UpdateServiceView() { private void MainWindow_Loaded(object sender, RoutedEventArgs e) { // add a new service client - serviceClient = new Client(); + serviceClient = new DataClient(); serviceClient.OnClientConnected += ServiceClient_OnClientConnected; serviceClient.OnClientDisconnected += ServiceClient_OnClientDisconnected; serviceClient.OnIdentityEvent += ServiceClient_OnIdentityEvent; @@ -289,7 +289,7 @@ private void ServiceClient_OnTunnelStatusEvent(object sender, TunnelStatusEvent Application.Current.Properties.Add("CurrentTunnelStatus", e.Status); e.Status.Dump(Console.Out); this.Dispatcher.Invoke(() => { - if(e.ApiVersion != Client.EXPECTED_API_VERSION) { + if(e.ApiVersion != DataClient.EXPECTED_API_VERSION) { SetCantDisplay("Version mismatch!", "The version of the Service is not compatible"); return; } @@ -518,7 +518,7 @@ private void AddIdentity(object sender, MouseButtonEventArgs e) { try { Identity createdId = serviceClient.AddIdentity(System.IO.Path.GetFileName(jwtDialog.FileName), false, fileContent); - ServiceClient.Client client = (ServiceClient.Client)Application.Current.Properties["ServiceClient"]; + DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; client.IdentityOnOff(createdId.FingerPrint, true); if (createdId != null) { diff --git a/DesktopEdge/Models/ZitiIdentity.cs b/DesktopEdge/Models/ZitiIdentity.cs index 187066f86..81ae0cd55 100644 --- a/DesktopEdge/Models/ZitiIdentity.cs +++ b/DesktopEdge/Models/ZitiIdentity.cs @@ -30,7 +30,7 @@ public ZitiIdentity(string Name, string ControllerUrl, bool IsEnabled, List -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Ziti.Desktop.Edge.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.7.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Ziti.Desktop.Edge.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml.cs b/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml.cs index eeda5c57d..ab55ea10b 100644 --- a/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml.cs +++ b/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml.cs @@ -13,7 +13,8 @@ using System.Windows.Navigation; using System.Windows.Shapes; using ZitiDesktopEdge.Models; - +using ZitiDesktopEdge.ServiceClient; + namespace ZitiDesktopEdge { /// /// User Control to list Identities and give status @@ -56,15 +57,15 @@ private void ToggleIdentity(bool on) { if (OnStatusChanged != null) { OnStatusChanged(on); } - ServiceClient.Client client = (ServiceClient.Client)Application.Current.Properties["ServiceClient"]; - ServiceClient.Identity id = client.IdentityOnOff(_identity.Fingerprint, on); + DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; + DataStructures.Identity id = client.IdentityOnOff(_identity.Fingerprint, on); this.Identity.IsEnabled = on; if (on) { ToggleStatus.Content = "ENABLED"; } else { ToggleStatus.Content = "DISABLED"; } - } catch (ServiceClient.ServiceException se) { + } catch (DataStructures.ServiceException se) { MessageBox.Show(se.AdditionalInfo, se.Message); } catch (Exception ex) { MessageBox.Show("Error", ex.Message); diff --git a/DesktopEdge/ZitiDesktopEdge.csproj b/DesktopEdge/ZitiDesktopEdge.csproj index 188d44eda..88fec2a3d 100644 --- a/DesktopEdge/ZitiDesktopEdge.csproj +++ b/DesktopEdge/ZitiDesktopEdge.csproj @@ -8,7 +8,7 @@ WinExe Ziti.Desktop.Edge ZitiDesktopEdge - v4.7.2 + v4.8 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 @@ -94,8 +94,16 @@ + + ..\packages\System.Management.Automation.dll.10.0.10586.0\lib\net40\System.Management.Automation.dll + + + ..\packages\System.Net.NetworkInformation.4.3.0\lib\net46\System.Net.NetworkInformation.dll + True + True + diff --git a/ZitiDesktopEdge.Client/ServiceClient/DataStructures.cs b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs similarity index 93% rename from ZitiDesktopEdge.Client/ServiceClient/DataStructures.cs rename to ZitiDesktopEdge.Client/DataStructures/DataStructures.cs index bc2b7e1a5..ae02f49c8 100644 --- a/ZitiDesktopEdge.Client/ServiceClient/DataStructures.cs +++ b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs @@ -5,8 +5,17 @@ /// These classes represent the data structures that are passed back and forth /// between the service and the client. /// -namespace ZitiDesktopEdge.ServiceClient -{ +namespace ZitiDesktopEdge.DataStructures { + public enum LogLevelEnum { + FATAL = 0, + ERROR = 1, + WARN = 2, + INFO = 3, + DEBUG = 4, + TRACE = 5, + VERBOSE = 6, + } + public class SvcResponse { public int Code { get; set; } diff --git a/ZitiDesktopEdge.Client/Server/IPCServer.cs b/ZitiDesktopEdge.Client/Server/IPCServer.cs new file mode 100644 index 000000000..c91319965 --- /dev/null +++ b/ZitiDesktopEdge.Client/Server/IPCServer.cs @@ -0,0 +1,108 @@ +using System; +using System.Threading.Tasks; +using System.IO; +using System.IO.Pipes; +using System.Security.Principal; +using System.Security.AccessControl; + +using Newtonsoft.Json; +using NLog; + +using ZitiDesktopEdge.DataStructures; + +namespace ZitiDesktopEdge.Server { + public class IPCServer { + public static string PipeName = @"OpenZiti\tunneler\monitoripc"; + + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static int BUFFER_SIZE = 16 * 1024; + + private JsonSerializer serializer = new JsonSerializer() { Formatting = Formatting.None }; + + /* + InteractivelyLoggedInUser = "(A;;GRGW;;;IU)" //generic read/write. We will want to tune this to a specific group but that is not working with Windows 10 home at the moment + System = "(A;;FA;;;SY)" + BuiltinAdmins = "(A;;FA;;;BA)" + LocalService = "(A;;FA;;;LS)" + */ + private string pipeName; + public IPCServer() { + this.pipeName = IPCServer.PipeName; + } + + async public Task acceptAsync() { + int idx = 0; + + PipeSecurity pipeSecurity = new PipeSecurity(); + var id = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null); + + // Allow AuthenticatedUserSid read and write access to the pipe. + pipeSecurity.SetAccessRule(new PipeAccessRule(id, PipeAccessRights.ReadWrite, AccessControlType.Allow)); + + while (true) { + var namedPipeServer = new NamedPipeServerStream( + pipeName, + PipeDirection.InOut, + NamedPipeServerStream.MaxAllowedServerInstances, + PipeTransmissionMode.Byte, + PipeOptions.Asynchronous, + BUFFER_SIZE, + BUFFER_SIZE, + pipeSecurity ); + + await namedPipeServer.WaitForConnectionAsync(); + _ = Task.Run(async ()=>{ + await handleClientAsync(namedPipeServer); + idx--; + Logger.Info("Total clients now at: {0}", idx); + }); + } + } + + async public Task handleClientAsync(NamedPipeServerStream ss) { + using (ss) { + try { + StreamReader reader = new StreamReader(ss); + StreamWriter writer = new StreamWriter(ss); + + string line = await reader.ReadLineAsync(); + + while (line != null) { + await processMessage(line, writer); + line = await reader.ReadLineAsync(); + } + + Logger.Info("reading from pipe is complete"); + } catch(Exception e) { + Logger.Error(e, "Unexpected erorr when reading from or writing to a client pipe."); + } + } + } + + async public Task processMessage(string msg, StreamWriter writer) { + Logger.Debug("message received: {0}", msg); + try { + ServiceFunction func = serializer.Deserialize(new JsonTextReader(new StringReader(msg))); + Logger.Info("function: {0}", func.Function); + switch (func.Function) { + case "stop": + ServiceActions.StopService(); + break; + case "start": + ServiceActions.StartService(); + break; + case "status": + msg = ServiceActions.ServiceStatus(); + break; + default: + Logger.Error("UNKNOWN ACTION received: {0}", func.Function); + break; + } + } catch (Exception e) { + Logger.Error(e, "Unexpected erorr in processMessage!"); + } + await writer.WriteLineAsync(msg); + await writer.FlushAsync(); + } + } +} diff --git a/ZitiDesktopEdge.Client/Server/ServiceActions.cs b/ZitiDesktopEdge.Client/Server/ServiceActions.cs new file mode 100644 index 000000000..b995467c7 --- /dev/null +++ b/ZitiDesktopEdge.Client/Server/ServiceActions.cs @@ -0,0 +1,30 @@ +using System.ServiceProcess; + +using NLog; + +namespace ZitiDesktopEdge.Server { + internal static class ServiceActions { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + + private static ServiceController sc = new ServiceController("ziti"); + public static string ServiceStatus() { + var status = sc.Status; + return status.ToString(); + } + + public static string StartService() { + Logger.Info("request to start ziti service received... processing..."); + sc.Start(); + Logger.Info("request to start ziti service received... complete..."); + return ServiceStatus(); + } + + public static string StopService() { + Logger.Info("request to stop ziti service received... processing..."); + sc.Start(); + Logger.Info("request to stop ziti service received... complete..."); + return ServiceStatus(); + } + } +} diff --git a/ZitiDesktopEdge.Client/ServiceClient/AbstractClient.cs b/ZitiDesktopEdge.Client/ServiceClient/AbstractClient.cs new file mode 100644 index 000000000..3e1fc7bc8 --- /dev/null +++ b/ZitiDesktopEdge.Client/ServiceClient/AbstractClient.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ZitiDesktopEdge.Server { + class AbstractClient { + } +} diff --git a/ZitiDesktopEdge.Client/ServiceClient/ClientImpl.cs b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs similarity index 92% rename from ZitiDesktopEdge.Client/ServiceClient/ClientImpl.cs rename to ZitiDesktopEdge.Client/ServiceClient/DataClient.cs index 38ecef697..883df63d1 100644 --- a/ZitiDesktopEdge.Client/ServiceClient/ClientImpl.cs +++ b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs @@ -1,17 +1,17 @@ using System; -using System.Diagnostics; using System.Collections.Generic; using System.IO; using System.IO.Pipes; using System.Security.Principal; using System.Security.AccessControl; - -using Newtonsoft.Json; using System.Threading; using System.Threading.Tasks; +using Newtonsoft.Json; using NLog; +using ZitiDesktopEdge.DataStructures; + /// /// The implementation will abstract away the setup of the communication to /// the service. This implementation will communicate to the service over a @@ -23,18 +23,7 @@ /// namespace ZitiDesktopEdge.ServiceClient { - public enum LogLevelEnum - { - FATAL = 0, - ERROR = 1, - WARN = 2, - INFO = 3, - DEBUG = 4, - TRACE = 5, - VERBOSE = 6, - } - - public class Client { + public class DataClient { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); public const int EXPECTED_API_VERSION = 1; @@ -47,6 +36,8 @@ public class Client { public event EventHandler OnClientDisconnected; public event EventHandler OnShutdownEvent; + private JsonSerializer serializer = new JsonSerializer() { Formatting=Formatting.None}; + public bool CleanShutdown { get; set; } protected virtual void ShutdownEvent(StatusEvent e) { @@ -91,12 +82,10 @@ protected virtual void ClientDisconnected(object e) OnClientDisconnected?.Invoke(this, e); } - JsonSerializer serializer = new JsonSerializer(); - private object namedPipeSyncLock = new object(); - const string ipcPipe = @"NetFoundry\tunneler\ipc"; - const string logPipe = @"NetFoundry\tunneler\logs"; - const string eventPipe = @"NetFoundry\tunneler\events"; + const string ipcPipe = @"OpenZiti\ziti\ipc"; + const string logPipe = @"OpenZiti\ziti\logs"; + const string eventPipe = @"OpenZiti\ziti\events"; const string localPipeServer = "."; const PipeDirection inOut = PipeDirection.InOut; const int ServiceConnectTimeout = 500; @@ -112,7 +101,7 @@ protected virtual void ClientDisconnected(object e) bool _extendedDebug = false; #endif - public Client() + public DataClient() { try { @@ -490,6 +479,7 @@ private void send(object objToSend) private T read(StreamReader reader) where T : SvcResponse { string respAsString = readMessage(reader); +// T resp = JsonSerializer.Deserialize(new JsonStr(respAsString)); T resp = (T)serializer.Deserialize(new StringReader(respAsString), typeof(T)); return resp; } @@ -499,12 +489,13 @@ private void processEvent(StreamReader reader) try { string respAsString = readMessage(reader); - StatusEvent evt = (StatusEvent)serializer.Deserialize(new StringReader(respAsString), typeof(StatusEvent)); + var jsonReader = new JsonTextReader(new StringReader(respAsString)); + StatusEvent evt = serializer.Deserialize(jsonReader); switch (evt.Op) { case "metrics": - MetricsEvent m = (MetricsEvent)serializer.Deserialize(new StringReader(respAsString), typeof(MetricsEvent)); + MetricsEvent m = serializer.Deserialize(jsonReader); if (m != null) { @@ -512,7 +503,7 @@ private void processEvent(StreamReader reader) } break; case "status": - TunnelStatusEvent se = (TunnelStatusEvent)serializer.Deserialize(new StringReader(respAsString), typeof(TunnelStatusEvent)); + TunnelStatusEvent se = serializer.Deserialize(jsonReader); if (se != null) { @@ -520,7 +511,7 @@ private void processEvent(StreamReader reader) } break; case "identity": - IdentityEvent id = (IdentityEvent)serializer.Deserialize(new StringReader(respAsString), typeof(IdentityEvent)); + IdentityEvent id = serializer.Deserialize(jsonReader); if (id != null) { @@ -528,7 +519,7 @@ private void processEvent(StreamReader reader) } break; case "service": - ServiceEvent svc = (ServiceEvent)serializer.Deserialize(new StringReader(respAsString), typeof(ServiceEvent)); + ServiceEvent svc = serializer.Deserialize(jsonReader); if (svc != null) { diff --git a/ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs b/ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs new file mode 100644 index 000000000..e0b78e059 --- /dev/null +++ b/ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs @@ -0,0 +1,491 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Pipes; +using System.Security.Principal; +using System.Security.AccessControl; +using System.Threading; +using System.Threading.Tasks; + +using Newtonsoft.Json; +using NLog; + +using ZitiDesktopEdge.DataStructures; + +/// +/// The implementation will abstract away the setup of the communication to +/// the service. This implementation will communicate to the service over a +/// a NamedPipe. +/// +/// All communication is effectively serial - one or more messages sent and +/// one or more messages returned. +/// +/// +namespace ZitiDesktopEdge.ServiceClient { + public class MonitorClient { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public const int EXPECTED_API_VERSION = 1; + + public event EventHandler OnTunnelStatusEvent; + public event EventHandler> OnMetricsEvent; + public event EventHandler OnIdentityEvent; + public event EventHandler OnServiceEvent; + public event EventHandler OnClientConnected; + public event EventHandler OnClientDisconnected; + public event EventHandler OnShutdownEvent; + + private JsonSerializer serializer = new JsonSerializer() { Formatting = Formatting.None }; + + public bool CleanShutdown { get; set; } + + protected virtual void ShutdownEvent(StatusEvent e) { + Logger.Debug("Clean shutdown detected from ziti"); + CleanShutdown = true; + OnShutdownEvent?.Invoke(this, e); + } + + protected virtual void TunnelStatusEvent(TunnelStatusEvent e) { + OnTunnelStatusEvent?.Invoke(this, e); + } + + protected virtual void MetricsEvent(List e) { + OnMetricsEvent?.Invoke(this, e); + } + + protected virtual void IdentityEvent(IdentityEvent e) { + OnIdentityEvent?.Invoke(this, e); + } + + protected virtual void ServiceEvent(ServiceEvent e) { + OnServiceEvent?.Invoke(this, e); + } + + protected virtual void ClientConnected(object e) { + Connected = true; + Reconnecting = false; + CleanShutdown = false; + Logger.Debug("CleanShutdown set to false"); + OnClientConnected?.Invoke(this, e); + } + + protected virtual void ClientDisconnected(object e) { + Reconnect(); + Connected = false; + OnClientDisconnected?.Invoke(this, e); + } + + private object namedPipeSyncLock = new object(); + const string ipcPipe = @"OpenZiti\ziti-monitor\ipc"; + const string logPipe = @"OpenZiti\ziti-monitor\logs"; + const string eventPipe = @"OpenZiti\ziti-monitor\events"; + const string localPipeServer = "."; + const PipeDirection inOut = PipeDirection.InOut; + const int ServiceConnectTimeout = 500; + + NamedPipeClientStream pipeClient = null; + StreamWriter writer = null; + StreamReader ipcReader = null; + + NamedPipeClientStream eventClient = null; +#if DEBUG + bool _extendedDebug = false; //set ZITI_EXTENDED_DEBUG env var to true if you want to diagnose issues with the service comms +#else + bool _extendedDebug = false; +#endif + + public MonitorClient() { + try { + string extDebugEnv = Environment.GetEnvironmentVariable("ZITI_EXTENDED_DEBUG"); + if (extDebugEnv != null) { + if (bool.Parse(extDebugEnv)) { + _extendedDebug = true; + } + } + } catch (Exception ex) { + Logger.Debug("EXCEPTION IN CLIENT CONNECT: " + ex.Message); + //if this happens - enter retry mode... + Reconnect(); + } + } + + public bool Reconnecting { get; set; } + public bool Connected { get; set; } + + public void Connect() { + //establish the named pipe to the service + setupPipe(); + } + + public void WaitForConnection() { + while (Reconnecting || !Connected) { + Task.Delay(100).Wait(); + } + } + + public void Reconnect() { + if (Reconnecting) { + Logger.Debug("Already in reconnect mode."); + return; + } else { + Reconnecting = true; + } + + Task.Run(() => { + Logger.Info("service is down. attempting to connect to service..."); + + DateTime reconnectStart = DateTime.Now; + DateTime logAgainAfter = reconnectStart + TimeSpan.FromSeconds(1); + + while (true) { + try { + Thread.Sleep(2500); + pipeClient?.Close(); + eventClient?.Close(); + setupPipe(); + + if (Connected) { + Logger.Debug("Connected to the service - exiting reconect loop"); + Connected = true; + Reconnecting = false; + return; + } else { + //ClientDisconnected(null); + } + } catch { + var now = DateTime.Now; + if (now > logAgainAfter) { + Logger.Debug("Reconnect failed. Trying again..."); + var duration = now - reconnectStart; + if (duration > TimeSpan.FromHours(1)) { + Logger.Info("reconnect has not completed and has been running for {0} hours", duration.TotalHours); + logAgainAfter += TimeSpan.FromHours(1); + } else if (duration > TimeSpan.FromMinutes(1)) { + Logger.Info("reconnect has not completed and has been running for {0} minutes", duration.TotalMinutes); + logAgainAfter += TimeSpan.FromMinutes(1); + } else { + logAgainAfter += TimeSpan.FromSeconds(1); + } + } + } + } + }); + } + + private void setupPipe() { + lock (namedPipeSyncLock) { + pipeClient = new NamedPipeClientStream(localPipeServer, ipcPipe, inOut); + eventClient = new NamedPipeClientStream(localPipeServer, eventPipe, PipeDirection.In); + + try { + eventClient.Connect(ServiceConnectTimeout); + pipeClient.Connect(ServiceConnectTimeout); + writer = new StreamWriter(pipeClient); + ipcReader = new StreamReader(pipeClient); + ClientConnected(null); + } catch (Exception ex) { + throw new ServiceException("Could not connect to the service.", 1, ex.Message); + } + + Task.Run(() => { //hack for now until it's async... + try { + StreamReader eventReader = new StreamReader(eventClient); + while (true) { + if (eventReader.EndOfStream) { + break; + } + + processEvent(eventReader); + } + } catch (Exception ex) { + Logger.Debug("unepxected error: " + ex.ToString()); + } + + // since this thread is always sitting waiting to read + // it should be the only one triggering this event + ClientDisconnected(null); + }); + } + } + + public ZitiTunnelStatus GetStatus() { + try { + send(new ServiceFunction() { Function = "Status" }); + var rtn = read(ipcReader); + return rtn; + } catch (IOException ioe) { + //almost certainly a problem with the pipe - recreate the pipe... + //setupPipe(); + throw ioe; + } + } + + ServiceFunction AddIdentityFunction = new ServiceFunction() { Function = "AddIdentity" }; + + public Identity AddIdentity(string identityName, bool activate, string jwt) { + try { + Identity id = new Identity { + Active = activate, + Name = identityName + }; + + NewIdentity newId = new NewIdentity() { + Id = id, + Flags = new EnrollmentFlags() { + JwtString = jwt + } + }; + + send(AddIdentityFunction); + send(newId); + var resp = read(ipcReader); + Logger.Debug(resp.ToString()); + if (resp.Code != 0) { + throw new ServiceException(resp.Message, resp.Code, resp.Error); + } + return resp.Payload; + } catch (IOException) { + //almost certainly a problem with the pipe - recreate the pipe... + //setupPipe(); + throw; + } + } + + + public void RemoveIdentity(string fingerPrint) { + if (string.IsNullOrEmpty(fingerPrint)) { + //nothing to do... + return; + } + + try { + FingerprintFunction removeFunction = new FingerprintFunction() { + Function = "RemoveIdentity", + Payload = new FingerprintPayload() { Fingerprint = fingerPrint } + }; + send(removeFunction); + var r = read(ipcReader); + } catch (IOException ioe) { + //almost certainly a problem with the pipe - recreate the pipe... + //setupPipe(); + throw ioe; + } + } + + private void checkConnected() { + if (Reconnecting) { + throw new ServiceException("Client is not connected", 2, "Cannot use the client at this time, it is reconnecting"); + } + if (!Connected) { + throw new ServiceException("Client is not connected", 2, "Cannot use the client at this time, it is not connected"); + } + } + + public string GetLogs() { + try { + NamedPipeClientStream logClient = new NamedPipeClientStream(localPipeServer, logPipe, PipeDirection.In); + StreamReader logReader = new StreamReader(logClient); + logClient.Connect(ServiceConnectTimeout); + + string content = logReader.ReadToEnd(); + + //ugly hack to turn ansi escaping to not... _bleck_ + //todo: fix this :point_up: + content = new System.Text.RegularExpressions.Regex(@"\x1B\[[^@-~]*[@-~]").Replace(content, ""); + return content; + } catch { + //almost certainly a problem with the pipe - probably means the service is NOT running + return "Error fetching logs from service. Is it running?"; + } + } + + public void SetLogLevel(string level) { + try { + send(new SetLogLevelFunction(level)); + SvcResponse resp = read(ipcReader); + return; + } catch (IOException ioe) { + //almost certainly a problem with the pipe - recreate the pipe... + //setupPipe(); + throw ioe; + } + } + + public void SetLogLevel(LogLevelEnum level) { + try { + send(new SetLogLevelFunction(Enum.GetName(level.GetType(), level))); + SvcResponse resp = read(ipcReader); + return; + } catch (IOException ioe) { + //almost certainly a problem with the pipe - recreate the pipe... + //setupPipe(); + throw ioe; + } + } + + public Identity IdentityOnOff(string fingerprint, bool onOff) { + try { + send(new IdentityToggleFunction(fingerprint, onOff)); + IdentityResponse idr = read(ipcReader); + return idr.Payload; + } catch (IOException ioe) { + //almost certainly a problem with the pipe - recreate the pipe... + //setupPipe(); + throw ioe; + } + } + + private void send(object objToSend) { + bool retried = false; + while (true) { + try { + string toSend = JsonConvert.SerializeObject(objToSend, Formatting.None); + + if (toSend?.Trim() != null) { + debugServiceCommunication("=============== sending message =============== "); + debugServiceCommunication(toSend); + writer.Write(toSend); + writer.Write('\n'); + debugServiceCommunication("=============== flushing message =============== "); + writer.Flush(); + debugServiceCommunication("=============== sent message =============== "); + debugServiceCommunication(""); + debugServiceCommunication(""); + } else { + Logger.Debug("NOT sending empty object??? " + objToSend?.ToString()); + } + break; + } catch (IOException ioe) { + //almost certainly a problem with the pipe - recreate the pipe... try one more time. + //setupPipe(); + if (retried) { + //we tried - throw the error... + throw ioe; + } else { + retried = true; //fall back through to the while and try again + } + } catch (Exception ex) { + //if this fails it's usually because the writer is null/invalid. throwing IOException + //will trigger the pipe to rebuild + throw new IOException("Unexpected error when sending data to service. " + ex.Message); + } + } + } + + private T read(StreamReader reader) where T : SvcResponse { + string respAsString = readMessage(reader); + // T resp = JsonSerializer.Deserialize(new JsonStr(respAsString)); + T resp = (T)serializer.Deserialize(new StringReader(respAsString), typeof(T)); + return resp; + } + + private void processEvent(StreamReader reader) { + try { + string respAsString = readMessage(reader); + var jsonReader = new JsonTextReader(new StringReader(respAsString)); + StatusEvent evt = serializer.Deserialize(jsonReader); + + switch (evt.Op) { + case "metrics": + MetricsEvent m = serializer.Deserialize(jsonReader); + + if (m != null) { + MetricsEvent(m.Identities); + } + break; + case "status": + TunnelStatusEvent se = serializer.Deserialize(jsonReader); + + if (se != null) { + TunnelStatusEvent(se); + } + break; + case "identity": + IdentityEvent id = serializer.Deserialize(jsonReader); + + if (id != null) { + IdentityEvent(id); + } + break; + case "service": + ServiceEvent svc = serializer.Deserialize(jsonReader); + + if (svc != null) { + ServiceEvent(svc); + } + break; + case "shutdown": + + break; + default: + Logger.Debug("unexpected operation! " + evt.Op); + break; + } + } catch (Exception e) { + Logger.Debug(e.Message); + } + } + + public string readMessage(StreamReader reader) { + try { + if (reader.EndOfStream) { + throw new ServiceException("the pipe has closed", 0, "end of stream reached"); + } + int emptyCount = 1; //just a stop gap in case something crazy happens in the communication + + debugServiceCommunication("=============== reading message =============== " + emptyCount); + string respAsString = reader.ReadLine(); + debugServiceCommunication(respAsString); + debugServiceCommunication("=============== read message =============== " + emptyCount); + while (string.IsNullOrEmpty(respAsString?.Trim())) { + if (reader.EndOfStream) { + throw new Exception("the pipe has closed"); + } + debugServiceCommunication("Received empty payload - continuing to read until a payload is received"); + //now how'd that happen... + debugServiceCommunication("=============== reading message =============== " + emptyCount); + respAsString = reader.ReadLine(); + debugServiceCommunication(respAsString); + debugServiceCommunication("=============== read message =============== " + emptyCount); + emptyCount++; + if (emptyCount > 5) { + Logger.Debug("are we there yet? " + reader.EndOfStream); + //that's just too many... + //setupPipe(); + return null; + } + } + debugServiceCommunication(""); + debugServiceCommunication(""); + return respAsString; + } catch (IOException ioe) { + //almost certainly a problem with the pipe + Logger.Debug("io error in read: " + ioe.Message); + ClientDisconnected(null); + throw ioe; + } catch (Exception ee) { + //almost certainly a problem with the pipe + Logger.Debug("unexpected error in read: " + ee.Message); + ClientDisconnected(null); + throw ee; + } + } + + private void debugServiceCommunication(string msg) { + if (_extendedDebug) { + Logger.Debug(msg); + } + } + public ZitiTunnelStatus debug() { + try { + send(new ServiceFunction() { Function = "Debug" }); + var rtn = read(ipcReader); + return rtn; + } catch (IOException ioe) { + //almost certainly a problem with the pipe - recreate the pipe... + //setupPipe(); + throw ioe; + } + } + } +} \ No newline at end of file diff --git a/ZitiDesktopEdge.Client/ZitiDesktopEdge.Client.csproj b/ZitiDesktopEdge.Client/ZitiDesktopEdge.Client.csproj index 19741a345..983e90eae 100644 --- a/ZitiDesktopEdge.Client/ZitiDesktopEdge.Client.csproj +++ b/ZitiDesktopEdge.Client/ZitiDesktopEdge.Client.csproj @@ -7,7 +7,7 @@ {26B30979-99B5-4102-BD0B-129BEDFF0057} Library Properties - ZitiDesktopEdge.Client + ZitiDesktopEdge ZitiDesktopEdge.Client v4.7.2 512 @@ -44,6 +44,7 @@ + @@ -54,8 +55,11 @@ - - + + + + + diff --git a/ZitiDesktopEdge.sln b/ZitiDesktopEdge.sln index 3edaa021d..8167e22a5 100644 --- a/ZitiDesktopEdge.sln +++ b/ZitiDesktopEdge.sln @@ -11,10 +11,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZitiDesktopEdge", "DesktopEdge\ZitiDesktopEdge.csproj", "{FA4291EA-A97E-4854-959F-91EE7B330B37}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZitiUpdateService", "ZitiUpdateService\ZitiUpdateService.csproj", "{9AB81609-F5DD-40A6-87B5-F3279D48514D}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZitiDesktopEdge.Client", "ZitiDesktopEdge.Client\ZitiDesktopEdge.Client.csproj", "{26B30979-99B5-4102-BD0B-129BEDFF0057}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZitiUpdateService", "ZitiUpdateService\ZitiUpdateService.csproj", "{9AB81609-F5DD-40A6-87B5-F3279D48514D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +27,11 @@ Global Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 + Releases|Any CPU = Releases|Any CPU + Releases|ARM = Releases|ARM + Releases|ARM64 = Releases|ARM64 + Releases|x64 = Releases|x64 + Releases|x86 = Releases|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {FA4291EA-A97E-4854-959F-91EE7B330B37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -49,26 +54,16 @@ Global {FA4291EA-A97E-4854-959F-91EE7B330B37}.Release|x64.Build.0 = Release|Any CPU {FA4291EA-A97E-4854-959F-91EE7B330B37}.Release|x86.ActiveCfg = Release|Any CPU {FA4291EA-A97E-4854-959F-91EE7B330B37}.Release|x86.Build.0 = Release|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|ARM.ActiveCfg = Debug|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|ARM.Build.0 = Debug|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|ARM64.Build.0 = Debug|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|x64.ActiveCfg = Debug|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|x64.Build.0 = Debug|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|x86.ActiveCfg = Debug|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|x86.Build.0 = Debug|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|Any CPU.Build.0 = Release|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|ARM.ActiveCfg = Release|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|ARM.Build.0 = Release|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|ARM64.ActiveCfg = Release|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|ARM64.Build.0 = Release|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|x64.ActiveCfg = Release|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|x64.Build.0 = Release|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|x86.ActiveCfg = Release|Any CPU - {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|x86.Build.0 = Release|Any CPU + {FA4291EA-A97E-4854-959F-91EE7B330B37}.Releases|Any CPU.ActiveCfg = Releases|Any CPU + {FA4291EA-A97E-4854-959F-91EE7B330B37}.Releases|Any CPU.Build.0 = Releases|Any CPU + {FA4291EA-A97E-4854-959F-91EE7B330B37}.Releases|ARM.ActiveCfg = Releases|Any CPU + {FA4291EA-A97E-4854-959F-91EE7B330B37}.Releases|ARM.Build.0 = Releases|Any CPU + {FA4291EA-A97E-4854-959F-91EE7B330B37}.Releases|ARM64.ActiveCfg = Releases|Any CPU + {FA4291EA-A97E-4854-959F-91EE7B330B37}.Releases|ARM64.Build.0 = Releases|Any CPU + {FA4291EA-A97E-4854-959F-91EE7B330B37}.Releases|x64.ActiveCfg = Releases|Any CPU + {FA4291EA-A97E-4854-959F-91EE7B330B37}.Releases|x64.Build.0 = Releases|Any CPU + {FA4291EA-A97E-4854-959F-91EE7B330B37}.Releases|x86.ActiveCfg = Releases|Any CPU + {FA4291EA-A97E-4854-959F-91EE7B330B37}.Releases|x86.Build.0 = Releases|Any CPU {26B30979-99B5-4102-BD0B-129BEDFF0057}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {26B30979-99B5-4102-BD0B-129BEDFF0057}.Debug|Any CPU.Build.0 = Debug|Any CPU {26B30979-99B5-4102-BD0B-129BEDFF0057}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -89,6 +84,46 @@ Global {26B30979-99B5-4102-BD0B-129BEDFF0057}.Release|x64.Build.0 = Release|Any CPU {26B30979-99B5-4102-BD0B-129BEDFF0057}.Release|x86.ActiveCfg = Release|Any CPU {26B30979-99B5-4102-BD0B-129BEDFF0057}.Release|x86.Build.0 = Release|Any CPU + {26B30979-99B5-4102-BD0B-129BEDFF0057}.Releases|Any CPU.ActiveCfg = Release|Any CPU + {26B30979-99B5-4102-BD0B-129BEDFF0057}.Releases|Any CPU.Build.0 = Release|Any CPU + {26B30979-99B5-4102-BD0B-129BEDFF0057}.Releases|ARM.ActiveCfg = Release|Any CPU + {26B30979-99B5-4102-BD0B-129BEDFF0057}.Releases|ARM.Build.0 = Release|Any CPU + {26B30979-99B5-4102-BD0B-129BEDFF0057}.Releases|ARM64.ActiveCfg = Release|Any CPU + {26B30979-99B5-4102-BD0B-129BEDFF0057}.Releases|ARM64.Build.0 = Release|Any CPU + {26B30979-99B5-4102-BD0B-129BEDFF0057}.Releases|x64.ActiveCfg = Release|Any CPU + {26B30979-99B5-4102-BD0B-129BEDFF0057}.Releases|x64.Build.0 = Release|Any CPU + {26B30979-99B5-4102-BD0B-129BEDFF0057}.Releases|x86.ActiveCfg = Release|Any CPU + {26B30979-99B5-4102-BD0B-129BEDFF0057}.Releases|x86.Build.0 = Release|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|ARM.ActiveCfg = Debug|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|ARM.Build.0 = Debug|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|ARM64.Build.0 = Debug|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|x64.ActiveCfg = Debug|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|x64.Build.0 = Debug|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|x86.ActiveCfg = Debug|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Debug|x86.Build.0 = Debug|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|Any CPU.Build.0 = Release|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|ARM.ActiveCfg = Release|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|ARM.Build.0 = Release|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|ARM64.ActiveCfg = Release|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|ARM64.Build.0 = Release|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|x64.ActiveCfg = Release|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|x64.Build.0 = Release|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|x86.ActiveCfg = Release|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Release|x86.Build.0 = Release|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Releases|Any CPU.ActiveCfg = Releases|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Releases|Any CPU.Build.0 = Releases|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Releases|ARM.ActiveCfg = Releases|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Releases|ARM.Build.0 = Releases|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Releases|ARM64.ActiveCfg = Releases|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Releases|ARM64.Build.0 = Releases|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Releases|x64.ActiveCfg = Releases|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Releases|x64.Build.0 = Releases|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Releases|x86.ActiveCfg = Releases|Any CPU + {9AB81609-F5DD-40A6-87B5-F3279D48514D}.Releases|x86.Build.0 = Releases|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ZitiUpdateService/Program.cs b/ZitiUpdateService/Program.cs index 53a18ec01..da4f2c952 100644 --- a/ZitiUpdateService/Program.cs +++ b/ZitiUpdateService/Program.cs @@ -1,14 +1,16 @@ -using System; -using System.IO; +using System.IO; +using System.Linq; using System.Reflection; -using System.ServiceProcess; +using System.Security.Cryptography.X509Certificates; + using NLog; using NLog.Config; using NLog.Targets; +using ZitiDesktopEdge.Server; + namespace ZitiUpdateService { static class Program { - private static string PipeName = @"OpenZiti\tunneler\ipc"; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); @@ -45,7 +47,7 @@ static void Main() { } Logger.Info("service started - logger initialized"); - IPC.IPCServer svr = new IPC.IPCServer(PipeName); + IPCServer svr = new IPCServer(); svr.acceptAsync().Wait(); UpdateService updateSvc = new UpdateService(); diff --git a/ZitiUpdateService/UpdateCheckers.cs b/ZitiUpdateService/UpdateCheckers.cs index f3ccff0c8..296d0c261 100644 --- a/ZitiUpdateService/UpdateCheckers.cs +++ b/ZitiUpdateService/UpdateCheckers.cs @@ -1,9 +1,9 @@ using System; using System.IO; using System.Net; -using System.Text.Json; using NLog; +using Newtonsoft.Json.Linq; namespace ZitiUpdateService { internal class GithubCheck : IUpdateCheck { @@ -40,8 +40,8 @@ public bool IsUpdateAvailable(Version current) { HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse(); StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()); string result = streamReader.ReadToEnd(); - JsonDocument json = JsonDocument.Parse(result); - string serverVersion = json.RootElement.GetProperty("tag_name").GetString() + ".0"; + JObject json = JObject.Parse(result); + string serverVersion = json.Property("tag_name").Value.ToString() + ".0"; Version published = new Version(serverVersion); int compare = current.CompareTo(published); @@ -54,12 +54,11 @@ public bool IsUpdateAvailable(Version current) { Logger.Debug("current version {0} is the same as the latest release {0}", current, published); return false; } - - foreach (JsonElement asset in json.RootElement.GetProperty("assets").EnumerateArray()) { - downloadUrl = asset.GetProperty("browser_download_url").GetString(); - if (downloadUrl != null) { - break; - } + + JArray assets = JArray.Parse(json.Property("assets").Value.ToString()); + foreach (JObject asset in assets.Children()) { + downloadUrl = asset.Property("browser_download_url").Value.ToString(); + break; } if (downloadUrl == null) { diff --git a/ZitiUpdateService/UpdateService.cs b/ZitiUpdateService/UpdateService.cs index 96c43d7ef..df9478d59 100644 --- a/ZitiUpdateService/UpdateService.cs +++ b/ZitiUpdateService/UpdateService.cs @@ -7,12 +7,17 @@ using System.Configuration; using System.Threading.Tasks; -using ZitiDesktopEdge.ServiceClient; +using ZitiDesktopEdge.DataStructures; using NLog; using System.Reflection; +using System.Security.Cryptography.X509Certificates; +using ZitiDesktopEdge.ServiceClient; namespace ZitiUpdateService { public partial class UpdateService : ServiceBase { + private static string[] expected_hashes = new string[] { "39636E9F5E80308DE370C914CE8112876ECF4E0C" }; + private static string[] expected_subject = new string[] { @"CN=""NetFoundry, Inc."", O=""NetFoundry, Inc."", L=Herndon, S=Virginia, C=US" }; + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private Timer _updateTimer = new Timer(); @@ -21,7 +26,7 @@ public partial class UpdateService : ServiceBase { private string _logDirectory = ""; private string _versionType = "latest"; - private Client svc = new Client(); + private DataClient svc = new DataClient(); private bool running = false; ServiceController controller; @@ -93,10 +98,7 @@ private void CheckUpdate(object sender, ElapsedEventArgs e) { inUpdateCheck = true; //simple semaphone try { Logger.Debug("checking for update"); - var updateUrl = ConfigurationManager.AppSettings.Get("UpdateUrl"); - if (string.IsNullOrEmpty(updateUrl)) { - updateUrl = "https://api.github.com/repos/openziti/desktop-edge-win/releases/latest"; - } + string updateUrl = "https://api.github.com/repos/openziti/desktop-edge-win/releases/latest"; //hardcoded on purpose IUpdateCheck check = new GithubCheck(updateUrl); //IUpdateCheck check = new FilesystemCheck(); @@ -126,10 +128,36 @@ private void CheckUpdate(object sender, ElapsedEventArgs e) { Logger.Info("copying update package complete"); } + string fileDestination = Path.Combine(updateFolder, filename); + + // check digital signature + var signer = X509Certificate.CreateFromSignedFile(fileDestination); + /* keep these commented out lines - just in case we need all the certs from the file use this + var coll = new X509Certificate2Collection(); + coll.Import(filePath); + */ + + var subject = signer.Subject; + if (!expected_subject.Contains(subject)) { + Logger.Error("the file downloaded uses a subject that is unknown! the installation will not proceed. [subject:{0}]", subject); + return; + + } else { + Logger.Info("the file downloaded uses a known subject. installation and can proceed. [subject:{0}]", subject); + } + + var hash = signer.GetCertHashString(); + if (!expected_hashes.Contains(hash)) { + Logger.Error("the file downloaded is signed by an unknown certificate! the installation will not proceed. [hash:{0}]", hash); + return; + + } else { + Logger.Info("the file downloaded is signed by a known certificate. installation and can proceed. [subject:{0}]", subject); + } + StopZiti(); // shell out to a new process and run the uninstall, reinstall steps which SHOULD stop this current process as well - string fileDestination = Path.Combine(updateFolder, filename); Process.Start(fileDestination, "/passive"); } catch (Exception ex) { Logger.Error(ex, "Unexpected error has occurred"); @@ -180,7 +208,7 @@ private static void Svc_OnClientConnected(object sender, object e) { } private static void Svc_OnClientDisconnected(object sender, object e) { - Client svc = (Client)sender; + DataClient svc = (DataClient)sender; if (svc.CleanShutdown) { //then this is fine and expected - the service is shutting down Logger.Info("client disconnected due to clean service shutdown"); diff --git a/ZitiUpdateService/ZitiUpdateService.csproj b/ZitiUpdateService/ZitiUpdateService.csproj index 81fa115f1..52a43b791 100644 --- a/ZitiUpdateService/ZitiUpdateService.csproj +++ b/ZitiUpdateService/ZitiUpdateService.csproj @@ -8,7 +8,7 @@ WinExe ZitiUpdateService ZitiUpdateService - v4.7.2 + v4.8 512 true true @@ -28,7 +28,6 @@ false true true - AnyCPU @@ -75,16 +74,13 @@ bin\Releases\ - - ..\packages\Microsoft.Bcl.AsyncInterfaces.5.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll + + ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll ..\packages\NLog.4.7.5\lib\net45\NLog.dll - - ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll - @@ -94,27 +90,8 @@ ..\packages\Microsoft.PowerShell.5.ReferenceAssemblies.1.1.0\lib\net4\System.Management.Automation.dll - - ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll - - - - ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll - - - ..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll - - - ..\packages\System.Text.Encodings.Web.5.0.0\lib\net461\System.Text.Encodings.Web.dll - - - ..\packages\System.Text.Json.5.0.0\lib\net461\System.Text.Json.dll - - - ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll - @@ -126,7 +103,6 @@ - diff --git a/ZitiUpdateService/packages.config b/ZitiUpdateService/packages.config index 86e6bcc16..bba3d6dad 100644 --- a/ZitiUpdateService/packages.config +++ b/ZitiUpdateService/packages.config @@ -1,14 +1,6 @@  - + - - - - - - - - \ No newline at end of file diff --git a/service/ziti-tunnel/service/pkg-vars.go b/service/ziti-tunnel/service/pkg-vars.go index 039dc0e2c..4d915515f 100644 --- a/service/ziti-tunnel/service/pkg-vars.go +++ b/service/ziti-tunnel/service/pkg-vars.go @@ -25,7 +25,7 @@ import ( "time" ) var Version dto.ServiceVersion -var pipeBase = `\\.\pipe\NetFoundry\tunneler\` +var pipeBase = `\\.\pipe\OpenZiti\ziti\` var rts = RuntimeState{ ids: make(map[string]*Id), From 51ad1d314fd0749b8be683d54dacaa9e41eb6e19 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 19 Nov 2020 12:59:22 -0500 Subject: [PATCH 07/25] wip - services converted. pipes renamed. initial bigbutton works. moving to UI work --- DesktopEdge/MainWindow.xaml | 648 +++++++++--------- DesktopEdge/MainWindow.xaml.cs | 144 ++-- ZitiDesktopEdge.Client/Server/IPCServer.cs | 139 +++- .../Server/ServiceActions.cs | 5 +- .../ServiceClient/AbstractClient.cs | 255 ++++++- .../ServiceClient/DataClient.cs | 383 +++-------- .../ServiceClient/MonitorClient.cs | 456 +----------- .../ZitiDesktopEdge.Client.csproj | 2 +- ZitiUpdateService/Program.cs | 8 +- ZitiUpdateService/UpdateService.cs | 2 +- 10 files changed, 888 insertions(+), 1154 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml b/DesktopEdge/MainWindow.xaml index 42c7e442e..6ac248011 100644 --- a/DesktopEdge/MainWindow.xaml +++ b/DesktopEdge/MainWindow.xaml @@ -1,323 +1,325 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +