From 47d7b16d935648c5e08c465defa31cf0f7df5610 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Wed, 31 Mar 2021 01:19:43 +0530 Subject: [PATCH 01/36] config ip and mask update --- service/ziti-tunnel/cli/constants.go | 4 + service/ziti-tunnel/cli/responseGenerator.go | 14 ++++ service/ziti-tunnel/cli/service.go | 50 +++++++++++- service/ziti-tunnel/main.go | 2 + service/ziti-tunnel/service/ipc.go | 18 ++++ service/ziti-tunnel/service/state.go | 86 +++++++++++++++++++- 6 files changed, 172 insertions(+), 2 deletions(-) diff --git a/service/ziti-tunnel/cli/constants.go b/service/ziti-tunnel/cli/constants.go index 3c9f4be5..5892ae96 100644 --- a/service/ziti-tunnel/cli/constants.go +++ b/service/ziti-tunnel/cli/constants.go @@ -42,6 +42,10 @@ var NOTIFY_IDENTITY_UI = dto.CommandMsg{ Function: "NotifyIdentityUI", } +var UPDATE_TUN_IPV4 = dto.CommandMsg{ + Function: "UpdateTunIpv4", +} + var monitorIpcPipe = `\\.\pipe\OpenZiti\ziti-monitor\ipc` var templateIdentity = `{{printf "%40s" "Name"}} | {{printf "%41s" "FingerPrint"}} | {{printf "%6s" "Active"}} | {{printf "%30s" "Config"}} | {{"Status"}} diff --git a/service/ziti-tunnel/cli/responseGenerator.go b/service/ziti-tunnel/cli/responseGenerator.go index 83ca8355..cc2b8c2c 100644 --- a/service/ziti-tunnel/cli/responseGenerator.go +++ b/service/ziti-tunnel/cli/responseGenerator.go @@ -160,6 +160,20 @@ func GetServicesFromRTS(args []string, status *dto.TunnelStatus, flags map[strin } +func GetStatusFromRTS(args []string, status *dto.TunnelStatus, flags map[string]bool) dto.Response { + + if status == nil { + return dto.Response{Message: "Stopped / Unknown State", Code: service.SUCCESS, Error: "", Payload: ""} + } + + if status.Active { + return dto.Response{Message: "Running", Code: service.SUCCESS, Error: "", Payload: ""} + } else { + return dto.Response{Message: "Stopped", Code: service.SUCCESS, Error: "", Payload: ""} + } + +} + func generateResponse(dataType string, message string, filteredData interface{}, flags map[string]bool, templateStr string) dto.Response { var bytesData []byte diff --git a/service/ziti-tunnel/cli/service.go b/service/ziti-tunnel/cli/service.go index ebc1b290..359b47cd 100644 --- a/service/ziti-tunnel/cli/service.go +++ b/service/ziti-tunnel/cli/service.go @@ -2,8 +2,10 @@ package cli import ( "strings" - + "strconv" + "golang.org/x/sys/windows/svc" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto" + "github.com/openziti/desktop-edge-win/service/ziti-tunnel/service" ) //GetIdentities is to fetch identities through cmdline @@ -53,3 +55,49 @@ func SetLogLevel(args []string, flags map[string]bool) { func GetFeedback(args []string, flags map[string]bool) { GetDataFromMonitorIpcPipe(&dto.FEEDBACK_REQUEST, args, flags) } + +func UpdateConfigIPSubnet(args []string, flags map[string]interface{}) { + CIDRstring := flags["CIDR"] + log.Infof("Updating the config file with IP CIDR %v", flags["CIDR"]) + var cidr = strings.Split(CIDRstring.(string), "/") + if len(cidr) != 2 { + log.Error("Incorrect cidr") + } + ipMask, err := strconv.Atoi(cidr[1]) + if err != nil { + log.Errorf("Incorrect ipv4 mask, %s", cidr[1]) + return + } + updateTunIpv4Payload := make(map[string]interface{}) + updateTunIpv4Payload["TunIPv4"] = cidr[0] + updateTunIpv4Payload["TunIPv4Mask"] = cidr[1] + UPDATE_TUN_IPV4.Payload = updateTunIpv4Payload + log.Debugf("updateTunIpv4 Payload %v", UPDATE_TUN_IPV4) + + status := GetDataFromIpcPipe(&UPDATE_TUN_IPV4, nil, GetResponseObjectFromRTS, args, nil) + + if !status { + log.Infof("Updating ip and mask in the config file. Manual restart is required") + err = service.UpdateRuntimeStateIpv4(true, cidr[0], ipMask) + if err != nil { + log.Errorf("Unable to set Tun ip and mask, %v", err) + return + } + log.Infof("ip and mask are set") + } + + if status { + log.Infof("Attempting to restart ziti ") + + err = service.ControlService(svc.Stop, svc.Stopped) + if (err != nil) { + log.Errorf("Unable to stop the service, %v", err) + return + } + err = service.StartService() + if (err != nil) { + log.Errorf("Unable to start the service, %v", err) + } + } + +} diff --git a/service/ziti-tunnel/main.go b/service/ziti-tunnel/main.go index c1c3f236..e765ea59 100644 --- a/service/ziti-tunnel/main.go +++ b/service/ziti-tunnel/main.go @@ -111,6 +111,8 @@ func main() { commandline.Execute() case "feedback": commandline.Execute() + case "config": + commandline.Execute() default: usage(fmt.Sprintf("invalid command %s", cmd)) } diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index fb8af897..16e63e12 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -42,6 +42,7 @@ import ( "os" "os/signal" "strings" + "strconv" "sync" "time" ) @@ -498,6 +499,8 @@ func serveIpc(conn net.Conn) { //save the state rts.SaveState() + case "UpdateTunIpv4": + updateTunIpv4(enc, cmd.Payload["TunIPv4"].(string), cmd.Payload["TunIPv4Mask"].(string)) case "NotifyLogLevelUIAndUpdateService": sendLogLevelAndNotify(enc, cmd.Payload["Level"].(string)) case "NotifyIdentityUI": @@ -622,6 +625,21 @@ func setLogLevel(out *json.Encoder, level string) { respond(out, dto.Response{Message: "log level set", Code: SUCCESS, Error: "", Payload: nil}) } +func updateTunIpv4(out *json.Encoder, ip string, ipmask string) { + ipMask, err := strconv.Atoi(ipmask) + if err != nil { + respondWithError(out, "Incorrect ipv4 mask", UNKNOWN_ERROR, err) + return + } + err = UpdateRuntimeStateIpv4(false, ip, ipMask) + if err != nil { + respondWithError(out, "Could not set Tun ip and mask", UNKNOWN_ERROR, err) + return + } + + respond(out, dto.Response{Message: "TunIPv4 and mask is set", Code: SUCCESS, Error: "", Payload: ""}) +} + func serveLogs(conn net.Conn) { log.Debug("accepted a logs connection, writing logs to pipe") w := bufio.NewWriter(conn) diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index 1f286216..86dfd1f6 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -28,7 +28,8 @@ import ( "path" "strings" "time" - + "path/filepath" + "errors" "github.com/openziti/desktop-edge-win/service/cziti" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/config" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/constants" @@ -105,6 +106,58 @@ func backupConfig() (string, error) { return backup, err } + +func (t *RuntimeState) SaveStateWithPath(systemPath string) { + // overwrite file if it exists + _ = os.MkdirAll(systemPath, 0644) + + log.Debugf("backing up config") + backup, err := backupConfigWithPath(systemPath) + if err != nil { + log.Warnf("could not backup config file! %v", err) + } else { + log.Debugf("config file backed up to: %s", backup) + } + + cfg, err := os.OpenFile(filepath.Join(systemPath, string(os.PathSeparator), "config.json"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) + defer cfg.Close() + if err != nil { + log.Panicf("An unexpected and unrecoverable error has occurred while %s: %v", "opening the config file", err) + } + + w := bufio.NewWriter(bufio.NewWriter(cfg)) + enc := json.NewEncoder(w) + enc.SetIndent("", " ") + _ = enc.Encode(t.state) + _ = w.Flush() + + err = cfg.Close() + if err != nil { + log.Panicf("An unexpected and unrecoverable error has occurred while %s: %v", "closing the config file", err) + } + log.Debug("state saved") +} + +func backupConfigWithPath(systemPath string) (string, error) { + original, err := os.Open(filepath.Join(systemPath, string(os.PathSeparator), "config.json")) + if err != nil { + return "", err + } + defer original.Close() + backup := filepath.Join(systemPath, string(os.PathSeparator), "config.json.backup") + new, err := os.Create(backup) + if err != nil { + return "", err + } + defer new.Close() + + _, err = io.Copy(new, original) + if err != nil { + return "", err + } + return backup, err +} + func (t *RuntimeState) ToStatus(onlyInitialized bool) dto.TunnelStatus { var uptime int64 @@ -397,6 +450,37 @@ func (t *RuntimeState) UpdateIpv4(ipv4 string) { rts.SaveState() } +func UpdateRuntimeStateIpv4(offline bool, ip string, ipv4Mask int) error { + + log.Infof("ip and mask %s %d", ip, ipv4Mask) + + if offline { + systemDrivePath := os.Getenv("SystemDrive") + if systemDrivePath == "" { + return errors.New("SystemDrive env is not found") + } + configPath := "Windows\\System32\\config\\systemprofile\\AppData\\Roaming\\NetFoundry" + systemPath := filepath.Join(systemDrivePath, string(os.PathSeparator), configPath) + err := readConfig(rts, filepath.Join(systemPath, string(os.PathSeparator), "config.json")) + if (err != nil) { + log.Errorf("Unable to read the config file, %v", err) + return err + } + + rts.state.TunIpv4 = ip + rts.state.TunIpv4Mask = ipv4Mask + + rts.SaveStateWithPath(systemPath) + + } else { + rts.state.TunIpv4 = ip + rts.state.TunIpv4Mask = ipv4Mask + rts.SaveState() + } + + return nil +} + // uses the registry to determine if IPv6 is enabled or disabled on this machine. If it is disabled an IPv6 DNS entry // will end up causing a fatal error on startup of the service. For this registry key and values see the MS documentation // at https://docs.microsoft.com/en-us/troubleshoot/windows-server/networking/configure-ipv6-in-windows From 55b0ca48f5e8f96c142be3a88df9b7aaa72b5cd1 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 5 Apr 2021 16:10:42 +0530 Subject: [PATCH 02/36] adding the config cli --- service/ziti-tunnel/cmd/config.go | 48 +++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 service/ziti-tunnel/cmd/config.go diff --git a/service/ziti-tunnel/cmd/config.go b/service/ziti-tunnel/cmd/config.go new file mode 100644 index 00000000..cd347c20 --- /dev/null +++ b/service/ziti-tunnel/cmd/config.go @@ -0,0 +1,48 @@ +/* +Copyright © 2021 NAME HERE + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package cmd + +import ( + "github.com/openziti/desktop-edge-win/service/ziti-tunnel/cli" + + "github.com/spf13/cobra" +) + +var CIDR string + +// configCmd represents the config command +var configCmd = &cobra.Command{ + Use: "config", + Short: "A brief description of your command", + Long: `A longer description that spans multiple lines and likely contains examples +and usage of using your command. For example: + +Cobra is a CLI library for Go that empowers applications. +This application is a tool to generate the needed files +to quickly create a Cobra application.`, + Run: func(cmd *cobra.Command, args []string) { + flags := map[string]interface{}{} + flags["CIDR"] = CIDR + cli.UpdateConfigIPSubnet(args,flags) + }, +} + +func init() { + rootCmd.AddCommand(configCmd) + + configCmd.Flags().StringVar(&CIDR, "CIDR", "100.64.0.1/10", "Update the cidr value in the config file") + +} From ad2ff23b4fd093d223a7eb1f5d9a6ae3c51be0b3 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Wed, 14 Apr 2021 17:05:40 +0530 Subject: [PATCH 03/36] adding add dns flag to config update function --- service/ziti-tunnel/cli/service.go | 44 ++++++++++++++++-------- service/ziti-tunnel/cmd/config.go | 43 ++++++++++-------------- service/ziti-tunnel/cmd/update.go | 50 ++++++++++++++++++++++++++++ service/ziti-tunnel/service/ipc.go | 32 ++++++++++++++---- service/ziti-tunnel/service/state.go | 35 ++++++++++++++++--- 5 files changed, 154 insertions(+), 50 deletions(-) create mode 100644 service/ziti-tunnel/cmd/update.go diff --git a/service/ziti-tunnel/cli/service.go b/service/ziti-tunnel/cli/service.go index 4e4b04e4..a988b4e4 100644 --- a/service/ziti-tunnel/cli/service.go +++ b/service/ziti-tunnel/cli/service.go @@ -58,19 +58,37 @@ func GetFeedback(args []string, flags map[string]bool) { func UpdateConfigIPSubnet(args []string, flags map[string]interface{}) { CIDRstring := flags["CIDR"] - log.Infof("Updating the config file with IP CIDR %v", flags["CIDR"]) - var cidr = strings.Split(CIDRstring.(string), "/") - if len(cidr) != 2 { - log.Error("Incorrect cidr") - } - ipMask, err := strconv.Atoi(cidr[1]) - if err != nil { - log.Errorf("Incorrect ipv4 mask, %s", cidr[1]) - return - } + AddDns := flags["AddDns"] + log.Info("Updating the config file") + var cidr []string + var ipMask int + var err error + updateTunIpv4Payload := make(map[string]interface{}) - updateTunIpv4Payload["TunIPv4"] = cidr[0] - updateTunIpv4Payload["TunIPv4Mask"] = cidr[1] + if CIDRstring != "" { + cidr = strings.Split(CIDRstring.(string), "/") + if len(cidr) != 2 { + log.Error("Incorrect cidr") + } + ipMask, err = strconv.Atoi(cidr[1]) + if err != nil { + log.Errorf("Incorrect ipv4 mask, %s", cidr[1]) + return + } + updateTunIpv4Payload["TunIPv4"] = cidr[0] + updateTunIpv4Payload["TunIPv4Mask"] = cidr[1] + } + if AddDns != "" { + var addDnsBool bool + addDnsBool, err = strconv.ParseBool(AddDns.(string)) + + if err != nil { + log.Errorf("Incorrect addDns %v", err) + return + } + updateTunIpv4Payload["AddDns"] = addDnsBool + } + UPDATE_TUN_IPV4.Payload = updateTunIpv4Payload log.Debugf("updateTunIpv4 Payload %v", UPDATE_TUN_IPV4) @@ -78,7 +96,7 @@ func UpdateConfigIPSubnet(args []string, flags map[string]interface{}) { if !status { log.Infof("Updating ip and mask in the config file. Manual restart is required") - err = service.UpdateRuntimeStateIpv4(true, cidr[0], ipMask) + err = service.UpdateRuntimeStateIpv4(true, cidr[0], ipMask, AddDns.(string)) if err != nil { log.Errorf("Unable to set Tun ip and mask, %v", err) return diff --git a/service/ziti-tunnel/cmd/config.go b/service/ziti-tunnel/cmd/config.go index cd347c20..81c2ee08 100644 --- a/service/ziti-tunnel/cmd/config.go +++ b/service/ziti-tunnel/cmd/config.go @@ -1,28 +1,26 @@ -/* -Copyright © 2021 NAME HERE - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ package cmd -import ( - "github.com/openziti/desktop-edge-win/service/ziti-tunnel/cli" +/* + * Copyright NetFoundry, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +import ( "github.com/spf13/cobra" ) -var CIDR string - // configCmd represents the config command var configCmd = &cobra.Command{ Use: "config", @@ -34,15 +32,10 @@ Cobra is a CLI library for Go that empowers applications. This application is a tool to generate the needed files to quickly create a Cobra application.`, Run: func(cmd *cobra.Command, args []string) { - flags := map[string]interface{}{} - flags["CIDR"] = CIDR - cli.UpdateConfigIPSubnet(args,flags) + checkHelp() }, } func init() { rootCmd.AddCommand(configCmd) - - configCmd.Flags().StringVar(&CIDR, "CIDR", "100.64.0.1/10", "Update the cidr value in the config file") - } diff --git a/service/ziti-tunnel/cmd/update.go b/service/ziti-tunnel/cmd/update.go new file mode 100644 index 00000000..25d2461c --- /dev/null +++ b/service/ziti-tunnel/cmd/update.go @@ -0,0 +1,50 @@ +package cmd + +/* + * Copyright NetFoundry, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import ( + "github.com/openziti/desktop-edge-win/service/ziti-tunnel/cli" + + "github.com/spf13/cobra" +) + +var CIDR string +var AddDns string + +// updateCmd represents the update command +var updateCmd = &cobra.Command{ + Use: "update", + Short: "Updates data into the ziti-tunnel", + Long: `update command should be used as a sub command to the main command + It helps to update the data into the ziti-tunnel. + eg: ziti-tunnel config update --CIDR 100.64.0.1/10 --AddDns=true`, + Run: func(cmd *cobra.Command, args []string) { + flags := map[string]interface{}{} + flags["CIDR"] = CIDR + flags["AddDns"] = AddDns + cli.UpdateConfigIPSubnet(args,flags) + }, +} + +func init() { + configCmd.AddCommand(updateCmd) + + updateCmd.Flags().StringVar(&CIDR, "CIDR", "", "Updates the cidr property in the config file") + updateCmd.Flags().StringVar(&AddDns, "AddDns", "", "Updates the Add Dns property in the config file") + +} diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index feffc2f4..f3c998de 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -500,7 +500,19 @@ func serveIpc(conn net.Conn) { //save the state rts.SaveState() case "UpdateTunIpv4": - updateTunIpv4(enc, cmd.Payload["TunIPv4"].(string), cmd.Payload["TunIPv4Mask"].(string)) + var tunIPv4 string + var tunIPv4Mask string + var addDns string + if cmd.Payload["TunIPv4"] != nil { + tunIPv4 = cmd.Payload["TunIPv4"].(string) + } + if cmd.Payload["TunIPv4Mask"] != nil { + tunIPv4Mask = cmd.Payload["TunIPv4Mask"].(string) + } + if cmd.Payload["AddDns"] != nil { + addDns = strconv.FormatBool(cmd.Payload["AddDns"].(bool)) + } + updateTunIpv4(enc, tunIPv4, tunIPv4Mask, addDns) case "NotifyLogLevelUIAndUpdateService": sendLogLevelAndNotify(enc, cmd.Payload["Level"].(string)) case "NotifyIdentityUI": @@ -625,13 +637,19 @@ func setLogLevel(out *json.Encoder, level string) { respond(out, dto.Response{Message: "log level set", Code: SUCCESS, Error: "", Payload: nil}) } -func updateTunIpv4(out *json.Encoder, ip string, ipmask string) { - ipMask, err := strconv.Atoi(ipmask) - if err != nil { - respondWithError(out, "Incorrect ipv4 mask", UNKNOWN_ERROR, err) - return +func updateTunIpv4(out *json.Encoder, ip string, ipmask string, addDns string) { + var ipMask int + var err error + if ipmask != "" { + ipMask, err = strconv.Atoi(ipmask) + + if err != nil { + respondWithError(out, "Incorrect ipv4 mask", UNKNOWN_ERROR, err) + return + } } - err = UpdateRuntimeStateIpv4(false, ip, ipMask) + + err = UpdateRuntimeStateIpv4(false, ip, ipMask, addDns) if err != nil { respondWithError(out, "Could not set Tun ip and mask", UNKNOWN_ERROR, err) return diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index 7d68e1be..6557de96 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -31,6 +31,7 @@ import ( "time" "path/filepath" "errors" + "strconv" "github.com/openziti/desktop-edge-win/service/cziti" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/config" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/constants" @@ -454,10 +455,20 @@ func (t *RuntimeState) UpdateIpv4(ipv4 string) { rts.SaveState() } -func UpdateRuntimeStateIpv4(offline bool, ip string, ipv4Mask int) error { +func UpdateRuntimeStateIpv4(offline bool, ip string, ipv4Mask int, addDns string) error { log.Infof("ip and mask %s %d", ip, ipv4Mask) + var addDnsBool bool + var err error + if addDns != "" { + addDnsBool, err = strconv.ParseBool(addDns) + + if err != nil { + return errors.New(fmt.Sprintf("Incorrect addDns %v", err)) + } + } + if offline { systemDrivePath := os.Getenv("SystemDrive") if systemDrivePath == "" { @@ -471,14 +482,28 @@ func UpdateRuntimeStateIpv4(offline bool, ip string, ipv4Mask int) error { return err } - rts.state.TunIpv4 = ip - rts.state.TunIpv4Mask = ipv4Mask + // if ip is not empty, then we set both ip and mask + if ip != "" { + rts.state.TunIpv4 = ip + rts.state.TunIpv4Mask = ipv4Mask + } + if addDns != "" { + rts.state.AddDns = addDnsBool + } rts.SaveStateWithPath(systemPath) } else { - rts.state.TunIpv4 = ip - rts.state.TunIpv4Mask = ipv4Mask + + // if ip is not empty, then we set both ip and mask + if ip != "" { + rts.state.TunIpv4 = ip + rts.state.TunIpv4Mask = ipv4Mask + } + if addDns != "" { + rts.state.AddDns = addDnsBool + } + rts.SaveState() } From bd64b2e083fd8cb2c235d369b8afaf59ad91d8d2 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Wed, 14 Apr 2021 17:26:55 +0530 Subject: [PATCH 04/36] fixing fatal error --- service/ziti-tunnel/cli/ipcClient.go | 2 +- service/ziti-tunnel/cli/service.go | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/service/ziti-tunnel/cli/ipcClient.go b/service/ziti-tunnel/cli/ipcClient.go index 50a87b94..a042ef92 100644 --- a/service/ziti-tunnel/cli/ipcClient.go +++ b/service/ziti-tunnel/cli/ipcClient.go @@ -144,7 +144,7 @@ func GetDataFromIpcPipe(commandMsg *dto.CommandMsg, fn fetchStatusFromRTS, respo if err != nil { log.Errorf("Connection to ipc pipe is not established, %v", err) - log.Fatal("Ziti Desktop Edge app may not be running") + log.Errorf("Ziti Desktop Edge app may not be running") return false } readDone := make(chan bool) diff --git a/service/ziti-tunnel/cli/service.go b/service/ziti-tunnel/cli/service.go index a988b4e4..242ec967 100644 --- a/service/ziti-tunnel/cli/service.go +++ b/service/ziti-tunnel/cli/service.go @@ -96,7 +96,11 @@ func UpdateConfigIPSubnet(args []string, flags map[string]interface{}) { if !status { log.Infof("Updating ip and mask in the config file. Manual restart is required") - err = service.UpdateRuntimeStateIpv4(true, cidr[0], ipMask, AddDns.(string)) + var tunIpv4 string + if len(cidr) == 2 { + tunIpv4 = cidr[0] + } + err = service.UpdateRuntimeStateIpv4(true, tunIpv4, ipMask, AddDns.(string)) if err != nil { log.Errorf("Unable to set Tun ip and mask, %v", err) return From db181acaa17e32d5fe35fbc1b6987dded2b18560 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Thu, 15 Apr 2021 15:37:35 +0530 Subject: [PATCH 05/36] accept mask as int value --- .../DataStructures/DataStructures.cs | 23 ++++++++++++++++++ .../ServiceClient/DataClient.cs | 24 +++++++++++++++++++ service/ziti-tunnel/cli/service.go | 2 +- service/ziti-tunnel/service/ipc.go | 19 ++++----------- 4 files changed, 53 insertions(+), 15 deletions(-) diff --git a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs index c64191bc..5936e0c0 100644 --- a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs +++ b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs @@ -459,4 +459,27 @@ namespace ZitiDesktopEdge.DataStructures { public class MfaRecoveryCodesResponse : SvcResponse { public string[] Payload { get; set; } } + + public class ConfigPayload + { + public string TunIPv4 { get; set; } + public int TunIPv4Mask { get; set; } + public bool AddDns { get; set; } + } + + public class ConfigUpdateFunction : ServiceFunction + { + public ConfigUpdateFunction(string tunIPv4, int tunIPv4Mask, bool addDns) + { + this.Function = "UpdateTunIpv4"; + this.Payload = new ConfigPayload() + { + TunIPv4 = tunIPv4, + TunIPv4Mask = tunIPv4Mask, + AddDns = addDns + }; + } + public ConfigPayload Payload { get; set; } + } + } diff --git a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs index af87b68d..cc1f0695 100644 --- a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs +++ b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs @@ -390,6 +390,30 @@ namespace ZitiDesktopEdge.ServiceClient { return; } + async public Task UpdateConfigAsync(string tunIPv4, int tunIPv4Mask, bool addDns) { + SvcResponse resp = null; + try { + + ConfigUpdateFunction configPayload = new ConfigUpdateFunction(tunIPv4, tunIPv4Mask, addDns); + + await sendAsync(configPayload); + resp = await readAsync(ipcReader); + Logger.Debug("config update payload is sent to the ziti tunnel"); + } catch (Exception ex) { + //almost certainly a problem with the pipe - recreate the pipe... + //setupPipe(); + //throw; + Logger.Error(ex, "Unexpected error"); + CommunicationError(ex); + throw ex; + } + if (resp?.Code != 0) { + Logger.Warn("failed to update the config. {0} {1}", resp.Message, resp.Error); + throw new ServiceException("Failed to update the config", resp.Code, "Un expected error."); + } + return resp; + } + async public Task debugAsync() { try { await sendAsync(new ServiceFunction() { Function = "Debug" }); diff --git a/service/ziti-tunnel/cli/service.go b/service/ziti-tunnel/cli/service.go index 242ec967..52b4649c 100644 --- a/service/ziti-tunnel/cli/service.go +++ b/service/ziti-tunnel/cli/service.go @@ -76,7 +76,7 @@ func UpdateConfigIPSubnet(args []string, flags map[string]interface{}) { return } updateTunIpv4Payload["TunIPv4"] = cidr[0] - updateTunIpv4Payload["TunIPv4Mask"] = cidr[1] + updateTunIpv4Payload["TunIPv4Mask"] = ipMask } if AddDns != "" { var addDnsBool bool diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index f3c998de..9c20fcc4 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -501,13 +501,14 @@ func serveIpc(conn net.Conn) { rts.SaveState() case "UpdateTunIpv4": var tunIPv4 string - var tunIPv4Mask string + var tunIPv4Mask int var addDns string if cmd.Payload["TunIPv4"] != nil { tunIPv4 = cmd.Payload["TunIPv4"].(string) } if cmd.Payload["TunIPv4Mask"] != nil { - tunIPv4Mask = cmd.Payload["TunIPv4Mask"].(string) + var tunIpv4Mask = cmd.Payload["TunIPv4Mask"].(float64) + tunIPv4Mask = int(tunIpv4Mask) } if cmd.Payload["AddDns"] != nil { addDns = strconv.FormatBool(cmd.Payload["AddDns"].(bool)) @@ -637,19 +638,9 @@ func setLogLevel(out *json.Encoder, level string) { respond(out, dto.Response{Message: "log level set", Code: SUCCESS, Error: "", Payload: nil}) } -func updateTunIpv4(out *json.Encoder, ip string, ipmask string, addDns string) { - var ipMask int - var err error - if ipmask != "" { - ipMask, err = strconv.Atoi(ipmask) +func updateTunIpv4(out *json.Encoder, ip string, ipMask int, addDns string) { - if err != nil { - respondWithError(out, "Incorrect ipv4 mask", UNKNOWN_ERROR, err) - return - } - } - - err = UpdateRuntimeStateIpv4(false, ip, ipMask, addDns) + err := UpdateRuntimeStateIpv4(false, ip, ipMask, addDns) if err != nil { respondWithError(out, "Could not set Tun ip and mask", UNKNOWN_ERROR, err) return From 281876d001af281c606d8a6476ab02b4911efaf9 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Thu, 15 Apr 2021 19:39:07 +0530 Subject: [PATCH 06/36] remove the offline update config option --- DesktopEdge/Views/Screens/MainMenu.xaml | 15 ++++ DesktopEdge/Views/Screens/MainMenu.xaml.cs | 17 ++++ service/ziti-tunnel/cli/ipcClient.go | 2 +- service/ziti-tunnel/cli/service.go | 45 ++++------ service/ziti-tunnel/main.go | 2 +- service/ziti-tunnel/service/ipc.go | 4 +- service/ziti-tunnel/service/state.go | 100 +++------------------ 7 files changed, 65 insertions(+), 120 deletions(-) diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml b/DesktopEdge/Views/Screens/MainMenu.xaml index d3a8286a..0961caf4 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml +++ b/DesktopEdge/Views/Screens/MainMenu.xaml @@ -93,6 +93,21 @@ + + + + + + + + + diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml.cs b/DesktopEdge/Views/Screens/MainMenu.xaml.cs index aeb5726e..d85a9b7a 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml.cs +++ b/DesktopEdge/Views/Screens/MainMenu.xaml.cs @@ -424,6 +424,23 @@ namespace ZitiDesktopEdge { CheckForUpdate.IsEnabled = true; } + async private void UpdateConfig_Click(object sender, RoutedEventArgs e) { + logger.Info("updating config..."); + DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; + try { + var newMaskVar = Int32.Parse(ConfigMaskNew.Text); + var addDnsNewVar = Convert.ToBoolean(AddDnsNew.Text); + + var r = await client.UpdateConfigAsync(ConfigIpNew.Text, newMaskVar, addDnsNewVar); + logger.Info("Got response from update config task : {0}", r); + } catch (DataStructures.ServiceException se) { + logger.Error(se, "service exception in update check: {0}", se.Message); + } + catch (Exception ex) { + logger.Error(ex, "unexpected error in update check: {0}", ex.Message); + } + } + async private void TriggerUpdate_Click(object sender, RoutedEventArgs e) { try { CheckForUpdate.IsEnabled = false; diff --git a/service/ziti-tunnel/cli/ipcClient.go b/service/ziti-tunnel/cli/ipcClient.go index a042ef92..50a87b94 100644 --- a/service/ziti-tunnel/cli/ipcClient.go +++ b/service/ziti-tunnel/cli/ipcClient.go @@ -144,7 +144,7 @@ func GetDataFromIpcPipe(commandMsg *dto.CommandMsg, fn fetchStatusFromRTS, respo if err != nil { log.Errorf("Connection to ipc pipe is not established, %v", err) - log.Errorf("Ziti Desktop Edge app may not be running") + log.Fatal("Ziti Desktop Edge app may not be running") return false } readDone := make(chan bool) diff --git a/service/ziti-tunnel/cli/service.go b/service/ziti-tunnel/cli/service.go index 52b4649c..be81a09a 100644 --- a/service/ziti-tunnel/cli/service.go +++ b/service/ziti-tunnel/cli/service.go @@ -1,11 +1,26 @@ package cli +/* + * Copyright NetFoundry, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + import ( "strings" "strconv" - "golang.org/x/sys/windows/svc" "github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto" - "github.com/openziti/desktop-edge-win/service/ziti-tunnel/service" ) //GetIdentities is to fetch identities through cmdline @@ -95,31 +110,7 @@ func UpdateConfigIPSubnet(args []string, flags map[string]interface{}) { status := GetDataFromIpcPipe(&UPDATE_TUN_IPV4, nil, GetResponseObjectFromRTS, args, nil) if !status { - log.Infof("Updating ip and mask in the config file. Manual restart is required") - var tunIpv4 string - if len(cidr) == 2 { - tunIpv4 = cidr[0] - } - err = service.UpdateRuntimeStateIpv4(true, tunIpv4, ipMask, AddDns.(string)) - if err != nil { - log.Errorf("Unable to set Tun ip and mask, %v", err) - return - } - log.Infof("ip and mask are set") - } - - if status { - log.Infof("Attempting to restart ziti ") - - err = service.ControlService(svc.Stop, svc.Stopped) - if (err != nil) { - log.Errorf("Unable to stop the service, %v", err) - return - } - err = service.StartService() - if (err != nil) { - log.Errorf("Unable to start the service, %v", err) - } + log.Infof("Config can be updated only if the tunnel is started") } } diff --git a/service/ziti-tunnel/main.go b/service/ziti-tunnel/main.go index e765ea59..1b5a51db 100644 --- a/service/ziti-tunnel/main.go +++ b/service/ziti-tunnel/main.go @@ -128,7 +128,7 @@ func usage(errmsg string) { "%s\n\n"+ "usage: %s \n"+ " where is one of\n"+ - " install, remove, debug, start, stop, pause, continue, list, identity, loglevel, feedback or version.\n", + " install, remove, debug, start, stop, pause, continue, list, identity, loglevel, feedback, config or version.\n", errmsg, os.Args[0]) os.Exit(2) } diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 9c20fcc4..d2343c10 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -640,13 +640,13 @@ func setLogLevel(out *json.Encoder, level string) { func updateTunIpv4(out *json.Encoder, ip string, ipMask int, addDns string) { - err := UpdateRuntimeStateIpv4(false, ip, ipMask, addDns) + err := UpdateRuntimeStateIpv4(ip, ipMask, addDns) if err != nil { respondWithError(out, "Could not set Tun ip and mask", UNKNOWN_ERROR, err) return } - respond(out, dto.Response{Message: "TunIPv4 and mask is set", Code: SUCCESS, Error: "", Payload: ""}) + respond(out, dto.Response{Message: "TunIPv4 and mask is set, Manual Restart is required", Code: SUCCESS, Error: "", Payload: ""}) } func serveLogs(conn net.Conn) { diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index 6557de96..ff2b9e15 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -29,7 +29,6 @@ import ( "path" "strings" "time" - "path/filepath" "errors" "strconv" "github.com/openziti/desktop-edge-win/service/cziti" @@ -109,57 +108,6 @@ func backupConfig() (string, error) { } -func (t *RuntimeState) SaveStateWithPath(systemPath string) { - // overwrite file if it exists - _ = os.MkdirAll(systemPath, 0644) - - log.Debugf("backing up config") - backup, err := backupConfigWithPath(systemPath) - if err != nil { - log.Warnf("could not backup config file! %v", err) - } else { - log.Debugf("config file backed up to: %s", backup) - } - - cfg, err := os.OpenFile(filepath.Join(systemPath, string(os.PathSeparator), "config.json"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) - defer cfg.Close() - if err != nil { - log.Panicf("An unexpected and unrecoverable error has occurred while %s: %v", "opening the config file", err) - } - - w := bufio.NewWriter(bufio.NewWriter(cfg)) - enc := json.NewEncoder(w) - enc.SetIndent("", " ") - _ = enc.Encode(t.state) - _ = w.Flush() - - err = cfg.Close() - if err != nil { - log.Panicf("An unexpected and unrecoverable error has occurred while %s: %v", "closing the config file", err) - } - log.Debug("state saved") -} - -func backupConfigWithPath(systemPath string) (string, error) { - original, err := os.Open(filepath.Join(systemPath, string(os.PathSeparator), "config.json")) - if err != nil { - return "", err - } - defer original.Close() - backup := filepath.Join(systemPath, string(os.PathSeparator), "config.json.backup") - new, err := os.Create(backup) - if err != nil { - return "", err - } - defer new.Close() - - _, err = io.Copy(new, original) - if err != nil { - return "", err - } - return backup, err -} - func (t *RuntimeState) ToStatus(onlyInitialized bool) dto.TunnelStatus { var uptime int64 @@ -455,7 +403,7 @@ func (t *RuntimeState) UpdateIpv4(ipv4 string) { rts.SaveState() } -func UpdateRuntimeStateIpv4(offline bool, ip string, ipv4Mask int, addDns string) error { +func UpdateRuntimeStateIpv4(ip string, ipv4Mask int, addDns string) error { log.Infof("ip and mask %s %d", ip, ipv4Mask) @@ -469,43 +417,17 @@ func UpdateRuntimeStateIpv4(offline bool, ip string, ipv4Mask int, addDns string } } - if offline { - systemDrivePath := os.Getenv("SystemDrive") - if systemDrivePath == "" { - return errors.New("SystemDrive env is not found") - } - configPath := "Windows\\System32\\config\\systemprofile\\AppData\\Roaming\\NetFoundry" - systemPath := filepath.Join(systemDrivePath, string(os.PathSeparator), configPath) - err := readConfig(rts, filepath.Join(systemPath, string(os.PathSeparator), "config.json")) - if (err != nil) { - log.Errorf("Unable to read the config file, %v", err) - return err - } - - // if ip is not empty, then we set both ip and mask - if ip != "" { - rts.state.TunIpv4 = ip - rts.state.TunIpv4Mask = ipv4Mask - } - if addDns != "" { - rts.state.AddDns = addDnsBool - } - - rts.SaveStateWithPath(systemPath) - - } else { - - // if ip is not empty, then we set both ip and mask - if ip != "" { - rts.state.TunIpv4 = ip - rts.state.TunIpv4Mask = ipv4Mask - } - if addDns != "" { - rts.state.AddDns = addDnsBool - } - - rts.SaveState() + // if ip is not empty, then we set both ip and mask + if ip != "" { + rts.state.TunIpv4 = ip + rts.state.TunIpv4Mask = ipv4Mask } + if addDns != "" { + rts.state.AddDns = addDnsBool + } + + rts.SaveState() + return nil } From aebd5226a37fd24037594ae048731679eccd6545 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Thu, 15 Apr 2021 19:50:16 +0530 Subject: [PATCH 07/36] update the version --- release-notes.md | 12 +++++------- version | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/release-notes.md b/release-notes.md index 67b66a3f..821b8fc0 100644 --- a/release-notes.md +++ b/release-notes.md @@ -1,16 +1,13 @@ -# Release 1.9.3 +# Release 1.9.4 ## What's New -* Page Service List -* Sort Service on Identity Details Page -* Consistent UX for MFA Screens +* none ## 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 +* none ## Bugs fixed: -* none +* [#362](https://github.com/openziti/desktop-edge-win/issues/362) Update tun ip, mask and addDns flag ## Dependency Updates * none @@ -24,6 +21,7 @@ ## 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 diff --git a/version b/version index 77fee73a..d615fd0c 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.9.3 +1.9.4 From 77ed580f759adbfe84635a3bb330139f69a9a659 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Thu, 15 Apr 2021 20:01:24 +0530 Subject: [PATCH 08/36] formatting code --- service/ziti-tunnel/cli/constants.go | 118 ++--- service/ziti-tunnel/cli/responseGenerator.go | 485 +++++++++---------- service/ziti-tunnel/cli/service.go | 233 +++++---- 3 files changed, 417 insertions(+), 419 deletions(-) diff --git a/service/ziti-tunnel/cli/constants.go b/service/ziti-tunnel/cli/constants.go index e6e49187..150d45af 100644 --- a/service/ziti-tunnel/cli/constants.go +++ b/service/ziti-tunnel/cli/constants.go @@ -1,59 +1,59 @@ -package cli - -/* - * Copyright NetFoundry, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import ( - "github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto" - "github.com/openziti/desktop-edge-win/service/ziti-tunnel/util/logging" -) - -var GET_STATUS = dto.CommandMsg{ - Function: "Status", -} - -var ONOFF_IDENTITY = dto.CommandMsg{ - Function: "IdentityOnOff", -} - -var SET_LOGLEVEL = dto.CommandMsg{ - Function: "SetLogLevel", -} - -var NOTIFY_LOGLEVEL_UI_MONITOR = dto.CommandMsg{ - Function: "NotifyLogLevelUIAndUpdateService", -} - -var NOTIFY_IDENTITY_UI = dto.CommandMsg{ - Function: "NotifyIdentityUI", -} - -var UPDATE_TUN_IPV4 = dto.CommandMsg{ - Function: "UpdateTunIpv4", -} - -var monitorIpcPipe = `\\.\pipe\OpenZiti\ziti-monitor\ipc` - -var templateIdentity = `{{printf "%40s" "Name"}} | {{printf "%41s" "FingerPrint"}} | {{printf "%6s" "Active"}} | {{printf "%30s" "Config"}} | {{"Status"}} -{{range .}}{{printf "%40s" .Name}} | {{printf "%41s" .FingerPrint}} | {{printf "%6t" .Active}} | {{printf "%30s" .Config}} | {{.Status}} -{{end}}` - -var templateService = `{{printf "%40s" "Name"}} | {{printf "%15s" "Id"}} | {{printf "%9s" "Protocols"}} | {{printf "%14s" "Ports"}} | {{printf "%60s" "Addresses"}} -{{range .}}{{printf "%40s" .Name}} | {{printf "%15s" .Id}} | {{printf "%9s" .Protocols}} | {{printf "%14s" .Ports}} | {{printf "%60s" .Addresses}} -{{end}}` - -var log = logging.Logger() +package cli + +/* + * Copyright NetFoundry, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import ( + "github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto" + "github.com/openziti/desktop-edge-win/service/ziti-tunnel/util/logging" +) + +var GET_STATUS = dto.CommandMsg{ + Function: "Status", +} + +var ONOFF_IDENTITY = dto.CommandMsg{ + Function: "IdentityOnOff", +} + +var SET_LOGLEVEL = dto.CommandMsg{ + Function: "SetLogLevel", +} + +var NOTIFY_LOGLEVEL_UI_MONITOR = dto.CommandMsg{ + Function: "NotifyLogLevelUIAndUpdateService", +} + +var NOTIFY_IDENTITY_UI = dto.CommandMsg{ + Function: "NotifyIdentityUI", +} + +var UPDATE_TUN_IPV4 = dto.CommandMsg{ + Function: "UpdateTunIpv4", +} + +var monitorIpcPipe = `\\.\pipe\OpenZiti\ziti-monitor\ipc` + +var templateIdentity = `{{printf "%40s" "Name"}} | {{printf "%41s" "FingerPrint"}} | {{printf "%6s" "Active"}} | {{printf "%30s" "Config"}} | {{"Status"}} +{{range .}}{{printf "%40s" .Name}} | {{printf "%41s" .FingerPrint}} | {{printf "%6t" .Active}} | {{printf "%30s" .Config}} | {{.Status}} +{{end}}` + +var templateService = `{{printf "%40s" "Name"}} | {{printf "%15s" "Id"}} | {{printf "%9s" "Protocols"}} | {{printf "%14s" "Ports"}} | {{printf "%60s" "Addresses"}} +{{range .}}{{printf "%40s" .Name}} | {{printf "%15s" .Id}} | {{printf "%9s" .Protocols}} | {{printf "%14s" .Ports}} | {{printf "%60s" .Addresses}} +{{end}}` + +var log = logging.Logger() diff --git a/service/ziti-tunnel/cli/responseGenerator.go b/service/ziti-tunnel/cli/responseGenerator.go index e736c7f4..2b19d6ad 100644 --- a/service/ziti-tunnel/cli/responseGenerator.go +++ b/service/ziti-tunnel/cli/responseGenerator.go @@ -1,243 +1,242 @@ -package cli - -/* - * Copyright NetFoundry, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import ( - "bytes" - "encoding/json" - "fmt" - "strings" - "text/template" - - "github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto" - "github.com/openziti/desktop-edge-win/service/ziti-tunnel/service" -) - -func convertToIdentityCli(id *dto.Identity) dto.IdentityCli { - return dto.IdentityCli{ - Name: id.Name, - FingerPrint: id.FingerPrint, - Active: id.Active, - Config: id.Config.ZtAPI, - Status: id.Status, - } -} - -func convertToServiceCli(svc dto.Service) dto.ServiceCli { - cliPorts := "" - for _, val := range svc.Ports { - if len(cliPorts) != 0 { - cliPorts = fmt.Sprintf("%s, %d-%d", cliPorts, val.Low, val.High) - } else { - cliPorts = fmt.Sprintf("%d-%d", val.Low, val.High) - } - } - cliAddresses := "" - for _, val := range svc.Addresses { - if len(cliAddresses) != 0 { - cliAddresses = cliAddresses + ", " + val.HostName + "/" + val.IP - } else { - cliAddresses = val.HostName + "/" + val.IP - } - } - - return dto.ServiceCli{ - Name: svc.Name, - Id: svc.Id, - Protocols: strings.Join(svc.Protocols, ","), - Ports: cliPorts, - Addresses: cliAddresses, - } -} - -// GetIdentitiesFromRTS is to get identities from the RTS -func GetIdentitiesFromRTS(args []string, status *dto.TunnelStatus, flags map[string]bool) dto.Response { - - var filteredIdentities []dto.IdentityCli - - if flags["services"] { - return filterServicesByIdentity(args, status, flags) - } - - for _, val := range args { - if val == "all" { - for _, id := range status.Identities { - filteredIdentities = append(filteredIdentities, convertToIdentityCli(id)) - } - break - } else { - for _, id := range status.Identities { - if strings.Compare(id.Name, val) == 0 { - filteredIdentities = append(filteredIdentities, convertToIdentityCli(id)) - } - } - } - } - - if len(filteredIdentities) == 0 { - errMsg := fmt.Sprintf("Could not find identities matching %s", args) - return dto.Response{Message: "", Code: service.ERROR, Error: errMsg, Payload: nil} - } - message := fmt.Sprintf("Got %d identities - %s", len(filteredIdentities), args) - return generateResponse("identities", message, filteredIdentities, flags, templateIdentity) -} - -func filterServicesByIdentity(identity []string, status *dto.TunnelStatus, flags map[string]bool) dto.Response { - var filteredServices []dto.ServiceCli - - for _, id := range status.Identities { - for _, filterID := range identity { - if (filterID == "all" || id.Name == filterID) && len(id.Services) > 0 { - for _, svc := range id.Services { - filteredServices = append(filteredServices, convertToServiceCli(*svc)) - } - // if the filterId array has all or matching string, then fetch all the services and break from the filter loop - break - } - } - - } - - if len(filteredServices) == 0 { - errMsg := fmt.Sprintf("Could not find services for identity %s", identity) - return dto.Response{Message: "", Code: service.ERROR, Error: errMsg, Payload: nil} - } - message := fmt.Sprintf("Got %d services for identity - %s", len(filteredServices), identity) - return generateResponse("services", message, filteredServices, flags, templateService) - -} - -func GetServicesFromRTS(args []string, status *dto.TunnelStatus, flags map[string]bool) dto.Response { - - var filteredServices []dto.ServiceCli - - for _, val := range args { - if val == "all" { - for _, id := range status.Identities { - if len(id.Services) > 0 { - for _, svc := range id.Services { - filteredServices = append(filteredServices, convertToServiceCli(*svc)) - } - } - } - break - } else { - for _, id := range status.Identities { - if len(id.Services) > 0 { - for _, svc := range id.Services { - if strings.Compare(val, svc.Name) == 0 { - filteredServices = append(filteredServices, convertToServiceCli(*svc)) - } - } - } - } - } - } - - if len(filteredServices) == 0 { - errMsg := fmt.Sprintf("Could not find services matching %s", args) - return dto.Response{Message: "", Code: service.ERROR, Error: errMsg, Payload: nil} - } - message := fmt.Sprintf("Got %d services - %s", len(filteredServices), args) - - return generateResponse("services", message, filteredServices, flags, templateService) - -} - -func generateResponse(dataType string, message string, filteredData interface{}, flags map[string]bool, templateStr string) dto.Response { - - var bytesData []byte - var err error - var responseBuffer bytes.Buffer - var responseStr string - - if flags["prettyJSON"] == true { - bytesData, err = json.MarshalIndent(filteredData, "", " ") - - if err != nil { - log.Error(err) - return dto.Response{Message: message, Code: service.ERROR, Error: "Could not fetch " + dataType + " from Runtime", Payload: nil} - } - responseStr = string(bytesData) - - } else { - it, err := template.New("filteredData").Parse(templateStr) - - if err != nil { - log.Error(err) - return dto.Response{Message: message, Code: service.ERROR, Error: "Could not parse " + dataType + " from Runtime", Payload: nil} - } - - err = it.Execute(&responseBuffer, filteredData) - - if err != nil { - log.Error(err) - return dto.Response{Message: message, Code: service.ERROR, Error: "Could not print " + dataType + " from Runtime", Payload: nil} - } - responseStr = responseBuffer.String() - } - - return dto.Response{Message: message, Code: service.SUCCESS, Error: "", Payload: responseStr} -} - -func GetLogLevelFromRTS(args []string, status *dto.TunnelStatus, flags map[string]bool) dto.Response { - - if flags["query"] == true { - message := fmt.Sprintf("Loglevel is currently set to %s", status.LogLevel) - return dto.Response{Message: message, Code: service.SUCCESS, Error: "", Payload: ""} - } - errMsg := fmt.Sprintf("Unknown error: args %s flag %v", args, flags) - return dto.Response{Message: "", Code: service.ERROR, Error: errMsg, Payload: ""} - -} - -// GetIdentityResponseObjectFromRTS is to get identity info from the RTS -func GetIdentityResponseObjectFromRTS(args []string, status dto.Response, flags map[string]bool) dto.Response { - log.Debugf("Message from ziti-tunnel : %v", status.Message) - if status.Error == "" && status.Payload != nil { - log.Debugf("Payload from RTS %v", status.Payload) - payloadData := status.Payload.(map[string]interface{}) - identityStatus := make(map[string]interface{}) - identityStatus["FingerPrint"] = payloadData["FingerPrint"] - identityStatus["Active"] = payloadData["Active"] - identityStatus["Name"] = payloadData["Name"] - return dto.Response{Message: status.Message, Code: service.SUCCESS, Error: "", Payload: identityStatus} - } else { - return status - } -} - -// GetResponseObjectFromRTS is to get response object info from the RTS -func GetResponseObjectFromRTS(args []string, status dto.Response, flags map[string]bool) dto.Response { - return status -} - -func GetStatusFromRTS(args []string, status *dto.TunnelStatus, flags map[string]bool) dto.Response { - - if status == nil { - return dto.Response{Message: "Stopped / Unknown State", Code: service.SUCCESS, Error: "", Payload: ""} - } - - if status.Active { - return dto.Response{Message: "Running", Code: service.SUCCESS, Error: "", Payload: ""} - } else { - return dto.Response{Message: "Stopped", Code: service.SUCCESS, Error: "", Payload: ""} - } - -} - +package cli + +/* + * Copyright NetFoundry, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "text/template" + + "github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto" + "github.com/openziti/desktop-edge-win/service/ziti-tunnel/service" +) + +func convertToIdentityCli(id *dto.Identity) dto.IdentityCli { + return dto.IdentityCli{ + Name: id.Name, + FingerPrint: id.FingerPrint, + Active: id.Active, + Config: id.Config.ZtAPI, + Status: id.Status, + } +} + +func convertToServiceCli(svc dto.Service) dto.ServiceCli { + cliPorts := "" + for _, val := range svc.Ports { + if len(cliPorts) != 0 { + cliPorts = fmt.Sprintf("%s, %d-%d", cliPorts, val.Low, val.High) + } else { + cliPorts = fmt.Sprintf("%d-%d", val.Low, val.High) + } + } + cliAddresses := "" + for _, val := range svc.Addresses { + if len(cliAddresses) != 0 { + cliAddresses = cliAddresses + ", " + val.HostName + "/" + val.IP + } else { + cliAddresses = val.HostName + "/" + val.IP + } + } + + return dto.ServiceCli{ + Name: svc.Name, + Id: svc.Id, + Protocols: strings.Join(svc.Protocols, ","), + Ports: cliPorts, + Addresses: cliAddresses, + } +} + +// GetIdentitiesFromRTS is to get identities from the RTS +func GetIdentitiesFromRTS(args []string, status *dto.TunnelStatus, flags map[string]bool) dto.Response { + + var filteredIdentities []dto.IdentityCli + + if flags["services"] { + return filterServicesByIdentity(args, status, flags) + } + + for _, val := range args { + if val == "all" { + for _, id := range status.Identities { + filteredIdentities = append(filteredIdentities, convertToIdentityCli(id)) + } + break + } else { + for _, id := range status.Identities { + if strings.Compare(id.Name, val) == 0 { + filteredIdentities = append(filteredIdentities, convertToIdentityCli(id)) + } + } + } + } + + if len(filteredIdentities) == 0 { + errMsg := fmt.Sprintf("Could not find identities matching %s", args) + return dto.Response{Message: "", Code: service.ERROR, Error: errMsg, Payload: nil} + } + message := fmt.Sprintf("Got %d identities - %s", len(filteredIdentities), args) + return generateResponse("identities", message, filteredIdentities, flags, templateIdentity) +} + +func filterServicesByIdentity(identity []string, status *dto.TunnelStatus, flags map[string]bool) dto.Response { + var filteredServices []dto.ServiceCli + + for _, id := range status.Identities { + for _, filterID := range identity { + if (filterID == "all" || id.Name == filterID) && len(id.Services) > 0 { + for _, svc := range id.Services { + filteredServices = append(filteredServices, convertToServiceCli(*svc)) + } + // if the filterId array has all or matching string, then fetch all the services and break from the filter loop + break + } + } + + } + + if len(filteredServices) == 0 { + errMsg := fmt.Sprintf("Could not find services for identity %s", identity) + return dto.Response{Message: "", Code: service.ERROR, Error: errMsg, Payload: nil} + } + message := fmt.Sprintf("Got %d services for identity - %s", len(filteredServices), identity) + return generateResponse("services", message, filteredServices, flags, templateService) + +} + +func GetServicesFromRTS(args []string, status *dto.TunnelStatus, flags map[string]bool) dto.Response { + + var filteredServices []dto.ServiceCli + + for _, val := range args { + if val == "all" { + for _, id := range status.Identities { + if len(id.Services) > 0 { + for _, svc := range id.Services { + filteredServices = append(filteredServices, convertToServiceCli(*svc)) + } + } + } + break + } else { + for _, id := range status.Identities { + if len(id.Services) > 0 { + for _, svc := range id.Services { + if strings.Compare(val, svc.Name) == 0 { + filteredServices = append(filteredServices, convertToServiceCli(*svc)) + } + } + } + } + } + } + + if len(filteredServices) == 0 { + errMsg := fmt.Sprintf("Could not find services matching %s", args) + return dto.Response{Message: "", Code: service.ERROR, Error: errMsg, Payload: nil} + } + message := fmt.Sprintf("Got %d services - %s", len(filteredServices), args) + + return generateResponse("services", message, filteredServices, flags, templateService) + +} + +func generateResponse(dataType string, message string, filteredData interface{}, flags map[string]bool, templateStr string) dto.Response { + + var bytesData []byte + var err error + var responseBuffer bytes.Buffer + var responseStr string + + if flags["prettyJSON"] == true { + bytesData, err = json.MarshalIndent(filteredData, "", " ") + + if err != nil { + log.Error(err) + return dto.Response{Message: message, Code: service.ERROR, Error: "Could not fetch " + dataType + " from Runtime", Payload: nil} + } + responseStr = string(bytesData) + + } else { + it, err := template.New("filteredData").Parse(templateStr) + + if err != nil { + log.Error(err) + return dto.Response{Message: message, Code: service.ERROR, Error: "Could not parse " + dataType + " from Runtime", Payload: nil} + } + + err = it.Execute(&responseBuffer, filteredData) + + if err != nil { + log.Error(err) + return dto.Response{Message: message, Code: service.ERROR, Error: "Could not print " + dataType + " from Runtime", Payload: nil} + } + responseStr = responseBuffer.String() + } + + return dto.Response{Message: message, Code: service.SUCCESS, Error: "", Payload: responseStr} +} + +func GetLogLevelFromRTS(args []string, status *dto.TunnelStatus, flags map[string]bool) dto.Response { + + if flags["query"] == true { + message := fmt.Sprintf("Loglevel is currently set to %s", status.LogLevel) + return dto.Response{Message: message, Code: service.SUCCESS, Error: "", Payload: ""} + } + errMsg := fmt.Sprintf("Unknown error: args %s flag %v", args, flags) + return dto.Response{Message: "", Code: service.ERROR, Error: errMsg, Payload: ""} + +} + +// GetIdentityResponseObjectFromRTS is to get identity info from the RTS +func GetIdentityResponseObjectFromRTS(args []string, status dto.Response, flags map[string]bool) dto.Response { + log.Debugf("Message from ziti-tunnel : %v", status.Message) + if status.Error == "" && status.Payload != nil { + log.Debugf("Payload from RTS %v", status.Payload) + payloadData := status.Payload.(map[string]interface{}) + identityStatus := make(map[string]interface{}) + identityStatus["FingerPrint"] = payloadData["FingerPrint"] + identityStatus["Active"] = payloadData["Active"] + identityStatus["Name"] = payloadData["Name"] + return dto.Response{Message: status.Message, Code: service.SUCCESS, Error: "", Payload: identityStatus} + } else { + return status + } +} + +// GetResponseObjectFromRTS is to get response object info from the RTS +func GetResponseObjectFromRTS(args []string, status dto.Response, flags map[string]bool) dto.Response { + return status +} + +func GetStatusFromRTS(args []string, status *dto.TunnelStatus, flags map[string]bool) dto.Response { + + if status == nil { + return dto.Response{Message: "Stopped / Unknown State", Code: service.SUCCESS, Error: "", Payload: ""} + } + + if status.Active { + return dto.Response{Message: "Running", Code: service.SUCCESS, Error: "", Payload: ""} + } else { + return dto.Response{Message: "Stopped", Code: service.SUCCESS, Error: "", Payload: ""} + } + +} diff --git a/service/ziti-tunnel/cli/service.go b/service/ziti-tunnel/cli/service.go index be81a09a..3b9a9e03 100644 --- a/service/ziti-tunnel/cli/service.go +++ b/service/ziti-tunnel/cli/service.go @@ -1,117 +1,116 @@ -package cli - -/* - * Copyright NetFoundry, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import ( - "strings" - "strconv" - "github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto" -) - -//GetIdentities is to fetch identities through cmdline -func GetIdentities(args []string, flags map[string]bool) { - GetDataFromIpcPipe(&GET_STATUS, GetIdentitiesFromRTS, nil, args, flags) -} - -//GetServices is to fetch services through cmdline -func GetServices(args []string, flags map[string]bool) { - GetDataFromIpcPipe(&GET_STATUS, GetServicesFromRTS, nil, args, flags) -} - -//OnOffIdentity is to enable or disable the identity through cmdline -func OnOffIdentity(args []string, flags map[string]bool) { - identityPayload := make(map[string]interface{}) - identityPayload["OnOff"] = strings.EqualFold(args[1], "on") - identityPayload["Fingerprint"] = args[0] - ONOFF_IDENTITY.Payload = identityPayload - log.Debugf("OnOffIdentity Payload %v", ONOFF_IDENTITY) - status := GetDataFromIpcPipe(&ONOFF_IDENTITY, nil, GetIdentityResponseObjectFromRTS, args, flags) - if status { - NOTIFY_IDENTITY_UI.Payload = identityPayload - log.Infof("Notifying the Identity Status to UI %v", identityPayload) - GetDataFromIpcPipe(&NOTIFY_IDENTITY_UI, nil, GetResponseObjectFromRTS, args, flags) - } -} - -//SetLogLevel is to change the loglevel through cmdline -func SetLogLevel(args []string, flags map[string]bool) { - if flags["query"] == true { - GetDataFromIpcPipe(&GET_STATUS, GetLogLevelFromRTS, nil, args, flags) - } else { - loglevelPayload := make(map[string]interface{}) - loglevelPayload["Level"] = args[0] - SET_LOGLEVEL.Payload = loglevelPayload - log.Debugf("LogLevel Payload %v", SET_LOGLEVEL) - status := GetDataFromIpcPipe(&SET_LOGLEVEL, nil, GetResponseObjectFromRTS, args, flags) - if status { - NOTIFY_LOGLEVEL_UI_MONITOR.Payload = loglevelPayload - log.Infof("Notifying the LogLevel to UI and Ziti monitor service %v", loglevelPayload) - GetDataFromIpcPipe(&NOTIFY_LOGLEVEL_UI_MONITOR, nil, GetResponseObjectFromRTS, args, flags) - } - } -} - -//GetFeedback is to create logs zip through cmdline -func GetFeedback(args []string, flags map[string]bool) { - GetDataFromMonitorIpcPipe(&dto.FEEDBACK_REQUEST, args, flags) -} - -func UpdateConfigIPSubnet(args []string, flags map[string]interface{}) { - CIDRstring := flags["CIDR"] - AddDns := flags["AddDns"] - log.Info("Updating the config file") - var cidr []string - var ipMask int - var err error - - updateTunIpv4Payload := make(map[string]interface{}) - if CIDRstring != "" { - cidr = strings.Split(CIDRstring.(string), "/") - if len(cidr) != 2 { - log.Error("Incorrect cidr") - } - ipMask, err = strconv.Atoi(cidr[1]) - if err != nil { - log.Errorf("Incorrect ipv4 mask, %s", cidr[1]) - return - } - updateTunIpv4Payload["TunIPv4"] = cidr[0] - updateTunIpv4Payload["TunIPv4Mask"] = ipMask - } - if AddDns != "" { - var addDnsBool bool - addDnsBool, err = strconv.ParseBool(AddDns.(string)) - - if err != nil { - log.Errorf("Incorrect addDns %v", err) - return - } - updateTunIpv4Payload["AddDns"] = addDnsBool - } - - UPDATE_TUN_IPV4.Payload = updateTunIpv4Payload - log.Debugf("updateTunIpv4 Payload %v", UPDATE_TUN_IPV4) - - status := GetDataFromIpcPipe(&UPDATE_TUN_IPV4, nil, GetResponseObjectFromRTS, args, nil) - - if !status { - log.Infof("Config can be updated only if the tunnel is started") - } - -} - +package cli + +/* + * Copyright NetFoundry, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import ( + "github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto" + "strconv" + "strings" +) + +//GetIdentities is to fetch identities through cmdline +func GetIdentities(args []string, flags map[string]bool) { + GetDataFromIpcPipe(&GET_STATUS, GetIdentitiesFromRTS, nil, args, flags) +} + +//GetServices is to fetch services through cmdline +func GetServices(args []string, flags map[string]bool) { + GetDataFromIpcPipe(&GET_STATUS, GetServicesFromRTS, nil, args, flags) +} + +//OnOffIdentity is to enable or disable the identity through cmdline +func OnOffIdentity(args []string, flags map[string]bool) { + identityPayload := make(map[string]interface{}) + identityPayload["OnOff"] = strings.EqualFold(args[1], "on") + identityPayload["Fingerprint"] = args[0] + ONOFF_IDENTITY.Payload = identityPayload + log.Debugf("OnOffIdentity Payload %v", ONOFF_IDENTITY) + status := GetDataFromIpcPipe(&ONOFF_IDENTITY, nil, GetIdentityResponseObjectFromRTS, args, flags) + if status { + NOTIFY_IDENTITY_UI.Payload = identityPayload + log.Infof("Notifying the Identity Status to UI %v", identityPayload) + GetDataFromIpcPipe(&NOTIFY_IDENTITY_UI, nil, GetResponseObjectFromRTS, args, flags) + } +} + +//SetLogLevel is to change the loglevel through cmdline +func SetLogLevel(args []string, flags map[string]bool) { + if flags["query"] == true { + GetDataFromIpcPipe(&GET_STATUS, GetLogLevelFromRTS, nil, args, flags) + } else { + loglevelPayload := make(map[string]interface{}) + loglevelPayload["Level"] = args[0] + SET_LOGLEVEL.Payload = loglevelPayload + log.Debugf("LogLevel Payload %v", SET_LOGLEVEL) + status := GetDataFromIpcPipe(&SET_LOGLEVEL, nil, GetResponseObjectFromRTS, args, flags) + if status { + NOTIFY_LOGLEVEL_UI_MONITOR.Payload = loglevelPayload + log.Infof("Notifying the LogLevel to UI and Ziti monitor service %v", loglevelPayload) + GetDataFromIpcPipe(&NOTIFY_LOGLEVEL_UI_MONITOR, nil, GetResponseObjectFromRTS, args, flags) + } + } +} + +//GetFeedback is to create logs zip through cmdline +func GetFeedback(args []string, flags map[string]bool) { + GetDataFromMonitorIpcPipe(&dto.FEEDBACK_REQUEST, args, flags) +} + +func UpdateConfigIPSubnet(args []string, flags map[string]interface{}) { + CIDRstring := flags["CIDR"] + AddDns := flags["AddDns"] + log.Info("Updating the config file") + var cidr []string + var ipMask int + var err error + + updateTunIpv4Payload := make(map[string]interface{}) + if CIDRstring != "" { + cidr = strings.Split(CIDRstring.(string), "/") + if len(cidr) != 2 { + log.Error("Incorrect cidr") + } + ipMask, err = strconv.Atoi(cidr[1]) + if err != nil { + log.Errorf("Incorrect ipv4 mask, %s", cidr[1]) + return + } + updateTunIpv4Payload["TunIPv4"] = cidr[0] + updateTunIpv4Payload["TunIPv4Mask"] = ipMask + } + if AddDns != "" { + var addDnsBool bool + addDnsBool, err = strconv.ParseBool(AddDns.(string)) + + if err != nil { + log.Errorf("Incorrect addDns %v", err) + return + } + updateTunIpv4Payload["AddDns"] = addDnsBool + } + + UPDATE_TUN_IPV4.Payload = updateTunIpv4Payload + log.Debugf("updateTunIpv4 Payload %v", UPDATE_TUN_IPV4) + + status := GetDataFromIpcPipe(&UPDATE_TUN_IPV4, nil, GetResponseObjectFromRTS, args, nil) + + if !status { + log.Infof("Config can be updated only if the tunnel is started") + } + +} From 4f0021fc8f73340030979ecaaacaeee4a64ed705 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Thu, 15 Apr 2021 20:08:29 +0530 Subject: [PATCH 09/36] removing unused function --- service/ziti-tunnel/cli/responseGenerator.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/service/ziti-tunnel/cli/responseGenerator.go b/service/ziti-tunnel/cli/responseGenerator.go index 2b19d6ad..d469dad7 100644 --- a/service/ziti-tunnel/cli/responseGenerator.go +++ b/service/ziti-tunnel/cli/responseGenerator.go @@ -226,17 +226,3 @@ func GetIdentityResponseObjectFromRTS(args []string, status dto.Response, flags func GetResponseObjectFromRTS(args []string, status dto.Response, flags map[string]bool) dto.Response { return status } - -func GetStatusFromRTS(args []string, status *dto.TunnelStatus, flags map[string]bool) dto.Response { - - if status == nil { - return dto.Response{Message: "Stopped / Unknown State", Code: service.SUCCESS, Error: "", Payload: ""} - } - - if status.Active { - return dto.Response{Message: "Running", Code: service.SUCCESS, Error: "", Payload: ""} - } else { - return dto.Response{Message: "Stopped", Code: service.SUCCESS, Error: "", Payload: ""} - } - -} From 2f7bb542c863e59da30a2811c98a86e64a8af10a Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Thu, 15 Apr 2021 20:16:40 +0530 Subject: [PATCH 10/36] removing unused code --- service/ziti-tunnel/service/state.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index ff2b9e15..b34c5513 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -407,14 +407,14 @@ func UpdateRuntimeStateIpv4(ip string, ipv4Mask int, addDns string) error { log.Infof("ip and mask %s %d", ip, ipv4Mask) - var addDnsBool bool - var err error if addDns != "" { - addDnsBool, err = strconv.ParseBool(addDns) + addDnsBool, err := strconv.ParseBool(addDns) if err != nil { return errors.New(fmt.Sprintf("Incorrect addDns %v", err)) } + + rts.state.AddDns = addDnsBool } // if ip is not empty, then we set both ip and mask @@ -422,9 +422,6 @@ func UpdateRuntimeStateIpv4(ip string, ipv4Mask int, addDns string) error { rts.state.TunIpv4 = ip rts.state.TunIpv4Mask = ipv4Mask } - if addDns != "" { - rts.state.AddDns = addDnsBool - } rts.SaveState() From 4507c2f6e5859e7966248994f45496ba5767d189 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Thu, 15 Apr 2021 21:30:13 +0530 Subject: [PATCH 11/36] fixing the code review comments --- service/ziti-tunnel/cli/service.go | 20 +++++++------------- service/ziti-tunnel/service/state.go | 6 +++++- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/service/ziti-tunnel/cli/service.go b/service/ziti-tunnel/cli/service.go index 3b9a9e03..dd6ebcfb 100644 --- a/service/ziti-tunnel/cli/service.go +++ b/service/ziti-tunnel/cli/service.go @@ -21,6 +21,7 @@ import ( "github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto" "strconv" "strings" + "net" ) //GetIdentities is to fetch identities through cmdline @@ -75,27 +76,20 @@ func UpdateConfigIPSubnet(args []string, flags map[string]interface{}) { CIDRstring := flags["CIDR"] AddDns := flags["AddDns"] log.Info("Updating the config file") - var cidr []string - var ipMask int - var err error updateTunIpv4Payload := make(map[string]interface{}) if CIDRstring != "" { - cidr = strings.Split(CIDRstring.(string), "/") - if len(cidr) != 2 { - log.Error("Incorrect cidr") - } - ipMask, err = strconv.Atoi(cidr[1]) + ip, ipnet, err := net.ParseCIDR(CIDRstring.(string)) if err != nil { - log.Errorf("Incorrect ipv4 mask, %s", cidr[1]) - return + log.Error("Incorrect cidr %s", CIDRstring.(string)) } - updateTunIpv4Payload["TunIPv4"] = cidr[0] + ipMask, _ := ipnet.Mask.Size() + + updateTunIpv4Payload["TunIPv4"] = ip updateTunIpv4Payload["TunIPv4Mask"] = ipMask } if AddDns != "" { - var addDnsBool bool - addDnsBool, err = strconv.ParseBool(AddDns.(string)) + addDnsBool, err := strconv.ParseBool(AddDns.(string)) if err != nil { log.Errorf("Incorrect addDns %v", err) diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index b34c5513..aa625adb 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -405,7 +405,11 @@ func (t *RuntimeState) UpdateIpv4(ipv4 string) { func UpdateRuntimeStateIpv4(ip string, ipv4Mask int, addDns string) error { - log.Infof("ip and mask %s %d", ip, ipv4Mask) + log.Infof("updating configuration ip: %s, mask: %d, dns: %t", ip, ipv4Mask, addDns) + + if ipv4Mask < constants.Ipv4MaxMask || ipv4Mask > constants.Ipv4MinMask { + return errors.New(fmt.Sprintf("ipv4Mask should be between %d and %d", constants.Ipv4MaxMask, constants.Ipv4MinMask)) + } if addDns != "" { addDnsBool, err := strconv.ParseBool(addDns) From af86b732296f1b8832104fa7c6f59865af0ae5d1 Mon Sep 17 00:00:00 2001 From: ziti-ci Date: Thu, 15 Apr 2021 16:13:32 +0000 Subject: [PATCH 12/36] [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 ec3cefc3..127f5b62 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.3.0")] -[assembly: AssemblyVersion("1.9.3.0")] -[assembly: AssemblyFileVersion("1.9.3.0")] +// [assembly: AssemblyVersion("1.9.4.0")] +[assembly: AssemblyVersion("1.9.4.0")] +[assembly: AssemblyFileVersion("1.9.4.0")] diff --git a/Installer/ZitiDesktopEdge.aip b/Installer/ZitiDesktopEdge.aip index fff0961b..9da73f34 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 6c15d9ab..7b16007f 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.3.0")] -[assembly: AssemblyVersion("1.9.3.0")] -[assembly: AssemblyFileVersion("1.9.3.0")] +// [assembly: AssemblyVersion("1.9.4.0")] +[assembly: AssemblyVersion("1.9.4.0")] +[assembly: AssemblyFileVersion("1.9.4.0")] diff --git a/service/ziti-tunnel/version.go b/service/ziti-tunnel/version.go index 6f114ee5..f7619a3b 100644 --- a/service/ziti-tunnel/version.go +++ b/service/ziti-tunnel/version.go @@ -20,9 +20,9 @@ package main const ( - Version = "1.9.3" - Revision = "a02a50cf6437" - Branch = "main" + Version = "1.9.4" + Revision = "138ceebaefbf" + Branch = "release-next" BuildUser = "" - BuildDate = "2021-04-12 17:35:14" + BuildDate = "2021-04-15 16:07:55" ) From 9e7e38317a3b313048aceaf7a4c0585f9a1e03a8 Mon Sep 17 00:00:00 2001 From: Jeremy Tellier - ROG Date: Fri, 16 Apr 2021 00:57:54 +0100 Subject: [PATCH 13/36] Start Scroller --- .../Views/Screens/IdentityDetails.xaml | 2 +- .../Views/Screens/IdentityDetails.xaml.cs | 41 ++++++++++++++++++- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/DesktopEdge/Views/Screens/IdentityDetails.xaml b/DesktopEdge/Views/Screens/IdentityDetails.xaml index 408e801a..4b3e088a 100644 --- a/DesktopEdge/Views/Screens/IdentityDetails.xaml +++ b/DesktopEdge/Views/Screens/IdentityDetails.xaml @@ -67,7 +67,7 @@ - + diff --git a/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs b/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs index ebaa8140..af592485 100644 --- a/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs +++ b/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs @@ -37,6 +37,7 @@ namespace ZitiDesktopEdge { public event OnRecovery Recovery; public int Page = 1; public int PerPage = 50; + public int TotalPages = 1; public string SortBy = "Name"; public string SortWay = "Asc"; @@ -156,8 +157,8 @@ namespace ZitiDesktopEdge { if (Page==1) { Pages.Items.Clear(); - int totalPages = (total / PerPage) + 1; - for (int i = 1; i <= totalPages; i++) { + 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(); @@ -394,5 +395,41 @@ namespace ZitiDesktopEdge { } } } + + private void Scrolled(object sender, ScrollChangedEventArgs e) { + var verticalOffset = ServiceScroller.VerticalOffset; + var maxVerticalOffset = ServiceScroller.ScrollableHeight; + + if (maxVerticalOffset < 0 || + verticalOffset == maxVerticalOffset) { + if (Page < TotalPages) { + Page += 1; + 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 < services.Length; i++) { + ZitiService zitiSvc = services[i]; + total++; + if (index < 100) { + 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); + index++; + } + } + } + } + } + } } } From dbf7a69fd0746fff466bedb2288955b2d2f01607 Mon Sep 17 00:00:00 2001 From: Jeremy Tellier - ROG Date: Fri, 16 Apr 2021 11:48:48 +0100 Subject: [PATCH 14/36] Screens for Config Editing --- DesktopEdge/App.xaml | 303 +++++- DesktopEdge/MainWindow.xaml.cs | 12 +- DesktopEdge/Views/Screens/MainMenu.xaml | 89 +- DesktopEdge/Views/Screens/MainMenu.xaml.cs | 1071 +++++++++++--------- 4 files changed, 962 insertions(+), 513 deletions(-) diff --git a/DesktopEdge/App.xaml b/DesktopEdge/App.xaml index bcd9158d..356176f8 100644 --- a/DesktopEdge/App.xaml +++ b/DesktopEdge/App.xaml @@ -1,7 +1,8 @@ - @@ -18,7 +19,7 @@ - + @@ -33,7 +34,7 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index c67c738d..0c1ddef9 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -156,6 +156,11 @@ namespace ZitiDesktopEdge { this.ShowMFA(identity, 1); } + /// + /// Show MFA for the identity and set the type of screen to show + /// + /// The Identity that is currently active + /// The type of screen to show - 1 Setup, 2 Authenticate, 3 Remove MFA, 4 Regenerate Codes private void ShowMFA(ZitiIdentity identity, int type) { MFASetup.Opacity = 0; MFASetup.Visibility = Visibility.Visible; @@ -503,6 +508,7 @@ namespace ZitiDesktopEdge { Application.Current.Properties.Add("Identities", new List()); MainMenu.OnAttachmentChange += AttachmentChanged; MainMenu.OnLogLevelChanged += LogLevelChanged; + MainMenu.OnShowBlurb += MainMenu_OnShowBlurb; IdentityMenu.OnError += IdentityMenu_OnError; try { @@ -524,7 +530,11 @@ namespace ZitiDesktopEdge { Placement(); } - private void ServiceClient_OnBulkServiceEvent(object sender, BulkServiceEvent e) { + private void MainMenu_OnShowBlurb(string message) { + _ = ShowBlurbAsync(message, ""); + } + + 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!"); diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml b/DesktopEdge/Views/Screens/MainMenu.xaml index 0961caf4..b3c566a2 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml +++ b/DesktopEdge/Views/Screens/MainMenu.xaml @@ -7,6 +7,7 @@ mc:Ignorable="d" x:Name="MainMenuArea" d:DesignHeight="400" d:DesignWidth="400" Margin="1,1,1,1"> + @@ -93,21 +94,7 @@ - - - - - - - - - + @@ -124,5 +111,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml.cs b/DesktopEdge/Views/Screens/MainMenu.xaml.cs index d85a9b7a..58ddab5d 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml.cs +++ b/DesktopEdge/Views/Screens/MainMenu.xaml.cs @@ -1,489 +1,586 @@ -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using System.Diagnostics; -using System; -using System.Reflection; -using System.Net.Mail; -using System.IO; -using NLog; - -using ZitiDesktopEdge.Models; -using ZitiDesktopEdge.DataStructures; -using ZitiDesktopEdge.ServiceClient; -using System.Configuration; - -namespace ZitiDesktopEdge { - /// - /// Interaction logic for MainMenu.xaml - /// - public partial class MainMenu : UserControl { - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - - public delegate void AttachementChanged(bool attached); - public event AttachementChanged OnAttachmentChange; - public delegate void LogLevelChanged(string level); - public event LogLevelChanged OnLogLevelChanged; - public delegate void Detched(MouseButtonEventArgs e); - public event Detched OnDetach; - public string menuState = "Main"; - public string licenseData = "it's open source."; - public string LogLevel = ""; - private string appVersion = null; - private bool allowReleaseSelect = false; - public double MainHeight = 500; - - private bool isBeta { - get { - return Application.Current.Properties["ReleaseStream"]?.ToString() == "beta"; - } - } - - internal MainWindow MainWindow { get; set; } - - public MainMenu() { - InitializeComponent(); - Application.Current.MainWindow.Title = "Ziti Desktop Edge"; - - try { - allowReleaseSelect = bool.Parse(ConfigurationManager.AppSettings.Get("ReleaseStreamSelect")); - } catch { - //if we can't parse the config - leave it as false... - allowReleaseSelect = false; //setting it here in case anyone changes the default above - } -#if DEBUG - Debug.WriteLine("OVERRIDING allowReleaseSelect to true!"); - allowReleaseSelect = true; -#endif - appVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); - LicensesItems.Text = licenseData; - // don't check from the UI any more... CheckUpdates(); - } - - private void HideMenu(object sender, MouseButtonEventArgs e) { - menuState = "Menu"; - UpdateState(); - MainMenuArea.Visibility = Visibility.Collapsed; - } - private void Window_MouseDown(object sender, MouseButtonEventArgs e) { - if (e.ChangedButton == MouseButton.Left) { - OnDetach(e); - } - } - - private void CloseApp(object sender, MouseButtonEventArgs e) { - Application.Current.Shutdown(); - } - - private void ShowAbout(object sender, MouseButtonEventArgs e) { - menuState = "About"; - UpdateState(); - } - - private void ShowAdvanced(object sender, MouseButtonEventArgs e) { - menuState = "Advanced"; - UpdateState(); - } - private void ShowIdentities(object sender, MouseButtonEventArgs e) { - menuState = "Identities"; - UpdateState(); - } - private void ShowLicenses(object sender, MouseButtonEventArgs e) { - menuState = "Licenses"; - UpdateState(); - } - private void ShowConfig(object sender, MouseButtonEventArgs e) { - menuState = "Config"; - UpdateState(); - } - private void ShowLogs(object sender, MouseButtonEventArgs e) { - menuState = "Logs"; - UpdateState(); - } - private void ShowUILogs(object sender, MouseButtonEventArgs e) { - menuState = "UILogs"; - UpdateState(); - } - private void ShowReleaseStreamMenuAction(object sender, MouseButtonEventArgs e) { - logger.Warn("this is ShowReleaseStreamMenuAction at warn"); - logger.Info("this is ShowReleaseStreamMenuAction at info"); - logger.Debug("this is ShowReleaseStreamMenuAction at debug"); - logger.Trace("this is ShowReleaseStreamMenuAction at trace"); - menuState = "SetReleaseStream"; - UpdateState(); - } - - async private void SetReleaseStreamMenuAction(object sender, MouseButtonEventArgs e) { - CheckForUpdateStatus.Visibility = Visibility.Collapsed; - TriggerUpdateButton.Visibility = Visibility.Collapsed; - SubOptionItem opt = (SubOptionItem)sender; - var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; - menuState = "SetReleaseStream"; - - bool releaseClicked = opt.Label.ToLower() == "stable"; - - if (releaseClicked) { - if (isBeta) { - //toggle to stable - var r = await monitorClient.SetReleaseStreamAsync("stable"); - checkResponse(r, "Error When Setting Release Stream", "An error occurred while trying to set the release stream."); - } else { - logger.Debug("stable clicked but already on stable stream"); - } - } else { - if (!isBeta) { - //toggle to beta - var r = await monitorClient.SetReleaseStreamAsync("beta"); - checkResponse(r, "Error When Setting Release Stream", "An error occurred while trying to set the release stream."); - } else { - logger.Debug("beta clicked but already on beta stream"); - } - } - Application.Current.Properties["ReleaseStream"] = opt.Label.ToLower(); - UpdateState(); - } - - private void checkResponse(SvcResponse r, string titleOnErr, string msgOnErr) { - if (r == null) { - MainWindow.ShowError(titleOnErr, msgOnErr); - } else { - logger.Info(r?.ToString()); - } - } - - private void SetLogLevel(object sender, MouseButtonEventArgs e) { - menuState = "LogLevel"; - UpdateState(); - } - - private void UpdateState() { - IdListScrollView.Height = this.ActualHeight-100.00; - IdListScrollView.Visibility = Visibility.Collapsed; - MainItems.Visibility = Visibility.Collapsed; - AboutItems.Visibility = Visibility.Collapsed; - MainItemsButton.Visibility = Visibility.Collapsed; - AboutItemsArea.Visibility = Visibility.Collapsed; - BackArrow.Visibility = Visibility.Collapsed; - AdvancedItems.Visibility = Visibility.Collapsed; - LicensesItems.Visibility = Visibility.Collapsed; - LogsItems.Visibility = Visibility.Collapsed; - ConfigItems.Visibility = Visibility.Collapsed; - LogLevelItems.Visibility = Visibility.Collapsed; - ReleaseStreamItems.Visibility = Visibility.Collapsed; - - if (menuState == "About") { - MenuTitle.Content = "About"; - AboutItemsArea.Visibility = Visibility.Visible; - AboutItems.Visibility = Visibility.Visible; - BackArrow.Visibility = Visibility.Visible; - - string version = ""; - try { - TunnelStatus s = (TunnelStatus)Application.Current.Properties["CurrentTunnelStatus"]; - version = $"{s.ServiceVersion.Version}@{s.ServiceVersion.Revision}"; - } catch (Exception e) { - logger.Warn(e, "Could not get service version/revision?"); - } - - // Interface Version - VersionInfo.Content = $"App: {appVersion} Service: {version}"; - - } else if (menuState == "Advanced") { - MenuTitle.Content = "Advanced Settings"; - AdvancedItems.Visibility = Visibility.Visible; - BackArrow.Visibility = Visibility.Visible; - ShowReleaseStreamMenuItem.Visibility = allowReleaseSelect ? Visibility.Visible : Visibility.Collapsed; - } else if (menuState == "Licenses") { - MenuTitle.Content = "Third Party Licenses"; - LicensesItems.Visibility = Visibility.Visible; - BackArrow.Visibility = Visibility.Visible; - } else if (menuState == "Logs") { - MenuTitle.Content = "Advanced Settings"; - AdvancedItems.Visibility = Visibility.Visible; - //string targetFile = NativeMethods.GetFinalPathName(MainWindow.ExpectedLogPathServices); - string targetFile = MainWindow.ExpectedLogPathServices; - - OpenLogFile("service", targetFile); - BackArrow.Visibility = Visibility.Visible; - } else if (menuState == "UILogs") { - MenuTitle.Content = "Advanced Settings"; - AdvancedItems.Visibility = Visibility.Visible; - OpenLogFile("UI", MainWindow.ExpectedLogPathUI); - BackArrow.Visibility = Visibility.Visible; - } else if (menuState == "LogLevel") { - ResetLevels(); - - MenuTitle.Content = "Set Log Level"; - LogLevelItems.Visibility = Visibility.Visible; - BackArrow.Visibility = Visibility.Visible; - } else if (menuState == "SetReleaseStream") { - SetReleaseStream(); - - MenuTitle.Content = "Set Release Stream"; - ReleaseStreamItems.Visibility = allowReleaseSelect ? Visibility.Visible : Visibility.Collapsed; - BackArrow.Visibility = Visibility.Visible; - } else if (menuState == "Config") { - MenuTitle.Content = "Tunnel Configuration"; - ConfigItems.Visibility = Visibility.Visible; - BackArrow.Visibility = Visibility.Visible; - - ConfigIp.Value = Application.Current.Properties["ip"]?.ToString(); - ConfigSubnet.Value = Application.Current.Properties["subnet"]?.ToString(); - ConfigMtu.Value = Application.Current.Properties["mtu"]?.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; - BackArrow.Visibility = Visibility.Visible; - } else { - MenuTitle.Content = "Main Menu"; - MainItems.Visibility = Visibility.Visible; - MainItemsButton.Visibility = Visibility.Visible; - ReleaseStreamItems.Visibility = Visibility.Collapsed; - } - } - - private void OpenLogFile(string which, string logFile) { - var whichRoot = Path.Combine(MainWindow.ExpectedLogPathRoot, which); - try { - string target = Native.NativeMethods.GetFinalPathName(logFile); - if (File.Exists(target)) { - logger.Info("opening {0} logs at: {1}", which, target); - var p = Process.Start(new ProcessStartInfo(target) { UseShellExecute = true }); - if (p != null) { - logger.Info("showing {0} logs. file: {1}", which, target); - } else { - Process.Start(whichRoot); - } - return; - } else { - logger.Warn("could not show {0} logs. file not found: {1}", which, target); - } - } catch { - } - Process.Start(whichRoot); - } - - private void GoBack(object sender, MouseButtonEventArgs e) { - if (menuState == "Config" || menuState == "LogLevel" || menuState == "UILogs" || menuState == "SetReleaseStream") { - menuState = "Advanced"; - } else if (menuState == "Licenses") { - menuState = "About"; - } else { - menuState = "Menu"; - } - UpdateState(); - } - private void ShowPrivacy(object sender, MouseButtonEventArgs e) { - Process.Start(new ProcessStartInfo("https://netfoundry.io/privacy") { UseShellExecute = true }); - } - private void ShowTerms(object sender, MouseButtonEventArgs e) { - Process.Start(new ProcessStartInfo("https://netfoundry.io/terms") { UseShellExecute = true }); - } - - async private void ShowFeedback(object sender, MouseButtonEventArgs e) { - try { - MainWindow.ShowLoad("Collecting Information", "Please wait while we run some commands\nand collect some diagnostic information"); - var mailMessage = new MailMessage("help@openziti.org", "help@openziti.org"); - mailMessage.Subject = "Ziti Support"; - mailMessage.IsBodyHtml = false; - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - sb.Append("Logs collected at : " + DateTime.Now.ToString()); - sb.Append(". client version : " + appVersion); - - mailMessage.Body = sb.ToString(); - - string timestamp = DateTime.Now.ToFileTime().ToString(); - - var dataClient = (DataClient)Application.Current.Properties["ServiceClient"]; - await dataClient.zitiDump(); - - var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; - MonitorServiceStatusEvent resp = await monitorClient.CaptureLogsAsync(); - if (resp == null) { - logger.Error("no response from monitorClient?"); - MainWindow mw = (MainWindow)Application.Current.MainWindow; - mw?.ShowError("Error Collecting Feedback", "An error occurred while trying to gather feedback.\nIs the monitor service running?"); - return; - } - string pathToLogs = resp.Message; - logger.Info("Log files found at : {0}", resp.Message); - mailMessage.Attachments.Add(new Attachment(pathToLogs)); - - string emlFile = Path.Combine(Path.GetTempPath(), timestamp + "-ziti.eml"); - - using (var filestream = File.Open(emlFile, FileMode.Create)) { - var binaryWriter = new BinaryWriter(filestream); - binaryWriter.Write(System.Text.Encoding.UTF8.GetBytes("X-Unsent: 1" + Environment.NewLine)); - var assembly = typeof(SmtpClient).Assembly; - var mailWriterType = assembly.GetType("System.Net.Mail.MailWriter"); - var mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null); - var mailWriter = mailWriterContructor.Invoke(new object[] { filestream }); - var sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic); - sendMethod.Invoke(mailMessage, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { mailWriter, true, true }, null); - var closeMethod = mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic); - closeMethod.Invoke(mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null); - } - var p = Process.Start(emlFile); - if (p != null) { - p.Exited += (object lambdaSender, EventArgs lambdaEventArgs) => { - logger.Info("Removing temp file: {0}", emlFile); - File.Delete(emlFile); - }; - p.EnableRaisingEvents = true; - } else { - logger.Debug("process was null. most likely the email file format was not known when the process tried to start"); - } - } catch (Exception ex) { - logger.Warn(ex, "An unexpected error has occurred when submitting feedback? {0}", ex.Message); - } - MainWindow.HideLoad(); - } - - private void ShowSupport(object sender, MouseButtonEventArgs e) { - Process.Start(new ProcessStartInfo("https://openziti.discourse.group/") { UseShellExecute = true }); - } - - private void DetachWindow(object sender, MouseButtonEventArgs e) { - Application.Current.MainWindow.ShowInTaskbar = true; - DetachButton.Visibility = Visibility.Collapsed; - AttachButton.Visibility = Visibility.Visible; - Arrow.Visibility = Visibility.Collapsed; - if (OnAttachmentChange != null) { - OnAttachmentChange(false); - } - MainMenuArea.Visibility = Visibility.Collapsed; - } - - public void Detach() { - Application.Current.MainWindow.ShowInTaskbar = true; - DetachButton.Visibility = Visibility.Collapsed; - AttachButton.Visibility = Visibility.Visible; - Arrow.Visibility = Visibility.Collapsed; - } - private void RetachWindow(object sender, MouseButtonEventArgs e) { - Application.Current.MainWindow.ShowInTaskbar = false; - DetachButton.Visibility = Visibility.Visible; - AttachButton.Visibility = Visibility.Collapsed; - Arrow.Visibility = Visibility.Visible; - if (OnAttachmentChange != null) { - OnAttachmentChange(true); - } - } - - private void ResetLevels() { - if (this.LogLevel == "") this.LogLevel = "error"; - LogVerbose.IsSelected = false; - LogDebug.IsSelected = false; - LogInfo.IsSelected = false; - LogError.IsSelected = false; - LogFatal.IsSelected = false; - LogWarn.IsSelected = false; - LogTrace.IsSelected = false; - if (this.LogLevel == "verbose") LogVerbose.IsSelected = true; - else if (this.LogLevel == "debug") LogDebug.IsSelected = true; - else if (this.LogLevel == "info") LogInfo.IsSelected = true; - else if (this.LogLevel == "error") LogError.IsSelected = true; - else if (this.LogLevel == "fatal") LogFatal.IsSelected = true; - else if (this.LogLevel == "warn") LogWarn.IsSelected = true; - else if (this.LogLevel == "trace") LogTrace.IsSelected = true; - } - - private void SetLevel(object sender, MouseButtonEventArgs e) { - SubOptionItem item = (SubOptionItem)sender; - this.LogLevel = item.Label.ToLower(); - if (OnLogLevelChanged != null) { - OnLogLevelChanged(this.LogLevel); - } - ResetLevels(); - } - - private void SetReleaseStream() { - this.ReleaseStreamItemBeta.IsSelected = isBeta; - this.ReleaseStreamItemStable.IsSelected = !isBeta; - } - - async private void CheckForUpdate_Click(object sender, RoutedEventArgs e) { - logger.Info("checking for update..."); - try { - CheckForUpdate.IsEnabled = false; - CheckForUpdateStatus.Content = "Checking for update..."; - CheckForUpdateStatus.Visibility = Visibility.Visible; - var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; - var r = await monitorClient.DoUpdateCheck(); - checkResponse(r, "Error When Checking for Update", "An error occurred while trying check for update."); - CheckForUpdateStatus.Content = r.Message; - if (r.UpdateAvailable) { - TriggerUpdateButton.Visibility = Visibility.Visible; - } else { - TriggerUpdateButton.Visibility = Visibility.Collapsed; - } - } catch (Exception ex) { - logger.Error(ex, "unexpected error in update check: {0}", ex.Message); - } - CheckForUpdate.IsEnabled = true; - } - - async private void UpdateConfig_Click(object sender, RoutedEventArgs e) { - logger.Info("updating config..."); - DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; - try { - var newMaskVar = Int32.Parse(ConfigMaskNew.Text); - var addDnsNewVar = Convert.ToBoolean(AddDnsNew.Text); - - var r = await client.UpdateConfigAsync(ConfigIpNew.Text, newMaskVar, addDnsNewVar); - logger.Info("Got response from update config task : {0}", r); - } catch (DataStructures.ServiceException se) { - logger.Error(se, "service exception in update check: {0}", se.Message); +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Diagnostics; +using System; +using System.Reflection; +using System.Net.Mail; +using System.IO; +using NLog; +using System.Windows.Media.Animation; + +using ZitiDesktopEdge.Models; +using ZitiDesktopEdge.DataStructures; +using ZitiDesktopEdge.ServiceClient; +using System.Configuration; + +namespace ZitiDesktopEdge { + /// + /// Interaction logic for MainMenu.xaml + /// + public partial class MainMenu : UserControl { + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + public delegate void AttachementChanged(bool attached); + public event AttachementChanged OnAttachmentChange; + public delegate void LogLevelChanged(string level); + public event LogLevelChanged OnLogLevelChanged; + public delegate void Detched(MouseButtonEventArgs e); + public event Detched OnDetach; + public delegate void ShowBlurb(string message); + public event ShowBlurb OnShowBlurb; + public string menuState = "Main"; + public string licenseData = "it's open source."; + public string LogLevel = ""; + private string appVersion = null; + private bool allowReleaseSelect = false; + public double MainHeight = 500; + + private bool isBeta { + get { + return Application.Current.Properties["ReleaseStream"]?.ToString() == "beta"; } - catch (Exception ex) { - logger.Error(ex, "unexpected error in update check: {0}", ex.Message); - } - } - - async private void TriggerUpdate_Click(object sender, RoutedEventArgs e) { - try { - CheckForUpdate.IsEnabled = false; - TriggerUpdateButton.IsEnabled = false; - CheckForUpdateStatus.Content = "Requesting automatic update..."; - var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; - var r = await monitorClient.TriggerUpdate(); - CheckForUpdateStatus.Content = "Automatic update requested..."; - checkResponse(r, "Error When Triggering Update", "An error occurred while trying to trigger the update."); - } catch (Exception ex) { - logger.Error(ex, "unexpected error in update check: {0}", ex.Message); - } - TriggerUpdateButton.IsEnabled = true; - CheckForUpdate.IsEnabled = true; - } - - public void SetupIdList(ZitiIdentity[] ids) { - IdListView.Children.Clear(); - for (int i=0; i { - VersionOlder.Content = msg; - VersionNewer.Content = ""; - VersionOlder.Visibility = Visibility.Visible; - VersionNewer.Visibility = Visibility.Collapsed; - }); - } - public void SetAppIsNewer(string msg) { - this.Dispatcher.Invoke(() => { - VersionNewer.Content = msg; - VersionOlder.Content = ""; - VersionNewer.Visibility = Visibility.Visible; - VersionOlder.Visibility = Visibility.Collapsed; - }); - } - } + } + + internal MainWindow MainWindow { get; set; } + + public MainMenu() { + InitializeComponent(); + Application.Current.MainWindow.Title = "Ziti Desktop Edge"; + + try { + allowReleaseSelect = bool.Parse(ConfigurationManager.AppSettings.Get("ReleaseStreamSelect")); + } catch { + //if we can't parse the config - leave it as false... + allowReleaseSelect = false; //setting it here in case anyone changes the default above + } +#if DEBUG + Debug.WriteLine("OVERRIDING allowReleaseSelect to true!"); + allowReleaseSelect = true; +#endif + appVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); + LicensesItems.Text = licenseData; + // don't check from the UI any more... CheckUpdates(); + } + + private void HideMenu(object sender, MouseButtonEventArgs e) { + menuState = "Menu"; + UpdateState(); + MainMenuArea.Visibility = Visibility.Collapsed; + } + private void Window_MouseDown(object sender, MouseButtonEventArgs e) { + if (e.ChangedButton == MouseButton.Left) { + OnDetach(e); + } + } + + private void CloseApp(object sender, MouseButtonEventArgs e) { + Application.Current.Shutdown(); + } + + private void ShowAbout(object sender, MouseButtonEventArgs e) { + menuState = "About"; + UpdateState(); + } + + private void ShowAdvanced(object sender, MouseButtonEventArgs e) { + menuState = "Advanced"; + UpdateState(); + } + private void ShowIdentities(object sender, MouseButtonEventArgs e) { + menuState = "Identities"; + UpdateState(); + } + private void ShowLicenses(object sender, MouseButtonEventArgs e) { + menuState = "Licenses"; + UpdateState(); + } + private void ShowConfig(object sender, MouseButtonEventArgs e) { + menuState = "Config"; + UpdateState(); + } + private void ShowLogs(object sender, MouseButtonEventArgs e) { + menuState = "Logs"; + UpdateState(); + } + private void ShowUILogs(object sender, MouseButtonEventArgs e) { + menuState = "UILogs"; + UpdateState(); + } + private void ShowReleaseStreamMenuAction(object sender, MouseButtonEventArgs e) { + logger.Warn("this is ShowReleaseStreamMenuAction at warn"); + logger.Info("this is ShowReleaseStreamMenuAction at info"); + logger.Debug("this is ShowReleaseStreamMenuAction at debug"); + logger.Trace("this is ShowReleaseStreamMenuAction at trace"); + menuState = "SetReleaseStream"; + UpdateState(); + } + + async private void SetReleaseStreamMenuAction(object sender, MouseButtonEventArgs e) { + CheckForUpdateStatus.Visibility = Visibility.Collapsed; + TriggerUpdateButton.Visibility = Visibility.Collapsed; + SubOptionItem opt = (SubOptionItem)sender; + var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; + menuState = "SetReleaseStream"; + + bool releaseClicked = opt.Label.ToLower() == "stable"; + + if (releaseClicked) { + if (isBeta) { + //toggle to stable + var r = await monitorClient.SetReleaseStreamAsync("stable"); + checkResponse(r, "Error When Setting Release Stream", "An error occurred while trying to set the release stream."); + } else { + logger.Debug("stable clicked but already on stable stream"); + } + } else { + if (!isBeta) { + //toggle to beta + var r = await monitorClient.SetReleaseStreamAsync("beta"); + checkResponse(r, "Error When Setting Release Stream", "An error occurred while trying to set the release stream."); + } else { + logger.Debug("beta clicked but already on beta stream"); + } + } + Application.Current.Properties["ReleaseStream"] = opt.Label.ToLower(); + UpdateState(); + } + + private void checkResponse(SvcResponse r, string titleOnErr, string msgOnErr) { + if (r == null) { + MainWindow.ShowError(titleOnErr, msgOnErr); + } else { + logger.Info(r?.ToString()); + } + } + + private void SetLogLevel(object sender, MouseButtonEventArgs e) { + menuState = "LogLevel"; + UpdateState(); + } + + private void UpdateState() { + IdListScrollView.Height = this.ActualHeight-100.00; + IdListScrollView.Visibility = Visibility.Collapsed; + MainItems.Visibility = Visibility.Collapsed; + AboutItems.Visibility = Visibility.Collapsed; + MainItemsButton.Visibility = Visibility.Collapsed; + AboutItemsArea.Visibility = Visibility.Collapsed; + BackArrow.Visibility = Visibility.Collapsed; + AdvancedItems.Visibility = Visibility.Collapsed; + LicensesItems.Visibility = Visibility.Collapsed; + LogsItems.Visibility = Visibility.Collapsed; + ConfigItems.Visibility = Visibility.Collapsed; + LogLevelItems.Visibility = Visibility.Collapsed; + ReleaseStreamItems.Visibility = Visibility.Collapsed; + + if (menuState == "About") { + MenuTitle.Content = "About"; + AboutItemsArea.Visibility = Visibility.Visible; + AboutItems.Visibility = Visibility.Visible; + BackArrow.Visibility = Visibility.Visible; + + string version = ""; + try { + TunnelStatus s = (TunnelStatus)Application.Current.Properties["CurrentTunnelStatus"]; + version = $"{s.ServiceVersion.Version}@{s.ServiceVersion.Revision}"; + } catch (Exception e) { + logger.Warn(e, "Could not get service version/revision?"); + } + + // Interface Version + VersionInfo.Content = $"App: {appVersion} Service: {version}"; + + } else if (menuState == "Advanced") { + MenuTitle.Content = "Advanced Settings"; + AdvancedItems.Visibility = Visibility.Visible; + BackArrow.Visibility = Visibility.Visible; + ShowReleaseStreamMenuItem.Visibility = allowReleaseSelect ? Visibility.Visible : Visibility.Collapsed; + } else if (menuState == "Licenses") { + MenuTitle.Content = "Third Party Licenses"; + LicensesItems.Visibility = Visibility.Visible; + BackArrow.Visibility = Visibility.Visible; + } else if (menuState == "Logs") { + MenuTitle.Content = "Advanced Settings"; + AdvancedItems.Visibility = Visibility.Visible; + //string targetFile = NativeMethods.GetFinalPathName(MainWindow.ExpectedLogPathServices); + string targetFile = MainWindow.ExpectedLogPathServices; + + OpenLogFile("service", targetFile); + BackArrow.Visibility = Visibility.Visible; + } else if (menuState == "UILogs") { + MenuTitle.Content = "Advanced Settings"; + AdvancedItems.Visibility = Visibility.Visible; + OpenLogFile("UI", MainWindow.ExpectedLogPathUI); + BackArrow.Visibility = Visibility.Visible; + } else if (menuState == "LogLevel") { + ResetLevels(); + + MenuTitle.Content = "Set Log Level"; + LogLevelItems.Visibility = Visibility.Visible; + BackArrow.Visibility = Visibility.Visible; + } else if (menuState == "SetReleaseStream") { + SetReleaseStream(); + + MenuTitle.Content = "Set Release Stream"; + ReleaseStreamItems.Visibility = allowReleaseSelect ? Visibility.Visible : Visibility.Collapsed; + BackArrow.Visibility = Visibility.Visible; + } else if (menuState == "Config") { + MenuTitle.Content = "Tunnel Configuration"; + ConfigItems.Visibility = Visibility.Visible; + BackArrow.Visibility = Visibility.Visible; + + ConfigIp.Value = Application.Current.Properties["ip"]?.ToString(); + ConfigSubnet.Value = Application.Current.Properties["subnet"]?.ToString(); + ConfigMtu.Value = Application.Current.Properties["mtu"]?.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; + BackArrow.Visibility = Visibility.Visible; + } else { + MenuTitle.Content = "Main Menu"; + MainItems.Visibility = Visibility.Visible; + MainItemsButton.Visibility = Visibility.Visible; + ReleaseStreamItems.Visibility = Visibility.Collapsed; + } + } + + private void OpenLogFile(string which, string logFile) { + var whichRoot = Path.Combine(MainWindow.ExpectedLogPathRoot, which); + try { + string target = Native.NativeMethods.GetFinalPathName(logFile); + if (File.Exists(target)) { + logger.Info("opening {0} logs at: {1}", which, target); + var p = Process.Start(new ProcessStartInfo(target) { UseShellExecute = true }); + if (p != null) { + logger.Info("showing {0} logs. file: {1}", which, target); + } else { + Process.Start(whichRoot); + } + return; + } else { + logger.Warn("could not show {0} logs. file not found: {1}", which, target); + } + } catch { + } + Process.Start(whichRoot); + } + + private void GoBack(object sender, MouseButtonEventArgs e) { + if (menuState == "Config" || menuState == "LogLevel" || menuState == "UILogs" || menuState == "SetReleaseStream") { + menuState = "Advanced"; + } else if (menuState == "Licenses") { + menuState = "About"; + } else { + menuState = "Menu"; + } + UpdateState(); + } + private void ShowPrivacy(object sender, MouseButtonEventArgs e) { + Process.Start(new ProcessStartInfo("https://netfoundry.io/privacy") { UseShellExecute = true }); + } + private void ShowTerms(object sender, MouseButtonEventArgs e) { + Process.Start(new ProcessStartInfo("https://netfoundry.io/terms") { UseShellExecute = true }); + } + + async private void ShowFeedback(object sender, MouseButtonEventArgs e) { + try { + MainWindow.ShowLoad("Collecting Information", "Please wait while we run some commands\nand collect some diagnostic information"); + var mailMessage = new MailMessage("help@openziti.org", "help@openziti.org"); + mailMessage.Subject = "Ziti Support"; + mailMessage.IsBodyHtml = false; + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.Append("Logs collected at : " + DateTime.Now.ToString()); + sb.Append(". client version : " + appVersion); + + mailMessage.Body = sb.ToString(); + + string timestamp = DateTime.Now.ToFileTime().ToString(); + + var dataClient = (DataClient)Application.Current.Properties["ServiceClient"]; + await dataClient.zitiDump(); + + var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; + MonitorServiceStatusEvent resp = await monitorClient.CaptureLogsAsync(); + if (resp == null) { + logger.Error("no response from monitorClient?"); + MainWindow mw = (MainWindow)Application.Current.MainWindow; + mw?.ShowError("Error Collecting Feedback", "An error occurred while trying to gather feedback.\nIs the monitor service running?"); + return; + } + string pathToLogs = resp.Message; + logger.Info("Log files found at : {0}", resp.Message); + mailMessage.Attachments.Add(new Attachment(pathToLogs)); + + string emlFile = Path.Combine(Path.GetTempPath(), timestamp + "-ziti.eml"); + + using (var filestream = File.Open(emlFile, FileMode.Create)) { + var binaryWriter = new BinaryWriter(filestream); + binaryWriter.Write(System.Text.Encoding.UTF8.GetBytes("X-Unsent: 1" + Environment.NewLine)); + var assembly = typeof(SmtpClient).Assembly; + var mailWriterType = assembly.GetType("System.Net.Mail.MailWriter"); + var mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null); + var mailWriter = mailWriterContructor.Invoke(new object[] { filestream }); + var sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic); + sendMethod.Invoke(mailMessage, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { mailWriter, true, true }, null); + var closeMethod = mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic); + closeMethod.Invoke(mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null); + } + var p = Process.Start(emlFile); + if (p != null) { + p.Exited += (object lambdaSender, EventArgs lambdaEventArgs) => { + logger.Info("Removing temp file: {0}", emlFile); + File.Delete(emlFile); + }; + p.EnableRaisingEvents = true; + } else { + logger.Debug("process was null. most likely the email file format was not known when the process tried to start"); + } + } catch (Exception ex) { + logger.Warn(ex, "An unexpected error has occurred when submitting feedback? {0}", ex.Message); + } + MainWindow.HideLoad(); + } + + private void ShowSupport(object sender, MouseButtonEventArgs e) { + Process.Start(new ProcessStartInfo("https://openziti.discourse.group/") { UseShellExecute = true }); + } + + private void DetachWindow(object sender, MouseButtonEventArgs e) { + Application.Current.MainWindow.ShowInTaskbar = true; + DetachButton.Visibility = Visibility.Collapsed; + AttachButton.Visibility = Visibility.Visible; + Arrow.Visibility = Visibility.Collapsed; + if (OnAttachmentChange != null) { + OnAttachmentChange(false); + } + MainMenuArea.Visibility = Visibility.Collapsed; + } + + public void Detach() { + Application.Current.MainWindow.ShowInTaskbar = true; + DetachButton.Visibility = Visibility.Collapsed; + AttachButton.Visibility = Visibility.Visible; + Arrow.Visibility = Visibility.Collapsed; + } + private void RetachWindow(object sender, MouseButtonEventArgs e) { + Application.Current.MainWindow.ShowInTaskbar = false; + DetachButton.Visibility = Visibility.Visible; + AttachButton.Visibility = Visibility.Collapsed; + Arrow.Visibility = Visibility.Visible; + if (OnAttachmentChange != null) { + OnAttachmentChange(true); + } + } + + private void ResetLevels() { + if (this.LogLevel == "") this.LogLevel = "error"; + LogVerbose.IsSelected = false; + LogDebug.IsSelected = false; + LogInfo.IsSelected = false; + LogError.IsSelected = false; + LogFatal.IsSelected = false; + LogWarn.IsSelected = false; + LogTrace.IsSelected = false; + if (this.LogLevel == "verbose") LogVerbose.IsSelected = true; + else if (this.LogLevel == "debug") LogDebug.IsSelected = true; + else if (this.LogLevel == "info") LogInfo.IsSelected = true; + else if (this.LogLevel == "error") LogError.IsSelected = true; + else if (this.LogLevel == "fatal") LogFatal.IsSelected = true; + else if (this.LogLevel == "warn") LogWarn.IsSelected = true; + else if (this.LogLevel == "trace") LogTrace.IsSelected = true; + } + + private void SetLevel(object sender, MouseButtonEventArgs e) { + SubOptionItem item = (SubOptionItem)sender; + this.LogLevel = item.Label.ToLower(); + if (OnLogLevelChanged != null) { + OnLogLevelChanged(this.LogLevel); + } + ResetLevels(); + } + + private void SetReleaseStream() { + this.ReleaseStreamItemBeta.IsSelected = isBeta; + this.ReleaseStreamItemStable.IsSelected = !isBeta; + } + + async private void CheckForUpdate_Click(object sender, RoutedEventArgs e) { + logger.Info("checking for update..."); + try { + CheckForUpdate.IsEnabled = false; + CheckForUpdateStatus.Content = "Checking for update..."; + CheckForUpdateStatus.Visibility = Visibility.Visible; + var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; + var r = await monitorClient.DoUpdateCheck(); + checkResponse(r, "Error When Checking for Update", "An error occurred while trying check for update."); + CheckForUpdateStatus.Content = r.Message; + if (r.UpdateAvailable) { + TriggerUpdateButton.Visibility = Visibility.Visible; + } else { + TriggerUpdateButton.Visibility = Visibility.Collapsed; + } + } catch (Exception ex) { + logger.Error(ex, "unexpected error in update check: {0}", ex.Message); + } + CheckForUpdate.IsEnabled = true; + } + + async public void TriggerUpdate_Click(object sender, RoutedEventArgs e) { + try { + CheckForUpdate.IsEnabled = false; + TriggerUpdateButton.IsEnabled = false; + CheckForUpdateStatus.Content = "Requesting automatic update..."; + var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; + var r = await monitorClient.TriggerUpdate(); + CheckForUpdateStatus.Content = "Automatic update requested..."; + checkResponse(r, "Error When Triggering Update", "An error occurred while trying to trigger the update."); + } catch (Exception ex) { + logger.Error(ex, "unexpected error in update check: {0}", ex.Message); + } + TriggerUpdateButton.IsEnabled = true; + CheckForUpdate.IsEnabled = true; + } + + public void SetupIdList(ZitiIdentity[] ids) { + IdListView.Children.Clear(); + for (int i=0; i { + VersionOlder.Content = msg; + VersionNewer.Content = ""; + VersionOlder.Visibility = Visibility.Visible; + VersionNewer.Visibility = Visibility.Collapsed; + }); + } + public void SetAppIsNewer(string msg) { + this.Dispatcher.Invoke(() => { + VersionNewer.Content = msg; + VersionOlder.Content = ""; + VersionNewer.Visibility = Visibility.Visible; + VersionOlder.Visibility = Visibility.Collapsed; + }); + } + + /// + /// Save the config information to the properties and queue for update. + /// + async private void UpdateConfig() { + logger.Info("updating config..."); + DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; + try { + ComboBoxItem item = (ComboBoxItem)ConfigMaskNew.SelectedValue; + var newMaskVar = Int32.Parse(item.Tag.ToString()); + var addDnsNewVar = Convert.ToBoolean(AddDnsNew.IsChecked); + + var r = await client.UpdateConfigAsync(ConfigIpNew.Text, newMaskVar, addDnsNewVar); + if (r.Code != 0) { + this.OnShowBlurb?.Invoke("Error: " + r.Error); + logger.Debug("ERROR: {0} : {1}", r.Message, r.Error); + } else { + this.OnShowBlurb?.Invoke("Config Save, Please Restart Ziti to Update"); + this.CloseEdit(); + } + logger.Info("Got response from update config task : {0}", r); + } catch (DataStructures.ServiceException se) { + this.OnShowBlurb?.Invoke("Error: " + se.Message); + logger.Error(se, "service exception in update check: {0}", se.Message); + } catch (Exception ex) { + this.OnShowBlurb?.Invoke("Error: " + ex.Message); + logger.Error(ex, "unexpected error in update check: {0}", ex.Message); + } + } + + /// + /// Show the Edit Modal and blur the background + /// + private void ShowEdit() { + ConfigIpNew.Text = ConfigIp.Value; + for (int i=0; i0) { + ConfigMaskNew.SelectedIndex = i; + break; + } + } + EditArea.Opacity = 0; + EditArea.Visibility = Visibility.Visible; + EditArea.Margin = new Thickness(0, 0, 0, 0); + EditArea.BeginAnimation(Grid.OpacityProperty, new DoubleAnimation(1, TimeSpan.FromSeconds(.3))); + EditArea.BeginAnimation(Grid.MarginProperty, new ThicknessAnimation(new Thickness(30, 30, 30, 30), TimeSpan.FromSeconds(.3))); + ShowModal(); + } + + /// + /// Hide the Edit Config + /// + private void CloseEdit() { + DoubleAnimation animation = new DoubleAnimation(0, TimeSpan.FromSeconds(.3)); + ThicknessAnimation animateThick = new ThicknessAnimation(new Thickness(0, 0, 0, 0), TimeSpan.FromSeconds(.3)); + animation.Completed += CloseComplete; + EditArea.BeginAnimation(Grid.OpacityProperty, animation); + EditArea.BeginAnimation(Grid.MarginProperty, animateThick); + HideModal(); + } + + /// + /// Show the modal, aniimating opacity + /// + private void ShowModal() { + ModalBg.Visibility = Visibility.Visible; + ModalBg.Opacity = 0; + DoubleAnimation animation = new DoubleAnimation(.8, TimeSpan.FromSeconds(.3)); + ModalBg.BeginAnimation(Grid.OpacityProperty, animation); + } + + /// + /// Close the config window + /// + /// The close button + /// The event arguments + private void CloseComplete(object sender, EventArgs e) { + EditArea.Visibility = Visibility.Collapsed; + } + + /// + /// Hide the modal animating the opacity + /// + private void HideModal() { + DoubleAnimation animation = new DoubleAnimation(0, TimeSpan.FromSeconds(.3)); + animation.Completed += ModalHideComplete; + ModalBg.BeginAnimation(Grid.OpacityProperty, animation); + } + + /// + /// When the animation completes, set the visibility to avoid UI object conflicts + /// + /// The animation + /// The event + private void ModalHideComplete(object sender, EventArgs e) { + ModalBg.Visibility = Visibility.Collapsed; + } + + /// + /// Close the config editor without saving + /// + /// The image button + /// The click event + private void CloseEditConfig(object sender, MouseButtonEventArgs e) { + CloseEdit(); + } + + private void SaveConfig() { + this.UpdateConfig(); + } + } } \ No newline at end of file From 570a141f29188abe73437a45e68328fd6ce66e37 Mon Sep 17 00:00:00 2001 From: Jeremy Tellier - ROG Date: Fri, 16 Apr 2021 12:54:17 +0100 Subject: [PATCH 15/36] Infinite Scroll --- .../Views/Screens/IdentityDetails.xaml | 3 - .../Views/Screens/IdentityDetails.xaml.cs | 97 +++++++++---------- 2 files changed, 48 insertions(+), 52 deletions(-) diff --git a/DesktopEdge/Views/Screens/IdentityDetails.xaml b/DesktopEdge/Views/Screens/IdentityDetails.xaml index 4b3e088a..58697fef 100644 --- a/DesktopEdge/Views/Screens/IdentityDetails.xaml +++ b/DesktopEdge/Views/Screens/IdentityDetails.xaml @@ -91,9 +91,6 @@ - - - Name diff --git a/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs b/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs index af592485..d13ebc27 100644 --- a/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs +++ b/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs @@ -40,6 +40,8 @@ namespace ZitiDesktopEdge { public int TotalPages = 1; public string SortBy = "Name"; public string SortWay = "Asc"; + private bool _loaded = false; + private double scrolledTo = 0; internal MainWindow MainWindow { get; set; } @@ -56,6 +58,8 @@ namespace ZitiDesktopEdge { return _identity; } set { + _loaded = false; + scrolledTo = 0; _identity = value; this.IdDetailToggle.Enabled = _identity.IsEnabled; Page = 1; @@ -98,6 +102,10 @@ namespace ZitiDesktopEdge { } public void UpdateView() { + ServiceScroller.InvalidateScrollInfo(); + ServiceScroller.ScrollToVerticalOffset(0); + ServiceScroller.InvalidateScrollInfo(); + scrolledTo = 0; IdDetailName.Text = _identity.Name; IdDetailName.ToolTip = _identity.Name; IdDetailToggle.Enabled = _identity.IsEnabled; @@ -142,7 +150,7 @@ namespace ZitiDesktopEdge { for (int i= startIndex; i= 0 || zitiSvc.ToString().ToLower().IndexOf(filter.ToLower()) >= 0) { Logger.Trace("painting: " + zitiSvc.Name); ServiceInfo info = new ServiceInfo(); @@ -155,16 +163,7 @@ namespace ZitiDesktopEdge { } } - if (Page==1) { - Pages.Items.Clear(); - 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); - } - } + TotalPages = (total / PerPage) + 1; double newHeight = MainHeight - 330; ServiceRow.Height = new GridLength((double)newHeight); @@ -197,6 +196,7 @@ namespace ZitiDesktopEdge { } } ConfirmView.Visibility = Visibility.Collapsed; + _loaded = true; } private void ShowDetails(ZitiService info) { @@ -365,17 +365,6 @@ namespace ZitiDesktopEdge { 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) { @@ -397,36 +386,46 @@ namespace ZitiDesktopEdge { } private void Scrolled(object sender, ScrollChangedEventArgs e) { - var verticalOffset = ServiceScroller.VerticalOffset; - var maxVerticalOffset = ServiceScroller.ScrollableHeight; + if (_loaded) { + var verticalOffset = ServiceScroller.VerticalOffset; + var maxVerticalOffset = ServiceScroller.ScrollableHeight; - if (maxVerticalOffset < 0 || - verticalOffset == maxVerticalOffset) { - if (Page < TotalPages) { - Page += 1; - 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 < services.Length; i++) { - ZitiService zitiSvc = services[i]; - total++; - if (index < 100) { - 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); - index++; + if ((maxVerticalOffset < 0 || verticalOffset == maxVerticalOffset) && verticalOffset>0 && scrolledTo 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 < services.Length; i++) { + ZitiService zitiSvc = services[i]; + if (index < PerPage) { + if (zitiSvc.Name.ToLower().IndexOf(filter.ToLower()) >= 0 || zitiSvc.ToString().ToLower().IndexOf(filter.ToLower()) >= 0) { + ServiceInfo info = new ServiceInfo(); + info.Info = zitiSvc; + info.OnMessage += Info_OnMessage; + info.OnDetails += ShowDetails; + ServiceList.Children.Add(info); + index++; + } } } + double totalOffset = ServiceScroller.VerticalOffset; + double toNegate = index * 33; + double scrollTo = (totalOffset - toNegate); + ServiceScroller.InvalidateScrollInfo(); + ServiceScroller.ScrollToVerticalOffset(verticalOffset); + ServiceScroller.InvalidateScrollInfo(); + _loaded = true; + ServiceScroller.ScrollChanged += Scrolled; } } } From c5751307beae1af75b66e270ac8fb6c525002cb0 Mon Sep 17 00:00:00 2001 From: Jeremy Tellier - ROG Date: Fri, 16 Apr 2021 21:54:08 +0100 Subject: [PATCH 16/36] New Layout for Details. --- DesktopEdge/App.xaml | 119 ++++++++++++++++++ DesktopEdge/Assets/Images/disconnected.png | Bin 0 -> 5208 bytes DesktopEdge/Assets/Images/name.png | Bin 0 -> 3465 bytes DesktopEdge/Assets/Images/statusconnected.png | Bin 0 -> 3803 bytes DesktopEdge/MainWindow.xaml | 5 +- DesktopEdge/MainWindow.xaml.cs | 16 ++- DesktopEdge/Models/FilterData.cs | 22 ++++ DesktopEdge/Views/Controls/StyledButton.xaml | 5 + .../Views/Controls/StyledButton.xaml.cs | 20 ++- DesktopEdge/Views/ItemRenderers/Filter.xaml | 36 ++++++ .../Views/ItemRenderers/Filter.xaml.cs | 106 ++++++++++++++++ .../Views/ItemRenderers/IdentityItem.xaml.cs | 2 - .../Views/ItemRenderers/MenuEditItem.xaml | 1 - .../Views/ItemRenderers/MenuEditSearch.xaml | 2 +- .../ItemRenderers/MenuIdentityItem.xaml.cs | 1 - .../Views/Screens/IdentityDetails.xaml | 103 ++++----------- .../Views/Screens/IdentityDetails.xaml.cs | 116 ++++++++--------- DesktopEdge/ZitiDesktopEdge.csproj | 13 ++ 18 files changed, 418 insertions(+), 149 deletions(-) create mode 100644 DesktopEdge/Assets/Images/disconnected.png create mode 100644 DesktopEdge/Assets/Images/name.png create mode 100644 DesktopEdge/Assets/Images/statusconnected.png create mode 100644 DesktopEdge/Models/FilterData.cs create mode 100644 DesktopEdge/Views/ItemRenderers/Filter.xaml create mode 100644 DesktopEdge/Views/ItemRenderers/Filter.xaml.cs diff --git a/DesktopEdge/App.xaml b/DesktopEdge/App.xaml index 356176f8..8d816d24 100644 --- a/DesktopEdge/App.xaml +++ b/DesktopEdge/App.xaml @@ -449,6 +449,125 @@ + + + + + + diff --git a/DesktopEdge/Assets/Images/disconnected.png b/DesktopEdge/Assets/Images/disconnected.png new file mode 100644 index 0000000000000000000000000000000000000000..5853d7a6f0214cb30f0c884a9339bc040e6a22c6 GIT binary patch literal 5208 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 literal 0 HcmV?d00001 diff --git a/DesktopEdge/Assets/Images/name.png b/DesktopEdge/Assets/Images/name.png new file mode 100644 index 0000000000000000000000000000000000000000..0897340fda49a9241570c91716d59e6fcc5665dc GIT binary patch literal 3465 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 literal 0 HcmV?d00001 diff --git a/DesktopEdge/Assets/Images/statusconnected.png b/DesktopEdge/Assets/Images/statusconnected.png new file mode 100644 index 0000000000000000000000000000000000000000..d558909d279109b3c6b3a843a62a6f5570bc00e2 GIT binary patch literal 3803 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 literal 0 HcmV?d00001 diff --git a/DesktopEdge/MainWindow.xaml b/DesktopEdge/MainWindow.xaml index 9b10b302..d7d4e470 100644 --- a/DesktopEdge/MainWindow.xaml +++ b/DesktopEdge/MainWindow.xaml @@ -217,7 +217,7 @@ - + @@ -247,7 +247,8 @@ - + + diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index 0c1ddef9..727a29e2 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -531,7 +531,7 @@ namespace ZitiDesktopEdge { } private void MainMenu_OnShowBlurb(string message) { - _ = ShowBlurbAsync(message, ""); + _ = ShowBlurbAsync(message, "", "info"); } private void ServiceClient_OnBulkServiceEvent(object sender, BulkServiceEvent e) { @@ -1297,7 +1297,14 @@ namespace ZitiDesktopEdge { /// /// The message to show /// The url or action name to execute - public async Task ShowBlurbAsync(string message, string url) { + public async Task ShowBlurbAsync(string message, string url, string level="error") { + RedBlurb.Visibility = Visibility.Collapsed; + InfoBlurb.Visibility = Visibility.Collapsed; + if (level=="error") { + RedBlurb.Visibility = Visibility.Visible; + } else { + InfoBlurb.Visibility = Visibility.Visible; + } Blurb.Content = message; _blurbUrl = url; BlurbArea.Visibility = Visibility.Visible; @@ -1387,6 +1394,11 @@ namespace ZitiDesktopEdge { someCommand = value; } } + + private void DoLoading(bool isComplete) { + if (isComplete) HideLoad(); + else ShowLoad("Loading", "Please Wait."); + } } public class ActionCommand : ICommand { diff --git a/DesktopEdge/Models/FilterData.cs b/DesktopEdge/Models/FilterData.cs new file mode 100644 index 00000000..408000e9 --- /dev/null +++ b/DesktopEdge/Models/FilterData.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ZitiDesktopEdge.Models { + public class FilterData { + + public FilterData():this("", "", "asc") { } + + public FilterData(string searchFor, string sortBy, string sortHow) { + SearchFor = searchFor; + SortBy = sortBy; + SortHow = sortHow; + } + + public string SearchFor { get; set; } + public string SortBy { get; set; } + public string SortHow { get; set; } + } +} diff --git a/DesktopEdge/Views/Controls/StyledButton.xaml b/DesktopEdge/Views/Controls/StyledButton.xaml index 5bb623f8..51d11a1d 100644 --- a/DesktopEdge/Views/Controls/StyledButton.xaml +++ b/DesktopEdge/Views/Controls/StyledButton.xaml @@ -20,6 +20,11 @@ + + + + + diff --git a/DesktopEdge/Views/Controls/StyledButton.xaml.cs b/DesktopEdge/Views/Controls/StyledButton.xaml.cs index 086f0cfe..c6f44b23 100644 --- a/DesktopEdge/Views/Controls/StyledButton.xaml.cs +++ b/DesktopEdge/Views/Controls/StyledButton.xaml.cs @@ -23,6 +23,15 @@ namespace ZitiDesktopEdge { public delegate void ClickAction(); public event ClickAction OnClick; private string _label = ""; + private string bgColor = "#0069FF"; + + public string BgColor { + get { return bgColor; } + set { + bgColor = value; + ButtonBgColor.Color = (Color)ColorConverter.ConvertFromString(bgColor); + } + } public string Label { get { @@ -44,8 +53,8 @@ namespace ZitiDesktopEdge { /// The button object /// The mouse event private void Hover(object sender, MouseEventArgs e) { - ButtonBg.Opacity = 0.8; - ButtonBg.BeginAnimation(Grid.OpacityProperty, new DoubleAnimation(1.0, TimeSpan.FromSeconds(.3))); + ButtonBgDarken.Opacity = 0.0; + ButtonBgDarken.BeginAnimation(Grid.OpacityProperty, new DoubleAnimation(0.2, TimeSpan.FromSeconds(.3))); } /// @@ -54,9 +63,8 @@ namespace ZitiDesktopEdge { /// The button object /// The mouse event private void Leave(object sender, MouseEventArgs e) { - ButtonBgColor.Color = Color.FromRgb(0, 104, 249); - ButtonBg.BeginAnimation(Grid.OpacityProperty, null); - ButtonBg.Opacity = 0.8; + ButtonBgDarken.Opacity = 0.2; + ButtonBgDarken.BeginAnimation(Grid.OpacityProperty, new DoubleAnimation(0.0, TimeSpan.FromSeconds(.3))); } /// @@ -65,7 +73,7 @@ namespace ZitiDesktopEdge { /// /// private void Down(object sender, MouseButtonEventArgs e) { - ButtonBgColor.Color = Color.FromRgb(126, 180, 255); + // ButtonBgColor.Color = Color.FromRgb(126, 180, 255); } /// diff --git a/DesktopEdge/Views/ItemRenderers/Filter.xaml b/DesktopEdge/Views/ItemRenderers/Filter.xaml new file mode 100644 index 00000000..33777664 --- /dev/null +++ b/DesktopEdge/Views/ItemRenderers/Filter.xaml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + Name + Address + Protocol + Port + + + Asc + Desc + + + + diff --git a/DesktopEdge/Views/ItemRenderers/Filter.xaml.cs b/DesktopEdge/Views/ItemRenderers/Filter.xaml.cs new file mode 100644 index 00000000..1c39c4b8 --- /dev/null +++ b/DesktopEdge/Views/ItemRenderers/Filter.xaml.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using System.Timers; +using ZitiDesktopEdge.Models; + +namespace ZitiDesktopEdge { + /// + /// Interaction logic for Filter.xaml + /// + public partial class Filter :UserControl { + + public delegate void OnFilterEvent(FilterData filter); + public event OnFilterEvent OnFilter; + public string placeholder = "any text"; + private static Timer timeout; + + private FilterData filter = new FilterData("", "Name", "Asc"); + public Filter() { + InitializeComponent(); + } + + public void Clear() { + FilterFor.Text = ""; + filter.SearchFor = ""; + FilterFor.Text = placeholder; + SortWayField.SelectedIndex = 0; + SortByField.SelectedIndex = 0; + } + + private void FilterPressed(object sender, KeyEventArgs e) { + if (e.Key==Key.Enter) { + OnFilter?.Invoke(filter); + } + } + + private void FilterChanged(object sender, KeyEventArgs e) { + string search = FilterFor.Text.Trim(); + if (filter.SearchFor!=search) { + filter.SearchFor = search; + if (filter.SearchFor == placeholder) filter.SearchFor = ""; + + if (e.Key==Key.Enter) { + OnFilter?.Invoke(filter); + } else { + if (timeout != null && timeout.Enabled) { + timeout.Close(); + } + timeout = new Timer(1000); + timeout.Elapsed += OnTimedEvent; + timeout.AutoReset = false; + timeout.Enabled = true; + } + } + } + + private void SortWayChanged(object sender, SelectionChangedEventArgs e) { + ComboBoxItem selected = (ComboBoxItem)SortWayField.SelectedValue; + if (selected != null && selected.Content != null) { + if (selected.Content.ToString() != filter.SortHow) { + filter.SortHow = selected.Content.ToString(); + this.OnFilter?.Invoke(filter); + } + } + } + + private void SortByChanged(object sender, SelectionChangedEventArgs e) { + ComboBoxItem selected = (ComboBoxItem)SortByField.SelectedValue; + if (selected != null && selected.Content != null) { + if (selected.Content.ToString() != filter.SortBy) { + filter.SortBy = selected.Content.ToString(); + this.OnFilter?.Invoke(filter); + } + } + } + + private void FocusFilter(object sender, RoutedEventArgs e) { + if (FilterFor.Text==placeholder) { + FilterFor.Text = ""; + } + } + + private void FocusLostFilter(object sender, RoutedEventArgs e) { + if (FilterFor.Text.Trim() == "") { + FilterFor.Text = placeholder; + } + } + + private void OnTimedEvent(Object source, ElapsedEventArgs e) { + this.Dispatcher.Invoke(() => { + OnFilter?.Invoke(filter); + }); + } + } +} diff --git a/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml.cs b/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml.cs index 1b75ed8e..32ca433e 100644 --- a/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml.cs +++ b/DesktopEdge/Views/ItemRenderers/IdentityItem.xaml.cs @@ -107,8 +107,6 @@ namespace ZitiDesktopEdge { private void OpenDetails(object sender, MouseButtonEventArgs e) { IdentityDetails deets = ((MainWindow)Application.Current.MainWindow).IdentityMenu; deets.SelectedIdentity = this; - deets.ServiceTitle.Clear(); - deets.IdDetailToggle.Enabled = this.Identity.IsEnabled; deets.Identity = this.Identity; } diff --git a/DesktopEdge/Views/ItemRenderers/MenuEditItem.xaml b/DesktopEdge/Views/ItemRenderers/MenuEditItem.xaml index 3bebb7db..2e843e7c 100644 --- a/DesktopEdge/Views/ItemRenderers/MenuEditItem.xaml +++ b/DesktopEdge/Views/ItemRenderers/MenuEditItem.xaml @@ -15,6 +15,5 @@ - \ No newline at end of file diff --git a/DesktopEdge/Views/ItemRenderers/MenuEditSearch.xaml b/DesktopEdge/Views/ItemRenderers/MenuEditSearch.xaml index d40627ac..02d1bc3f 100644 --- a/DesktopEdge/Views/ItemRenderers/MenuEditSearch.xaml +++ b/DesktopEdge/Views/ItemRenderers/MenuEditSearch.xaml @@ -21,7 +21,7 @@ diff --git a/DesktopEdge/Views/ItemRenderers/MenuIdentityItem.xaml.cs b/DesktopEdge/Views/ItemRenderers/MenuIdentityItem.xaml.cs index 1244c1fb..36586978 100644 --- a/DesktopEdge/Views/ItemRenderers/MenuIdentityItem.xaml.cs +++ b/DesktopEdge/Views/ItemRenderers/MenuIdentityItem.xaml.cs @@ -64,7 +64,6 @@ namespace ZitiDesktopEdge { private void ShowIdentity(object sender, MouseButtonEventArgs e) { IdentityDetails deets = ((MainWindow)Application.Current.MainWindow).IdentityMenu; deets.SelectedIdentityMenu = this; - deets.IdDetailToggle.Enabled = this.Identity.IsEnabled; deets.Identity = this.Identity; } } diff --git a/DesktopEdge/Views/Screens/IdentityDetails.xaml b/DesktopEdge/Views/Screens/IdentityDetails.xaml index 58697fef..69b141e2 100644 --- a/DesktopEdge/Views/Screens/IdentityDetails.xaml +++ b/DesktopEdge/Views/Screens/IdentityDetails.xaml @@ -20,100 +20,51 @@ - + - - + + - + - + - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - Name - Address - Protocol - Port - - - - - - - Asc - Desc - - - - - + + - diff --git a/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs b/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs index d13ebc27..2e383c98 100644 --- a/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs +++ b/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs @@ -35,6 +35,9 @@ namespace ZitiDesktopEdge { public event OnAuthenticate Authenticate; public delegate void OnRecovery(ZitiIdentity identity); public event OnRecovery Recovery; + public delegate void LoadingEvent(bool isComplete); + public event LoadingEvent OnLoading; + public int Page = 1; public int PerPage = 50; public int TotalPages = 1; @@ -42,6 +45,7 @@ namespace ZitiDesktopEdge { public string SortWay = "Asc"; private bool _loaded = false; private double scrolledTo = 0; + public int totalServices = 0; internal MainWindow MainWindow { get; set; } @@ -59,14 +63,13 @@ namespace ZitiDesktopEdge { } set { _loaded = false; + FilterServices.Clear(); scrolledTo = 0; _identity = value; - this.IdDetailToggle.Enabled = _identity.IsEnabled; Page = 1; SortBy = "Name"; SortWay = "Asc"; - SortByField.SelectedIndex = 0; - SortWayField.SelectedIndex = 0; + filter = ""; UpdateView(); IdentityArea.Opacity = 1.0; IdentityArea.Visibility = Visibility.Visible; @@ -108,14 +111,20 @@ namespace ZitiDesktopEdge { scrolledTo = 0; IdDetailName.Text = _identity.Name; IdDetailName.ToolTip = _identity.Name; - IdDetailToggle.Enabled = _identity.IsEnabled; - IdentityName.Value = _identity.Name; - IdentityNetwork.Value = _identity.ControllerUrl; - IdentityEnrollment.Value = _identity.EnrollmentStatus; - IdentityStatus.Value = _identity.IsEnabled ? "active" : "disabled"; IdentityMFA.IsOn = _identity.IsMFAEnabled; IdentityMFA.ToggleField.IsEnabled = true; IdentityMFA.ToggleField.Opacity = 1; + IsConnected.Visibility = Visibility.Collapsed; + IsDisconnected.Visibility = Visibility.Collapsed; + IsConnected.ToolTip = "Enabled - Click To Disable"; + IsDisconnected.ToolTip = "Disabled - Click to Enable"; + IdServer.Value = _identity.ControllerUrl; + IdName.Value = _identity.Name; + if (_identity.IsEnabled) { + IsConnected.Visibility = Visibility.Visible; + } else { + IsDisconnected.Visibility = Visibility.Visible; + } if (_identity.IsMFAEnabled) { if (_identity.MFAInfo.IsAuthenticated) { IdentityMFA.ToggleField.IsEnabled = true; @@ -135,9 +144,10 @@ namespace ZitiDesktopEdge { IdentityMFA.RecoveryButton.Visibility = Visibility.Collapsed; } ServiceList.Children.Clear(); - PageSortArea.Visibility = Visibility.Collapsed; + + totalServices = _identity.Services.Count; + if (_identity.Services.Count>0) { - PageSortArea.Visibility = Visibility.Visible; int index = 0; int total = 0; ZitiService[] services = new ZitiService[0]; @@ -165,31 +175,21 @@ namespace ZitiDesktopEdge { TotalPages = (total / PerPage) + 1; - double newHeight = MainHeight - 330; - ServiceRow.Height = new GridLength((double)newHeight); + double newHeight = MainHeight - 330; MainDetailScroll.MaxHeight = newHeight; MainDetailScroll.Height = newHeight; MainDetailScroll.Visibility = Visibility.Visible; - ServiceTitle.Label = _identity.Services.Count + " Services"; - ServiceTitle.MainEdit.Visibility = Visibility.Visible; - ServiceTitle.Visibility = Visibility.Visible; + AuthMessageBg.Visibility = Visibility.Collapsed; AuthMessageLabel.Visibility = Visibility.Collapsed; NoAuthServices.Visibility = Visibility.Collapsed; } else { - ServiceRow.Height = new GridLength((double)0.0); MainDetailScroll.Visibility = Visibility.Collapsed; - ServiceTitle.Label = "No Services"; - ServiceTitle.MainEdit.Text = ""; - ServiceTitle.MainEdit.Visibility = Visibility.Collapsed; if (this._identity.IsMFAEnabled&&!this._identity.MFAInfo.IsAuthenticated) { - ServiceTitle.Visibility = Visibility.Collapsed; AuthMessageBg.Visibility = Visibility.Visible; AuthMessageLabel.Visibility = Visibility.Visible; - ServiceRow.Height = new GridLength((double)30); NoAuthServices.Visibility = Visibility.Visible; } else { - ServiceTitle.Visibility = Visibility.Visible; AuthMessageBg.Visibility = Visibility.Collapsed; AuthMessageLabel.Visibility = Visibility.Collapsed; NoAuthServices.Visibility = Visibility.Collapsed; @@ -258,15 +258,6 @@ namespace ZitiDesktopEdge { OnMessage?.Invoke(message); } - async private void IdToggle(bool on) { - DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; - await client.IdentityOnOffAsync(_identity.Fingerprint, on); - if (SelectedIdentity!=null) SelectedIdentity.ToggleSwitch.Enabled = on; - if (SelectedIdentityMenu != null) SelectedIdentityMenu.ToggleSwitch.Enabled = on; - _identity.IsEnabled = on; - IdentityStatus.Value = _identity.IsEnabled ? "active" : "disabled"; - } - public IdentityDetails() { InitializeComponent(); } @@ -278,7 +269,7 @@ namespace ZitiDesktopEdge { MainDetailScroll.Height = height; } - private void ForgetIdentity(object sender, MouseButtonEventArgs e) { + private void ForgetIdentity() { if (this.Visibility==Visibility.Visible&&ConfirmView.Visibility==Visibility.Collapsed) { ConfirmView.Visibility = Visibility.Visible; } @@ -314,12 +305,6 @@ namespace ZitiDesktopEdge { } } - private void DoFilter(string filter) { - this.filter = filter; - if (this._identity!=null) UpdateView(); - } - - private void ToggleMFA(bool isOn) { this.OnMFAToggled?.Invoke(isOn); } @@ -365,26 +350,6 @@ namespace ZitiDesktopEdge { this.Authenticate.Invoke(this.Identity); } - 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(); - } - } - } - private void Scrolled(object sender, ScrollChangedEventArgs e) { if (_loaded) { var verticalOffset = ServiceScroller.VerticalOffset; @@ -430,5 +395,40 @@ namespace ZitiDesktopEdge { } } } + + private void DoFilter(FilterData filterData) { + filter = filterData.SearchFor; + SortBy = filterData.SortBy; + SortWay = filterData.SortHow; + UpdateView(); + } + + async private void DoConnect(object sender, MouseButtonEventArgs e) { + this.OnLoading?.Invoke(false); + DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; + await client.IdentityOnOffAsync(_identity.Fingerprint, true); + if (SelectedIdentity != null) SelectedIdentity.ToggleSwitch.Enabled = true; + if (SelectedIdentityMenu != null) SelectedIdentityMenu.ToggleSwitch.Enabled = true; + _identity.IsEnabled = true; + IsConnected.Visibility = Visibility.Visible; + IsDisconnected.Visibility = Visibility.Collapsed; + this.OnLoading?.Invoke(true); + } + + async private void DoDisconnect(object sender, MouseButtonEventArgs e) { + this.OnLoading?.Invoke(false); + DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; + await client.IdentityOnOffAsync(_identity.Fingerprint, false); + if (SelectedIdentity != null) SelectedIdentity.ToggleSwitch.Enabled = false; + if (SelectedIdentityMenu != null) SelectedIdentityMenu.ToggleSwitch.Enabled = false; + _identity.IsEnabled = false; + IsConnected.Visibility = Visibility.Collapsed; + IsDisconnected.Visibility = Visibility.Visible; + this.OnLoading?.Invoke(true); + } + + private void ForgetIdentityButton_OnClick() { + + } } } diff --git a/DesktopEdge/ZitiDesktopEdge.csproj b/DesktopEdge/ZitiDesktopEdge.csproj index b406e57b..a6ef0dc4 100644 --- a/DesktopEdge/ZitiDesktopEdge.csproj +++ b/DesktopEdge/ZitiDesktopEdge.csproj @@ -143,11 +143,15 @@ MSBuild:Compile Designer + StyledButton.xaml + + Filter.xaml + MenuEditSearch.xaml @@ -197,6 +201,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + MSBuild:Compile Designer @@ -447,5 +455,10 @@ + + + + + \ No newline at end of file From 1945e158cd076a9f9a089e3fde75508e51d02966 Mon Sep 17 00:00:00 2001 From: ziti-ci Date: Fri, 16 Apr 2021 21:06:23 +0000 Subject: [PATCH 17/36] [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 f7619a3b..14f28fab 100644 --- a/service/ziti-tunnel/version.go +++ b/service/ziti-tunnel/version.go @@ -21,8 +21,8 @@ package main const ( Version = "1.9.4" - Revision = "138ceebaefbf" + Revision = "c5751307beae" Branch = "release-next" BuildUser = "" - BuildDate = "2021-04-15 16:07:55" + BuildDate = "2021-04-16 21:00:50" ) From 71b125e6a4cf403c0c04d6750c7de4bd265ae1e0 Mon Sep 17 00:00:00 2001 From: Jeremy Tellier - ROG Date: Sat, 17 Apr 2021 15:07:08 +0100 Subject: [PATCH 18/36] Layout Tweaks --- DesktopEdge/MainWindow.xaml | 2 +- DesktopEdge/Views/ItemRenderers/Filter.xaml | 6 ++-- .../Views/ItemRenderers/ServiceInfo.xaml | 9 +++-- .../Views/ItemRenderers/ServiceInfo.xaml.cs | 35 +++++++++++++++++-- .../Views/Screens/IdentityDetails.xaml | 3 +- .../Views/Screens/IdentityDetails.xaml.cs | 1 + 6 files changed, 47 insertions(+), 9 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml b/DesktopEdge/MainWindow.xaml index d7d4e470..c6fd3c04 100644 --- a/DesktopEdge/MainWindow.xaml +++ b/DesktopEdge/MainWindow.xaml @@ -202,7 +202,7 @@ - + diff --git a/DesktopEdge/Views/ItemRenderers/Filter.xaml b/DesktopEdge/Views/ItemRenderers/Filter.xaml index 33777664..f44575bf 100644 --- a/DesktopEdge/Views/ItemRenderers/Filter.xaml +++ b/DesktopEdge/Views/ItemRenderers/Filter.xaml @@ -10,9 +10,9 @@ HorizontalAlignment="Stretch" d:DesignWidth="350" > - + - + - + Name Address diff --git a/DesktopEdge/Views/ItemRenderers/ServiceInfo.xaml b/DesktopEdge/Views/ItemRenderers/ServiceInfo.xaml index cbb7e818..1bf48ee7 100644 --- a/DesktopEdge/Views/ItemRenderers/ServiceInfo.xaml +++ b/DesktopEdge/Views/ItemRenderers/ServiceInfo.xaml @@ -10,6 +10,7 @@ + @@ -17,8 +18,12 @@ - - + + + + + + diff --git a/DesktopEdge/Views/ItemRenderers/ServiceInfo.xaml.cs b/DesktopEdge/Views/ItemRenderers/ServiceInfo.xaml.cs index 4534dc1e..e0e678d5 100644 --- a/DesktopEdge/Views/ItemRenderers/ServiceInfo.xaml.cs +++ b/DesktopEdge/Views/ItemRenderers/ServiceInfo.xaml.cs @@ -36,10 +36,41 @@ namespace ZitiDesktopEdge { } set { this._info = value; - MainEdit.ToolTip = this._info.ToString(); - MainEdit.Text = this._info.ToString(); + + string addresses = ""; + if (_info.Addresses!=null) { + for (int i = 0; i < this._info.Addresses?.Length; i++) { + addresses += ((i > 0) ? "," : "") + this._info.Addresses[i].Hostname; + } + } + + MainEdit.ToolTip = addresses; + MainEdit.Text = addresses; + MainLabel.ToolTip = this._info.Name; MainLabel.Text = this._info.Name; + + string ports = ""; + if (_info.Ports != null) { + for (int i = 0; i < this._info.Ports.Length; i++) { + ports += ((i > 0) ? "," : "") + this._info.Ports[i].ToString(); + } + } + + Ports.ToolTip = ports; + Ports.Text = ports; + + string protocols = ""; + + if (_info.Protocols != null) { + for (int i = 0; i < this._info.Protocols.Length; i++) { + protocols += ((i > 0) ? "," : "") + this._info.Protocols[i]; + } + } + + Protocols.ToolTip = protocols; + Protocols.Text = protocols; + WarningColumn.Width = new GridLength(0); if (this._info.Warning.Length > 0) { WarnIcon.ToolTip = this._info.Warning; diff --git a/DesktopEdge/Views/Screens/IdentityDetails.xaml b/DesktopEdge/Views/Screens/IdentityDetails.xaml index 69b141e2..becc065e 100644 --- a/DesktopEdge/Views/Screens/IdentityDetails.xaml +++ b/DesktopEdge/Views/Screens/IdentityDetails.xaml @@ -48,12 +48,13 @@ - + + diff --git a/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs b/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs index 2e383c98..227bff66 100644 --- a/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs +++ b/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs @@ -66,6 +66,7 @@ namespace ZitiDesktopEdge { FilterServices.Clear(); scrolledTo = 0; _identity = value; + ServiceCount.Content = _identity.Services.Count + " services"; Page = 1; SortBy = "Name"; SortWay = "Asc"; From a21605a1cf8b754d9febed34ce3a59a7acc68a11 Mon Sep 17 00:00:00 2001 From: ziti-ci Date: Sat, 17 Apr 2021 14:15:54 +0000 Subject: [PATCH 19/36] [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 14f28fab..ad8e8496 100644 --- a/service/ziti-tunnel/version.go +++ b/service/ziti-tunnel/version.go @@ -21,8 +21,8 @@ package main const ( Version = "1.9.4" - Revision = "c5751307beae" + Revision = "bf21f40f8dbc" Branch = "release-next" BuildUser = "" - BuildDate = "2021-04-16 21:00:50" + BuildDate = "2021-04-17 14:10:53" ) From cd51730b576dfbf3c086fcdaa1a445f3b2104d2a Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Sun, 18 Apr 2021 20:19:58 +0530 Subject: [PATCH 20/36] adding test nrpt policy function --- service/windns/windns.go | 48 ++++++++++++++++++++++++++++ service/ziti-tunnel/service/state.go | 26 +++++++-------- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/service/windns/windns.go b/service/windns/windns.go index ae2897c0..f31c03f4 100644 --- a/service/windns/windns.go +++ b/service/windns/windns.go @@ -238,3 +238,51 @@ ForEach ($ns in $toRemove){ log.Errorf("ERROR removing nrpt rules: %v", err) } } + +func IsNrptPoliciesEffective() bool { + script := fmt.Sprintf(`Add-DnsClientNrptRule -Namespace ".ziti.test" -NameServers "100.64.0.1" -Comment "Added by ziti-tunnel" -DisplayName "ziti-tunnel:.ziti.test" + Get-DnsClientNrptPolicy -Effective | Select-Object Namespace -Unique | Where-Object Namespace -Eq ".ziti.test"`) + log.Debugf("checking the nrpt policies with: %s", script) + + cmd := exec.Command("powershell", "-Command", script) + cmd.Stderr = os.Stdout + output := new(bytes.Buffer) + cmd.Stdout = output + + err := cmd.Run() + if err != nil { + log.Errorf("ERROR removing all nrpt rules: %v", err) + } + + policyFound := false + for { + l, err := output.ReadString('\n') + policyOut := strings.Trim(l, "\r\n") + if err != nil { + break + } + + if strings.Compare(policyOut, ".ziti.test") == 0 { + policyFound = true + log.Debug("The nrpt policies are effective in this client") + removeSingleNrtpRule(".ziti.test") + break + } + } + return policyFound +} + +func removeSingleNrtpRule(nrptRule string) { + script := fmt.Sprintf(`Get-DnsClientNrptRule | where Namespace -eq "%s" | Remove-DnsClientNrptRule -Force -ErrorAction SilentlyContinue`, nrptRule) + log.Debugf("Removing the nrpt rule with: %s", script) + + cmd := exec.Command("powershell", "-Command", script) + cmd.Stderr = os.Stdout + output := new(bytes.Buffer) + cmd.Stdout = output + + err := cmd.Run() + if err != nil { + log.Errorf("ERROR removing the nrpt rules: %v", err) + } +} diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index aa625adb..ce0cf91c 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -20,25 +20,26 @@ package service import ( "bufio" "encoding/json" + "errors" "fmt" + "github.com/openziti/desktop-edge-win/service/cziti" + "github.com/openziti/desktop-edge-win/service/windns" + "github.com/openziti/desktop-edge-win/service/ziti-tunnel/config" + "github.com/openziti/desktop-edge-win/service/ziti-tunnel/constants" + "github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto" + idcfg "github.com/openziti/sdk-golang/ziti/config" "golang.org/x/sys/windows" + "golang.org/x/sys/windows/registry" + "golang.zx2c4.com/wireguard/tun" + "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" "io" "io/ioutil" "net" "os" "path" + "strconv" "strings" "time" - "errors" - "strconv" - "github.com/openziti/desktop-edge-win/service/cziti" - "github.com/openziti/desktop-edge-win/service/ziti-tunnel/config" - "github.com/openziti/desktop-edge-win/service/ziti-tunnel/constants" - "github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto" - idcfg "github.com/openziti/sdk-golang/ziti/config" - "golang.org/x/sys/windows/registry" - "golang.zx2c4.com/wireguard/tun" - "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" ) type RuntimeState struct { @@ -107,7 +108,6 @@ func backupConfig() (string, error) { return backup, err } - func (t *RuntimeState) ToStatus(onlyInitialized bool) dto.TunnelStatus { var uptime int64 @@ -223,7 +223,8 @@ func (t *RuntimeState) CreateTun(ipv4 string, ipv4mask int, applyDns bool) (net. } log.Info("routing applied") - if applyDns { + zitiPoliciesEffective := windns.IsNrptPoliciesEffective() + if applyDns || !zitiPoliciesEffective { //for windows 10+, could 'domains' be able to replace NRPT? dunno - didn't test it luid.SetDNS(windows.AF_INET, []net.IP{ip}, nil) } @@ -428,7 +429,6 @@ func UpdateRuntimeStateIpv4(ip string, ipv4Mask int, addDns string) error { } rts.SaveState() - return nil } From d2b81c612c24898b84dac1a3081687e75501418c Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Sun, 18 Apr 2021 20:22:13 +0530 Subject: [PATCH 21/36] fixing format of code and log messages --- ZitiUpdateService/UpdateService.cs | 10 +++++----- service/ziti-tunnel/cli/service.go | 2 +- service/ziti-tunnel/cmd/update.go | 2 +- service/ziti-tunnel/dto/clidtos.go | 10 +++++----- service/ziti-tunnel/service/ipc.go | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ZitiUpdateService/UpdateService.cs b/ZitiUpdateService/UpdateService.cs index 57fdf030..529ae040 100644 --- a/ZitiUpdateService/UpdateService.cs +++ b/ZitiUpdateService/UpdateService.cs @@ -214,7 +214,7 @@ namespace ZitiUpdateService { } return zipName; } catch (Exception ex) { - Logger.Error(ex, "Unexpected error {0}", ex.Message); + Logger.Error(ex, "Unexpected error in generating system files {0}", ex.Message); return null; } } @@ -233,7 +233,7 @@ namespace ZitiUpdateService { process.Start(); process.WaitForExit(); } catch (Exception ex) { - Logger.Error(ex, "Unexpected error {0}", ex.Message); + Logger.Error(ex, "Unexpected error in outputIpconfigInfo {0}", ex.Message); } } @@ -251,7 +251,7 @@ namespace ZitiUpdateService { process.Start(); process.WaitForExit(); } catch (Exception ex) { - Logger.Error(ex, "Unexpected error {0}", ex.Message); + Logger.Error(ex, "Unexpected error in outputSystemInfo {0}", ex.Message); } } @@ -269,7 +269,7 @@ namespace ZitiUpdateService { process.Start(); process.WaitForExit(); } catch (Exception ex) { - Logger.Error(ex, "Unexpected error {0}", ex.Message); + Logger.Error(ex, "Unexpected error in outputDnsCache {0}", ex.Message); } } @@ -283,7 +283,7 @@ namespace ZitiUpdateService { string responseBody = resp.Content.ReadAsStringAsync().Result; File.WriteAllText(extIpFile, responseBody); } catch (Exception ex) { - Logger.Error(ex, "Unexpected error {0}", ex.Message); + Logger.Error(ex, "Unexpected error in outputExternalIP {0}", ex.Message); } } diff --git a/service/ziti-tunnel/cli/service.go b/service/ziti-tunnel/cli/service.go index dd6ebcfb..bda4320d 100644 --- a/service/ziti-tunnel/cli/service.go +++ b/service/ziti-tunnel/cli/service.go @@ -19,9 +19,9 @@ package cli import ( "github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto" + "net" "strconv" "strings" - "net" ) //GetIdentities is to fetch identities through cmdline diff --git a/service/ziti-tunnel/cmd/update.go b/service/ziti-tunnel/cmd/update.go index 25d2461c..a72d9958 100644 --- a/service/ziti-tunnel/cmd/update.go +++ b/service/ziti-tunnel/cmd/update.go @@ -37,7 +37,7 @@ var updateCmd = &cobra.Command{ flags := map[string]interface{}{} flags["CIDR"] = CIDR flags["AddDns"] = AddDns - cli.UpdateConfigIPSubnet(args,flags) + cli.UpdateConfigIPSubnet(args, flags) }, } diff --git a/service/ziti-tunnel/dto/clidtos.go b/service/ziti-tunnel/dto/clidtos.go index 6f7e840d..df93a954 100644 --- a/service/ziti-tunnel/dto/clidtos.go +++ b/service/ziti-tunnel/dto/clidtos.go @@ -27,11 +27,11 @@ type IdentityCli struct { } type ServiceCli struct { - Name string - Id string - Protocols string - Ports string - Addresses string + Name string + Id string + Protocols string + Ports string + Addresses string } type IdentityOnOffPayload struct { diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index d2343c10..f06e14ea 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -41,8 +41,8 @@ import ( "net" "os" "os/signal" - "strings" "strconv" + "strings" "sync" "time" ) @@ -645,7 +645,7 @@ func updateTunIpv4(out *json.Encoder, ip string, ipMask int, addDns string) { respondWithError(out, "Could not set Tun ip and mask", UNKNOWN_ERROR, err) return } - + respond(out, dto.Response{Message: "TunIPv4 and mask is set, Manual Restart is required", Code: SUCCESS, Error: "", Payload: ""}) } From 792a934de70d26cbf506aebdd9c61f50814e7408 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 19 Apr 2021 17:29:18 +0530 Subject: [PATCH 22/36] update release notes --- release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/release-notes.md b/release-notes.md index 821b8fc0..6394b297 100644 --- a/release-notes.md +++ b/release-notes.md @@ -8,6 +8,7 @@ ## Bugs fixed: * [#362](https://github.com/openziti/desktop-edge-win/issues/362) Update tun ip, mask and addDns flag +* [#364](https://github.com/openziti/desktop-edge-win/issues/364) Add the test nrpt policy function in the startup method ## Dependency Updates * none From 5d54e7edf1b8a54cde34018030814faee4c89816 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 19 Apr 2021 17:40:43 +0530 Subject: [PATCH 23/36] removing the test nrpt policy --- service/windns/windns.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/service/windns/windns.go b/service/windns/windns.go index f31c03f4..44ec0cc5 100644 --- a/service/windns/windns.go +++ b/service/windns/windns.go @@ -251,7 +251,7 @@ func IsNrptPoliciesEffective() bool { err := cmd.Run() if err != nil { - log.Errorf("ERROR removing all nrpt rules: %v", err) + log.Errorf("ERROR adding the test nrpt rules: %v", err) } policyFound := false @@ -265,10 +265,11 @@ func IsNrptPoliciesEffective() bool { if strings.Compare(policyOut, ".ziti.test") == 0 { policyFound = true log.Debug("The nrpt policies are effective in this client") - removeSingleNrtpRule(".ziti.test") break } } + removeSingleNrtpRule(".ziti.test") + return policyFound } From 72e46d893c4fb4f423d11f824009323664e89d67 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 19 Apr 2021 17:55:26 +0530 Subject: [PATCH 24/36] adding log --- service/ziti-tunnel/service/state.go | 1 + 1 file changed, 1 insertion(+) diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index ce0cf91c..e81a5549 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -225,6 +225,7 @@ func (t *RuntimeState) CreateTun(ipv4 string, ipv4mask int, applyDns bool) (net. zitiPoliciesEffective := windns.IsNrptPoliciesEffective() if applyDns || !zitiPoliciesEffective { + log.Info("DNS is applied to the TUN interface, because apply Dns flag in the config file : %t and ziti policies test result in this client: %t ", applyDns, zitiPoliciesEffective) //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 17dd0ef902d43b4aac90f1a5b9fafa91ccd4dda5 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 19 Apr 2021 17:59:25 +0530 Subject: [PATCH 25/36] returning if add nrpt rules fails --- service/windns/windns.go | 1 + service/ziti-tunnel/service/state.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/service/windns/windns.go b/service/windns/windns.go index 44ec0cc5..5f6124a5 100644 --- a/service/windns/windns.go +++ b/service/windns/windns.go @@ -252,6 +252,7 @@ func IsNrptPoliciesEffective() bool { err := cmd.Run() if err != nil { log.Errorf("ERROR adding the test nrpt rules: %v", err) + return false } policyFound := false diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index e81a5549..408e5416 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -225,7 +225,7 @@ func (t *RuntimeState) CreateTun(ipv4 string, ipv4mask int, applyDns bool) (net. zitiPoliciesEffective := windns.IsNrptPoliciesEffective() if applyDns || !zitiPoliciesEffective { - log.Info("DNS is applied to the TUN interface, because apply Dns flag in the config file : %t and ziti policies test result in this client: %t ", applyDns, zitiPoliciesEffective) + log.Info("DNS is applied to the TUN interface, because apply Dns flag in the config file: %t and ziti policies test result in this client: %t ", applyDns, zitiPoliciesEffective) //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 dfdad6917b71ebf4e843aabb48eb0c3afb0c7927 Mon Sep 17 00:00:00 2001 From: Mary Lincy Dcouto Date: Mon, 19 Apr 2021 21:12:29 +0530 Subject: [PATCH 26/36] fix as per the code review comments --- service/windns/windns.go | 6 +++--- service/ziti-tunnel/service/state.go | 9 +++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/service/windns/windns.go b/service/windns/windns.go index 5f6124a5..23e63f74 100644 --- a/service/windns/windns.go +++ b/service/windns/windns.go @@ -239,9 +239,9 @@ ForEach ($ns in $toRemove){ } } -func IsNrptPoliciesEffective() bool { - script := fmt.Sprintf(`Add-DnsClientNrptRule -Namespace ".ziti.test" -NameServers "100.64.0.1" -Comment "Added by ziti-tunnel" -DisplayName "ziti-tunnel:.ziti.test" - Get-DnsClientNrptPolicy -Effective | Select-Object Namespace -Unique | Where-Object Namespace -Eq ".ziti.test"`) +func IsNrptPoliciesEffective(dnsserver string) bool { + script := fmt.Sprintf(`Add-DnsClientNrptRule -Namespace ".ziti.test" -NameServers "%s" -Comment "Added by ziti-tunnel" -DisplayName "ziti-tunnel:.ziti.test" + Get-DnsClientNrptPolicy -Effective | Select-Object Namespace -Unique | Where-Object Namespace -Eq ".ziti.test"`, dnsserver) log.Debugf("checking the nrpt policies with: %s", script) cmd := exec.Command("powershell", "-Command", script) diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index 408e5416..7d667cfd 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -223,9 +223,14 @@ func (t *RuntimeState) CreateTun(ipv4 string, ipv4mask int, applyDns bool) (net. } log.Info("routing applied") - zitiPoliciesEffective := windns.IsNrptPoliciesEffective() + zitiPoliciesEffective := windns.IsNrptPoliciesEffective(ipv4) if applyDns || !zitiPoliciesEffective { - log.Info("DNS is applied to the TUN interface, because apply Dns flag in the config file: %t and ziti policies test result in this client: %t ", applyDns, zitiPoliciesEffective) + if applyDns { + log.Infof("DNS is applied to the TUN interface, because apply Dns flag in the config file is %t ", applyDns) + } + if !applyDns && !zitiPoliciesEffective { + log.Infof("DNS is applied to the TUN interface, because Ziti policies test result in this client is %t", zitiPoliciesEffective) + } //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 a61b3772109411341c6e3f5039448312d80d1753 Mon Sep 17 00:00:00 2001 From: ziti-ci Date: Mon, 19 Apr 2021 15:56:27 +0000 Subject: [PATCH 27/36] [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 ad8e8496..cb777bfe 100644 --- a/service/ziti-tunnel/version.go +++ b/service/ziti-tunnel/version.go @@ -21,8 +21,8 @@ package main const ( Version = "1.9.4" - Revision = "bf21f40f8dbc" + Revision = "24a59ec169b9" Branch = "release-next" BuildUser = "" - BuildDate = "2021-04-17 14:10:53" + BuildDate = "2021-04-19 15:51:04" ) From 4ee1864e8924ed9bfa821b177f69593fb7b656db Mon Sep 17 00:00:00 2001 From: Jeremy Tellier - ROG Date: Tue, 20 Apr 2021 12:00:57 +0100 Subject: [PATCH 28/36] Esc Close Menus, Use Observable Collection for ListView, Move ServiceInfo into Binding objects of ZitiService model --- DesktopEdge/MainWindow.xaml.cs | 8 + DesktopEdge/Models/ZitiService.cs | 362 ++++++++++++------ .../Views/ItemRenderers/ServiceInfo.xaml | 2 +- .../Views/Screens/IdentityDetails.xaml | 49 ++- .../Views/Screens/IdentityDetails.xaml.cs | 103 ++--- 5 files changed, 343 insertions(+), 181 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index 727a29e2..14620335 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -347,10 +347,18 @@ namespace ZitiDesktopEdge { this.IdentityMenu.MainWindow = this; SetNotifyIcon("white"); + this.PreviewKeyDown += KeyPressed; MFASetup.OnLoad += MFASetup_OnLoad; IdentityMenu.OnMessage += IdentityMenu_OnMessage; } + private void KeyPressed(object sender, KeyEventArgs e) { + if (e.Key == Key.Escape) { + if (IdentityMenu.Visibility == Visibility.Visible) IdentityMenu.Visibility = Visibility.Collapsed; + else if (MainMenu.Visibility == Visibility.Visible) MainMenu.Visibility = Visibility.Collapsed; + } + } + private void MFASetup_OnLoad(bool isComplete, string title, string message) { if (isComplete) HideLoad(); else ShowLoad(title, message); diff --git a/DesktopEdge/Models/ZitiService.cs b/DesktopEdge/Models/ZitiService.cs index c585b7b5..5a2b57e1 100644 --- a/DesktopEdge/Models/ZitiService.cs +++ b/DesktopEdge/Models/ZitiService.cs @@ -1,133 +1,241 @@ using NLog; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using ZitiDesktopEdge.DataStructures; - -namespace ZitiDesktopEdge.Models { +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; + +using ZitiDesktopEdge.DataStructures; + +namespace ZitiDesktopEdge.Models { public class ZitiService { - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - - public string Name { get; set; } - public string[] Protocols { get; set; } - public Address[] Addresses { get; set; } - public PortRange[] Ports { get; set; } - public PostureCheck[] PostureChecks { get; set; } - public bool OwnsIntercept { get; set; } - public string AssignedIP { get; set; } - - private bool failingPostureCheck; - public bool HasFailingPostureCheck() { + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + public string Name { get; set; } + public string[] Protocols { get; set; } + public Address[] Addresses { get; set; } + public PortRange[] Ports { get; set; } + public PostureCheck[] PostureChecks { get; set; } + public bool OwnsIntercept { get; set; } + public string AssignedIP { get; set; } + + private bool failingPostureCheck; + public bool HasFailingPostureCheck() { return failingPostureCheck; - } - public bool IsAccessable { get; set; } - - public string Warning { - get { - if (this.OwnsIntercept) { - return ""; - } else { - return "this won't trigger right now"; //$"Another identity already mapped the specified hostname: {Host}.\nThis service is only available via IP"; - } - } - } - - public ZitiService() { - } - - public ZitiService(Service svc) { - this.Name = svc.Name; - this.AssignedIP = svc.AssignedIP; - this.Addresses = svc.Addresses; - this.Protocols = svc.Protocols == null ? null : svc.Protocols.Select(p => p.ToUpper()).ToArray(); - this.Ports = svc.Ports; - this.PostureChecks = svc.PostureChecks; + } + public bool IsAccessable { get; set; } + + public string Warning { + get { + if (this.OwnsIntercept) { + return ""; + } else { + return "this won't trigger right now"; //$"Another identity already mapped the specified hostname: {Host}.\nThis service is only available via IP"; + } + } + } + + public ZitiService() { + } + + public ZitiService(Service svc) { + this.Name = svc.Name; + this.AssignedIP = svc.AssignedIP; + this.Addresses = svc.Addresses; + this.Protocols = svc.Protocols == null ? null : svc.Protocols.Select(p => p.ToUpper()).ToArray(); + this.Ports = svc.Ports; + this.PostureChecks = svc.PostureChecks; this.OwnsIntercept = svc.OwnsIntercept; if (this.PostureChecks != null) { this.failingPostureCheck = this.PostureChecks.Any(p => !p.IsPassing); - } - this.IsAccessable = svc.IsAccessable; - //commented out for now logger.Warn("SERVICE: " + this.Name + " HAS FAILING POSTURE CHECK: " + failingPostureCheck); - } - - - - private ServiceMatrix builtMatrix = null; - public ServiceMatrix Matrix { - get { - if (builtMatrix == null) { - builtMatrix = new ServiceMatrix(); - List matrix = new List(this.Protocols.Length * this.Addresses.Length * this.Ports.Length); - - foreach (var proto in this.Protocols) { - foreach (var addy in this.Addresses) { - foreach (var port in this.Ports) { - ServiceMatrixElement m = new ServiceMatrixElement(); - m.Ports = port.ToString(); - m.Proto = proto.ToUpper(); - m.Address = addy.Hostname; - - matrix.Add(m); - } - } - } - builtMatrix.Elements = matrix; - } - - return builtMatrix; - } - } - - public override string ToString() { - string protos = ""; - if (Protocols?.Length > 0) { - if (Protocols.Length > 1) { - protos = "[" + string.Join(",", Protocols.Select(p => p.ToString())) + "]"; - } else { - protos = Protocols[0]; - } - } - string addys = ""; - if (Addresses?.Length > 0) { - if (Addresses.Length > 1) { - addys = "[" + string.Join(",", Addresses.Select(a => a.ToString()).OrderBy(o => o)) + "]"; - } else { - addys = Addresses[0].ToString(); - } - } - string ranges = ""; - if (Ports?.Length > 0) { - if (Ports.Length > 1) { - ranges = "[" + string.Join(",", Ports.Select(a => a.ToString()).OrderBy(o => o)) + "]"; - } else { - ranges = Ports[0].ToString(); - } - } - - return protos + ":" + addys + ":" + ranges; - } - } - - public class ServiceMatrix { - public List Elements { get; internal set; } - } - - public class ServiceMatrixElement { - public ServiceMatrixElement() { - Proto = ""; - Address = ""; - Ports = ""; - } - - public string Proto { get; set; } - public string Address { get; set; } - public string Ports { get; set; } - - public override string ToString() { - return Proto + " " + Address + " " + Ports; - } - } -} + } + this.IsAccessable = svc.IsAccessable; + //commented out for now logger.Warn("SERVICE: " + this.Name + " HAS FAILING POSTURE CHECK: " + failingPostureCheck); + } + + public string WarningMessage { + get { + string message = Warning; + if (this.PostureChecks != null && this.PostureChecks.Length > 0) { + List messages = new List(); + for (int i = 0; i < this.PostureChecks.Length; i++) { + if (!this.PostureChecks[i].IsPassing) { + messages = AppendMessage(messages, this.PostureChecks[i].QueryType); + } + } + if (messages.Count > 0) { + string checks = ""; + for (int i = 0; i < messages.Count; i++) { + checks += ((i > 0) ? ", " : "") + messages[i].Total + " " + messages[i].Message; + } + message = message + " Posture Check Failing: " + checks; + return message.Trim(); + } else return message; + } else return message; + } + } + private List AppendMessage(List items, string message) { + bool found = false; + for (int i = 0; i < items.Count; i++) { + if (items[i].Message == message) { + items[i].Total++; + found = true; + } + } + if (!found) { + MessageCount count = new MessageCount(); + count.Total = 1; + count.Message = message; + items.Add(count); + } + return items; + } + + public int WarnWidth { + get { + return (HasWarning) ? 30 : 0; + } + set { } + } + + public Visibility WarningVisibility { + get { + return (HasWarning) ? Visibility.Visible : Visibility.Collapsed; + } + set { } + } + + public bool HasWarning { + get { + if (!this.OwnsIntercept) return true; + else { + if (this.IsAccessable) { + return false; + } else { + if (this.PostureChecks==null) { + return false; + } else { + for (int i = 0; i < this.PostureChecks.Length; i++) { + if (!this.PostureChecks[i].IsPassing) { + return true; + } + } + return false; + } + } + } + } + set { } + } + + public string ProtocolString { + get { + string toReturn = ""; + for (int i = 0; i < this.Protocols.Length; i++) { + toReturn += ((i > 0) ? "," : "") + this.Protocols[i]; + } + return toReturn; + } + set { } + } + + public string PortString { + get { + string toReturn = ""; + for (int i = 0; i < this.Ports.Length; i++) { + toReturn += ((i > 0) ? "," : "") + this.Ports[i].ToString(); + } + return toReturn; + } + set { } + } + + public string AddressString { + get { + string toReturn = ""; + for (int i = 0; i < this.Addresses.Length; i++) { + toReturn += ((i > 0) ? "," : "") + this.Addresses[i].Hostname; + } + return toReturn; + } + set { } + } + + private ServiceMatrix builtMatrix = null; + public ServiceMatrix Matrix { + get { + if (builtMatrix == null) { + builtMatrix = new ServiceMatrix(); + List matrix = new List(this.Protocols.Length * this.Addresses.Length * this.Ports.Length); + + foreach (var proto in this.Protocols) { + foreach (var addy in this.Addresses) { + foreach (var port in this.Ports) { + ServiceMatrixElement m = new ServiceMatrixElement(); + m.Ports = port.ToString(); + m.Proto = proto.ToUpper(); + m.Address = addy.Hostname; + + matrix.Add(m); + } + } + } + builtMatrix.Elements = matrix; + } + + return builtMatrix; + } + } + + public override string ToString() { + string protos = ""; + if (Protocols?.Length > 0) { + if (Protocols.Length > 1) { + protos = "[" + string.Join(",", Protocols.Select(p => p.ToString())) + "]"; + } else { + protos = Protocols[0]; + } + } + string addys = ""; + if (Addresses?.Length > 0) { + if (Addresses.Length > 1) { + addys = "[" + string.Join(",", Addresses.Select(a => a.ToString()).OrderBy(o => o)) + "]"; + } else { + addys = Addresses[0].ToString(); + } + } + string ranges = ""; + if (Ports?.Length > 0) { + if (Ports.Length > 1) { + ranges = "[" + string.Join(",", Ports.Select(a => a.ToString()).OrderBy(o => o)) + "]"; + } else { + ranges = Ports[0].ToString(); + } + } + + return protos + ":" + addys + ":" + ranges; + } + } + + public class ServiceMatrix { + public List Elements { get; internal set; } + } + + public class ServiceMatrixElement { + public ServiceMatrixElement() { + Proto = ""; + Address = ""; + Ports = ""; + } + + public string Proto { get; set; } + public string Address { get; set; } + public string Ports { get; set; } + + public override string ToString() { + return Proto + " " + Address + " " + Ports; + } + } +} diff --git a/DesktopEdge/Views/ItemRenderers/ServiceInfo.xaml b/DesktopEdge/Views/ItemRenderers/ServiceInfo.xaml index 1bf48ee7..d88c7b68 100644 --- a/DesktopEdge/Views/ItemRenderers/ServiceInfo.xaml +++ b/DesktopEdge/Views/ItemRenderers/ServiceInfo.xaml @@ -9,7 +9,7 @@ - + diff --git a/DesktopEdge/Views/Screens/IdentityDetails.xaml b/DesktopEdge/Views/Screens/IdentityDetails.xaml index becc065e..fb7ca458 100644 --- a/DesktopEdge/Views/Screens/IdentityDetails.xaml +++ b/DesktopEdge/Views/Screens/IdentityDetails.xaml @@ -6,7 +6,7 @@ xmlns:local="clr-namespace:ZitiDesktopEdge" mc:Ignorable="d" x:Name="IdentityArea" - d:DesignHeight="500" d:DesignWidth="350"> + d:DesignHeight="500" d:DesignWidth="350" IsVisibleChanged="VisibilityChanged"> @@ -16,7 +16,7 @@ - + @@ -46,13 +46,46 @@ - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -67,7 +100,7 @@ - + @@ -98,7 +131,7 @@ - + diff --git a/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs b/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs index 227bff66..37ff03d9 100644 --- a/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs +++ b/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using System.Windows; using System.Windows.Controls; @@ -10,6 +11,7 @@ using System.Windows.Media.Animation; using NLog; using System.Web; +using System.Windows.Media; namespace ZitiDesktopEdge { /// @@ -47,6 +49,9 @@ namespace ZitiDesktopEdge { private double scrolledTo = 0; public int totalServices = 0; + public ObservableCollection _services = new ObservableCollection(); + public ObservableCollection ZitiServices { get { return _services; } } + internal MainWindow MainWindow { get; set; } private List identities { @@ -66,7 +71,7 @@ namespace ZitiDesktopEdge { FilterServices.Clear(); scrolledTo = 0; _identity = value; - ServiceCount.Content = _identity.Services.Count + " services"; + ServiceCount.Content = _identity.Services.Count + " service"+((_identity.Services.Count>1)?"s":""); Page = 1; SortBy = "Name"; SortWay = "Asc"; @@ -106,9 +111,9 @@ namespace ZitiDesktopEdge { } public void UpdateView() { - ServiceScroller.InvalidateScrollInfo(); - ServiceScroller.ScrollToVerticalOffset(0); - ServiceScroller.InvalidateScrollInfo(); + //ServiceScroller.InvalidateScrollInfo(); + //ServiceScroller.ScrollToVerticalOffset(0); + //ServiceScroller.InvalidateScrollInfo(); scrolledTo = 0; IdDetailName.Text = _identity.Name; IdDetailName.ToolTip = _identity.Name; @@ -144,7 +149,7 @@ namespace ZitiDesktopEdge { IdentityMFA.AuthOff.Visibility = Visibility.Collapsed; IdentityMFA.RecoveryButton.Visibility = Visibility.Collapsed; } - ServiceList.Children.Clear(); + //ServiceList.Children.Clear(); totalServices = _identity.Services.Count; @@ -152,6 +157,8 @@ namespace ZitiDesktopEdge { int index = 0; int total = 0; ZitiService[] services = new ZitiService[0]; + _services = null; + _services = new ObservableCollection(); 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(); @@ -160,19 +167,15 @@ namespace ZitiDesktopEdge { 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); + _services.Add(zitiSvc); index++; } } } + ServiceList.ItemsSource = ZitiServices; TotalPages = (total / PerPage) + 1; @@ -202,26 +205,11 @@ namespace ZitiDesktopEdge { private void ShowDetails(ZitiService info) { DetailName.Text = info.Name; + DetailProtocols.Text = info.ProtocolString; + DetailAddress.Text = info.AddressString; + DetailPorts.Text = info.PortString; DetailUrl.Text = info.ToString(); - string protocols = ""; - string addresses = ""; - string ports = ""; - - for (int i = 0; i < info.Protocols.Length; i++) { - protocols += ((i > 0) ? "," : "") + info.Protocols[i]; - } - for (int i = 0; i < info.Addresses.Length; i++) { - addresses += ((i>0)?",":"")+info.Addresses[i]; - } - for (int i = 0; i < info.Ports.Length; i++) { - ports += ((i > 0) ? "," : "") + info.Ports[i]; - } - - DetailProtocols.Text = protocols; - DetailAddress.Text = addresses; - DetailPorts.Text = ports; - DetailsArea.Visibility = Visibility.Visible; DetailsArea.Opacity = 0; DetailsArea.Margin = new Thickness(0, 0, 0, 0); @@ -351,15 +339,30 @@ namespace ZitiDesktopEdge { this.Authenticate.Invoke(this.Identity); } + public static DependencyObject GetScrollViewer(DependencyObject o) { + if (o is ScrollViewer) { return o; } + for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++) { + var child = VisualTreeHelper.GetChild(o, i); + var result = GetScrollViewer(child); + if (result == null) { + continue; + } else { + return result; + } + } + return null; + } + private void Scrolled(object sender, ScrollChangedEventArgs e) { if (_loaded) { - var verticalOffset = ServiceScroller.VerticalOffset; - var maxVerticalOffset = ServiceScroller.ScrollableHeight; - + var scrollViewer = GetScrollViewer(ServiceList) as ScrollViewer; + var verticalOffset = scrollViewer.VerticalOffset; + var maxVerticalOffset = scrollViewer.ScrollableHeight; + if ((maxVerticalOffset < 0 || verticalOffset == maxVerticalOffset) && verticalOffset>0 && scrolledTo= 0 || zitiSvc.ToString().ToLower().IndexOf(filter.ToLower()) >= 0) { - ServiceInfo info = new ServiceInfo(); - info.Info = zitiSvc; - info.OnMessage += Info_OnMessage; - info.OnDetails += ShowDetails; - ServiceList.Children.Add(info); + ZitiServices.Add(zitiSvc); index++; } } } - double totalOffset = ServiceScroller.VerticalOffset; + double totalOffset = scrollViewer.VerticalOffset; double toNegate = index * 33; double scrollTo = (totalOffset - toNegate); - ServiceScroller.InvalidateScrollInfo(); - ServiceScroller.ScrollToVerticalOffset(verticalOffset); - ServiceScroller.InvalidateScrollInfo(); + scrollViewer.InvalidateScrollInfo(); + scrollViewer.ScrollToVerticalOffset(verticalOffset); + scrollViewer.InvalidateScrollInfo(); _loaded = true; - ServiceScroller.ScrollChanged += Scrolled; + // scrollViewer.ScrollChanged += Scrolled; } } } @@ -428,8 +427,22 @@ namespace ZitiDesktopEdge { this.OnLoading?.Invoke(true); } - private void ForgetIdentityButton_OnClick() { + private void WarnClicked(object sender, MouseButtonEventArgs e) { + ZitiService item = (ZitiService)(sender as FrameworkElement).DataContext; + OnMessage?.Invoke(item.Warning); + } + private void DetailsClicked(object sender, MouseButtonEventArgs e) { + ZitiService item = (ZitiService)(sender as FrameworkElement).DataContext; + ShowDetails(item); + } + + private void VisibilityChanged(object sender, DependencyPropertyChangedEventArgs e) { + if (this.Visibility==Visibility.Collapsed) { + ServiceList.DataContext = null; + _services.Clear(); + _services = null; + } } } } From be5ce22144318de97ca2430efa4d97a0a2a95796 Mon Sep 17 00:00:00 2001 From: ziti-ci Date: Tue, 20 Apr 2021 11:10:11 +0000 Subject: [PATCH 29/36] [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 cb777bfe..81c80915 100644 --- a/service/ziti-tunnel/version.go +++ b/service/ziti-tunnel/version.go @@ -21,8 +21,8 @@ package main const ( Version = "1.9.4" - Revision = "24a59ec169b9" + Revision = "1b4ca87a6bb0" Branch = "release-next" BuildUser = "" - BuildDate = "2021-04-19 15:51:04" + BuildDate = "2021-04-20 11:05:03" ) From 1fb3c7e04e25c369958b42d75caba1865b05bd8a Mon Sep 17 00:00:00 2001 From: Jeremy Tellier - ROG Date: Tue, 20 Apr 2021 12:41:15 +0100 Subject: [PATCH 30/36] Reset and Defer Scroll --- DesktopEdge/Views/Screens/IdentityDetails.xaml | 2 +- .../Views/Screens/IdentityDetails.xaml.cs | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/DesktopEdge/Views/Screens/IdentityDetails.xaml b/DesktopEdge/Views/Screens/IdentityDetails.xaml index fb7ca458..ad507f6c 100644 --- a/DesktopEdge/Views/Screens/IdentityDetails.xaml +++ b/DesktopEdge/Views/Screens/IdentityDetails.xaml @@ -50,7 +50,7 @@ - +