Merge pull request #323 from openziti/identity-onOff-cmdline

Identity on off cmdline
This commit is contained in:
dovholuknf
2021-04-08 06:56:36 -04:00
committed by GitHub
41 changed files with 979 additions and 391 deletions
+16
View File
@@ -487,6 +487,7 @@ namespace ZitiDesktopEdge {
serviceClient.OnServiceEvent += ServiceClient_OnServiceEvent;
serviceClient.OnTunnelStatusEvent += ServiceClient_OnTunnelStatusEvent;
serviceClient.OnMfaEvent += ServiceClient_OnMfaEvent;
serviceClient.OnLogLevelEvent += ServiceClient_OnLogLevelEvent;
Application.Current.Properties.Add("ServiceClient", serviceClient);
monitorClient = new MonitorClient();
@@ -724,6 +725,7 @@ namespace ZitiDesktopEdge {
found.Name = zid.Name;
found.ControllerUrl = zid.ControllerUrl;
found.IsEnabled = zid.IsEnabled;
LoadIdentities(true);
return;
}
} else if (e.Action == "updated") {
@@ -826,6 +828,20 @@ namespace ZitiDesktopEdge {
}
});
}
private void ServiceClient_OnLogLevelEvent(object sender, LogLevelEvent e) {
            if (e.LogLevel != null) {
                SetLogLevel_monitor(e.LogLevel);
                this.Dispatcher.Invoke(() =>  {
                    this.MainMenu.LogLevel = e.LogLevel;
                    Ziti.Desktop.Edge.Utils.UIUtils.SetLogLevel(e.LogLevel);
                });
            }
        }
        async private void SetLogLevel_monitor(string loglevel)  {
            await monitorClient.SetLogLevelAsync(loglevel);
        }
private void IdentityForgotten(ZitiIdentity forgotten) {
ZitiIdentity idToRemove = null;
@@ -119,7 +119,7 @@ namespace ZitiDesktopEdge {
ServiceList.Children.Clear();
if (_identity.Services.Count>0) {
foreach(var zitiSvc in _identity.Services.OrderBy(s => s.Name.ToLower())) {
if (zitiSvc.Name.ToLower().IndexOf(filter)>=0||zitiSvc.ToString().ToLower().IndexOf(filter)>=0) {
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;
@@ -418,6 +418,12 @@ namespace ZitiDesktopEdge.DataStructures {
{
public Identity Id { get; set; }
}
public class LogLevelEvent : ActionEvent
{
public string LogLevel { get; set; }
}
public class MonitorServiceStatusEvent : SvcResponse {
public string Status { get; set; }
@@ -33,6 +33,7 @@ namespace ZitiDesktopEdge.ServiceClient {
public event EventHandler<List<Identity>> OnMetricsEvent;
public event EventHandler<IdentityEvent> OnIdentityEvent;
public event EventHandler<ServiceEvent> OnServiceEvent;
public event EventHandler<LogLevelEvent> OnLogLevelEvent;
public event EventHandler<MfaEvent> OnMfaEvent;
protected override void ShutdownEvent(StatusEvent e) {
@@ -56,6 +57,11 @@ namespace ZitiDesktopEdge.ServiceClient {
protected virtual void ServiceEvent(ServiceEvent e) {
OnServiceEvent?.Invoke(this, e);
}
protected virtual void LogLevelEvent(LogLevelEvent e) {
OnLogLevelEvent?.Invoke(this, e);
}
protected virtual void MfaEvent(MfaEvent e) {
OnMfaEvent?.Invoke(this, e);
@@ -345,6 +351,13 @@ namespace ZitiDesktopEdge.ServiceClient {
ServiceEvent(svc);
}
break;
case "logLevel":
LogLevelEvent ll = serializer.Deserialize<LogLevelEvent>(jsonReader);
if (ll != null) {
LogLevelEvent(ll);
}
break;
case "shutdown":
Logger.Debug("shutdown message received");
var se = new StatusEvent();
+32
View File
@@ -199,6 +199,7 @@ namespace ZitiUpdateService {
outputTasklist(destinationLocation);
outputRouteInfo(destinationLocation);
outputNetstatInfo(destinationLocation);
outputNrpt(destinationLocation);
Task.Delay(500).Wait();
@@ -340,6 +341,37 @@ namespace ZitiUpdateService {
}
}
private void outputNrpt(string destinationFolder) {
Logger.Info("outputting NRPT rules");
try {
Logger.Info("outputting NRPT DnsClientNrptRule");
string nrptRuleOutput = Path.Combine(destinationFolder, "NrptRule.txt");
Process nrptRuleProcess = new Process();
ProcessStartInfo nrptRuleStartInfo = new ProcessStartInfo();
nrptRuleStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
nrptRuleStartInfo.FileName = "cmd.exe";
nrptRuleStartInfo.Arguments = $"/C powershell \"Get-DnsClientNrptRule | sort -Property Namespace\" > \"{nrptRuleOutput}\"";
Logger.Info("Running: {0}", nrptRuleStartInfo.Arguments);
nrptRuleProcess.StartInfo = nrptRuleStartInfo;
nrptRuleProcess.Start();
nrptRuleProcess.WaitForExit();
Logger.Info("outputting NRPT DnsClientNrptPolicy");
string nrptOutput = Path.Combine(destinationFolder, "NrptPolicy.txt");
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = $"/C powershell \"Get-DnsClientNrptPolicy | sort -Property Namespace\" > \"{nrptOutput}\"";
Logger.Info("Running: {0}", startInfo.Arguments);
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
} catch (Exception ex) {
Logger.Error(ex, "Unexpected error {0}", ex.Message);
}
}
public void Debug() {
OnStart(null);// new string[] { "FilesystemCheck" });
}
+16
View File
@@ -1,3 +1,19 @@
# Release 1.9.2
## What's New
* [#322](https://github.com/openziti/desktop-edge-win/issues/322) Ability to toggle identity, set loglevel and generate feedback zip file from cmd line
## Other changes:
* none
## Bugs fixed:
* [#346](https://github.com/openziti/desktop-edge-win/issues/346) Fixed the UI filtering of services on the Identity detail screen
* [#348](https://github.com/openziti/desktop-edge-win/issues/348) IP addresses do not need to be added to the NRPT
* [#349](https://github.com/openziti/desktop-edge-win/issues/349) Too many services can cause the NRPT update to fail
## Dependency Updates
* none
# Release 1.9.1
## What's New
+1
View File
@@ -7,3 +7,4 @@ NFWintunInstaller.msi
wintun.dll
gdb.txt
logs
+1 -1
View File
@@ -321,4 +321,4 @@ Set-NetIPInterface -InterfaceIndex $i.ifIndex -InterfaceMetric %d`, interfaceNam
if err != nil {
log.Errorf("ERROR setting interface metric: %v", err)
}
}
}
+9 -7
View File
@@ -113,9 +113,9 @@ func ziti_mfa_cb_verify_go(_ C.ziti_context, status C.int, cFingerprint *C.char)
fp := C.GoString(cFingerprint)
log.Debugf("ziti_mfa_cb_verify_go called for %s. status: %d for ", fp, int(status))
var m = dto.MfaEvent{
ActionEvent: dto.MFAEnrollmentVerificationEvent,
Fingerprint: fp,
Successful: false,
ActionEvent: dto.MFAEnrollmentVerificationEvent,
Fingerprint: fp,
Successful: false,
RecoveryCodes: nil,
}
@@ -135,6 +135,7 @@ func ziti_mfa_cb_verify_go(_ C.ziti_context, status C.int, cFingerprint *C.char)
}
var rtnCodes = make(chan mfaCodes)
func ReturnMfaCodes(id *ZIdentity, code string) ([]string, error) {
ccode := C.CString(code)
defer C.free(unsafe.Pointer(ccode))
@@ -179,6 +180,7 @@ func ziti_mfa_recovery_codes_cb_return(_ C.ziti_context, status C.int, recoveryC
}
var genCodes = make(chan mfaCodes)
func GenerateMfaCodes(id *ZIdentity, code string) ([]string, error) {
ccode := C.CString(code)
defer C.free(unsafe.Pointer(ccode))
@@ -292,9 +294,9 @@ func ziti_mfa_cb_remove_go(_ C.ziti_context, status C.int, cFingerprint *C.char)
log.Debugf("ziti_mfa_cb_remove_go called for %s. status: %d for ", fp, int(status))
var m = dto.MfaEvent{
ActionEvent: dto.MFAEnrollmentRemovedEvent,
Fingerprint: fp,
Successful: false,
ActionEvent: dto.MFAEnrollmentRemovedEvent,
Fingerprint: fp,
Successful: false,
RecoveryCodes: nil,
}
@@ -311,4 +313,4 @@ func ziti_mfa_cb_remove_go(_ C.ziti_context, status C.int, cFingerprint *C.char)
log.Debugf("sending ziti_mfa_verify response back to UI for %s. verified: %t. error: %s", fp, m.Successful, m.Error)
goapi.BroadcastEvent(m)
}
}
+14 -6
View File
@@ -340,7 +340,7 @@ func serviceCB(ziti_ctx C.ziti_context, service *C.ziti_service, status C.int, z
}
zid.Services.Store(svcId, &added)
ServiceChanges <- se
go func() {ServiceChanges <- se}() //do this in a go routine just in case it gets blocked so the uv loop doesn't block
}
return addresses
}
@@ -411,7 +411,9 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) {
}
addys := serviceCB(ztx, removed, C.ZITI_SERVICE_UNAVAILABLE, zid)
for _, toRemove := range addys {
hostnamesToRemove[toRemove.HostName] = true
if toRemove.IsHost {
hostnamesToRemove[toRemove.HostName] = true
}
}
}
for i := 0; true; i++ {
@@ -422,12 +424,16 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) {
log.Info("service changed remove the service then add it back immediately", C.GoString(changed.name))
addys := serviceCB(ztx, changed, C.ZITI_SERVICE_UNAVAILABLE, zid)
for _, toRemove := range addys {
hostnamesToRemove[toRemove.HostName] = true
if toRemove.IsHost {
hostnamesToRemove[toRemove.HostName] = true
}
}
addys = serviceCB(ztx, changed, C.ZITI_OK, zid)
for _, toAdd := range addys {
hostnamesToAdd[toAdd.HostName] = true
if toAdd.IsHost {
hostnamesToAdd[toAdd.HostName] = true
}
}
}
for i := 0; true; i++ {
@@ -437,7 +443,9 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) {
}
addys := serviceCB(ztx, added, C.ZITI_OK, zid)
for _, toAdd := range addys {
hostnamesToAdd[toAdd.HostName] = true
if toAdd.IsHost {
hostnamesToAdd[toAdd.HostName] = true
}
}
}
@@ -453,7 +461,7 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) {
var m = dto.IdentityEvent{
ActionEvent: dto.IdentityUpdateComplete,
Id: dto.Identity{
Id: dto.Identity{
FingerPrint: zid.Fingerprint,
},
}
+26 -2
View File
@@ -121,11 +121,35 @@ func AddNrptRules(domainsToMap map[string]bool, dnsServer string) {
log.Debug("no domains to map specified to AddNrptRules. exiting early")
return
}
blockSize := 50
if len(domainsToMap) > blockSize {
log.Debugf("domainsToMap is too long [%d] and may fail on some systems. splitting the requested entries into blocks of %d", len(domainsToMap), blockSize)
}
currentSize := 0
hostnames := make([]string, blockSize)
for hostname := range domainsToMap {
if currentSize >= blockSize {
log.Debugf("sending chunk of domains to be added to NRPT")
chunkedAddNrptRules(hostnames, dnsServer)
hostnames = make([]string, blockSize)
currentSize = 0
}
hostnames[currentSize] = hostname
currentSize++
}
if currentSize > 0 {
//means there's a chunk still to add....
chunkedAddNrptRules(hostnames[:currentSize], dnsServer)
}
}
func chunkedAddNrptRules(domainsToAdd []string, dnsServer string) {
sb := strings.Builder{}
sb.WriteString(`$Rules = @(
`)
for hostname := range domainsToMap {
for _, hostname := range domainsToAdd {
sb.WriteString(fmt.Sprintf(`@{ Namespace ="%s"; NameServers = @("%s"); Comment = "Added by ziti-tunnel"; DisplayName = "ziti-tunnel:%s"; }%s`, hostname, dnsServer, hostname, "\n"))
}
@@ -136,7 +160,7 @@ ForEach ($Rule in $Rules) {
}`))
script := sb.String()
log.Debugf("Executing NRPT script:\n%s", script)
log.Debugf("Executing NRPT script containing %d domains:\n%s", len(domainsToAdd), script)
cmd := exec.Command("powershell", "-Command", script)
cmd.Stderr = os.Stdout
@@ -1,133 +0,0 @@
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 (
"bufio"
"encoding/json"
"io"
"net"
"strings"
"time"
"github.com/Microsoft/go-winio"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/service"
)
type fetchFromRTS func([]string, *dto.TunnelStatus, map[string]bool) dto.Response
func sendMessagetoPipe(ipcPipeConn net.Conn, commandMsg *dto.CommandMsg, args []string) error {
writer := bufio.NewWriter(ipcPipeConn)
enc := json.NewEncoder(writer)
err := enc.Encode(commandMsg)
if err != nil {
log.Errorf("could not encode or writer list identities message, %v", err)
return err
}
log.Debug("Message sent to ipc pipe")
writer.Flush()
return nil
}
func readMessageFromPipe(ipcPipeConn net.Conn, readDone chan struct{}, fn fetchFromRTS, args []string, flags map[string]bool) {
reader := bufio.NewReader(ipcPipeConn)
msg, err := reader.ReadString('\n')
if err != nil {
log.Error(err)
return
}
if len(args) == 0 {
args = append(args, "all")
}
dec := json.NewDecoder(strings.NewReader(msg))
var tunnelStatus dto.ZitiTunnelStatus
if err := dec.Decode(&tunnelStatus); err == io.EOF {
return
} else if err != nil {
log.Fatal(err)
}
if tunnelStatus.Status != nil {
responseMsg := fn(args, tunnelStatus.Status, flags)
if responseMsg.Code == service.SUCCESS {
log.Info("\n" + responseMsg.Payload.(string) + "\n" + responseMsg.Message)
} else {
log.Info(responseMsg.Error)
}
} else {
log.Errorf("Ziti tunnel retuned nil status")
}
readDone <- struct{}{}
return
}
//GetIdentities is to fetch identities through cmdline
func GetIdentities(args []string, flags map[string]bool) {
getDataFromIpcPipe(&GET_STATUS, GetIdentitiesFromRTS, args, flags)
}
//GetServices is to fetch services through cmdline
func GetServices(args []string, flags map[string]bool) {
getDataFromIpcPipe(&GET_STATUS, GetServicesFromRTS, args, flags)
}
func getDataFromIpcPipe(commandMsg *dto.CommandMsg, fn fetchFromRTS, args []string, flags map[string]bool) {
log.Infof("fetching identities through cmdline...%s", args)
log.Debug("Connecting to pipe")
timeout := 2000 * time.Millisecond
ipcPipeConn, err := winio.DialPipe(service.IpcPipeName(), &timeout)
defer closeConn(ipcPipeConn)
if err != nil {
log.Errorf("Connection to ipc pipe is not established, %v", err)
return
}
readDone := make(chan struct{})
defer close(readDone) // ensure that goroutine exits
go readMessageFromPipe(ipcPipeConn, readDone, fn, args, flags)
err = sendMessagetoPipe(ipcPipeConn, commandMsg, args)
if err != nil {
log.Errorf("Message is not sent to ipc pipe, %v", err)
return
}
log.Debugf("Connection to ipc pipe is established - %s and remote address %s", ipcPipeConn.LocalAddr().String(), ipcPipeConn.RemoteAddr().String())
<-readDone
log.Debug("read finished normally")
}
func closeConn(conn net.Conn) {
err := conn.Close()
if err != nil {
log.Warnf("abnormal error while closing connection. %v", err)
}
}
@@ -1,37 +1,55 @@
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 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 "%40s" "InterceptHost"}} | {{printf "%14s" "InterceptPort"}} | {{printf "%15s" "AssignedIP"}} | {{printf "%15s" "AssignedHost"}} | {{"OwnsIntercept"}}
{{range .}}{{printf "%40s" .Name}} | {{printf "%15s" .Id}} | {{printf "%40s" .InterceptHost}} | {{printf "%14d" .InterceptPort}} | {{printf "%15s" .AssignedIP}} | {{printf "%15s" .AssignedHost}} | {{.OwnsIntercept}}
{{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 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()
+260
View File
@@ -0,0 +1,260 @@
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 (
"fmt"
"bufio"
"encoding/json"
"io"
"net"
"strings"
"time"
"github.com/Microsoft/go-winio"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/service"
)
type fetchStatusFromRTS func([]string, *dto.TunnelStatus, map[string]bool) dto.Response
type fetchResponseFromRTS func([]string, dto.Response, map[string]bool) dto.Response
func sendMessagetoPipe(ipcPipeConn net.Conn, commandMsg *dto.CommandMsg, args []string) error {
writer := bufio.NewWriter(ipcPipeConn)
enc := json.NewEncoder(writer)
err := enc.Encode(commandMsg)
if err != nil {
log.Error("could not encode or writer list identities message, %v", err)
return err
}
log.Debug("Message sent to ipc pipe")
writer.Flush()
return nil
}
func readMessageFromPipe(ipcPipeConn net.Conn, readDone chan bool, fn fetchStatusFromRTS, responseFn fetchResponseFromRTS, args []string, flags map[string]bool) {
reader := bufio.NewReader(ipcPipeConn)
msg, err := reader.ReadString('\n')
if err != nil {
log.Error(err)
readDone <- false
return
}
if len(args) == 0 {
args = append(args, "all")
}
dec := json.NewDecoder(strings.NewReader(msg))
if fn != nil {
var tunnelStatus dto.ZitiTunnelStatus
if err := dec.Decode(&tunnelStatus); err == io.EOF {
readDone <- false
return
} else if err != nil {
log.Fatal(err)
readDone <- false
return
}
if tunnelStatus.Status != nil {
responseMsg := fn(args, tunnelStatus.Status, flags)
if responseMsg.Code == service.SUCCESS {
fmt.Println(responseMsg.Payload.(string))
fmt.Println(responseMsg.Message)
readDone <- true
return
} else {
if responseMsg.Error != "" {
log.Error(responseMsg.Error)
} else {
log.Info(responseMsg.Message)
}
}
} else {
log.Errorf("Ziti tunnel retuned status, %v", tunnelStatus)
}
}
if responseFn != nil {
var response dto.Response
if err := dec.Decode(&response); err == io.EOF {
readDone <- false
return
} else if err != nil {
log.Fatal(err)
readDone <- false
return
}
if response.Message != "" {
responseMsg := responseFn(args, response, flags)
if responseMsg.Code == service.SUCCESS {
if responseMsg.Payload != nil {
log.Infof("Payload : %v", responseMsg.Payload)
}
log.Infof("Message : %s", responseMsg.Message)
readDone <- true
return
} else {
if responseMsg.Error != "" {
log.Error(responseMsg.Error)
} else {
log.Info(responseMsg.Message)
}
}
} else {
log.Errorf("Ziti tunnel retuned nil response message, %v", response)
}
}
readDone <- false
return
}
func GetDataFromIpcPipe(commandMsg *dto.CommandMsg, fn fetchStatusFromRTS, responseFn fetchResponseFromRTS, args []string, flags map[string]bool) bool {
log.Infof("Command %s with args %s", commandMsg.Function, args)
log.Debug("Connecting to pipe")
timeout := 2000 * time.Millisecond
ipcPipeConn, err := winio.DialPipe(service.IpcPipeName(), &timeout)
defer closeConn(ipcPipeConn)
if err != nil {
log.Errorf("Connection to ipc pipe is not established, %v", err)
log.Fatal("Ziti Desktop Edge app may not be running")
return false
}
readDone := make(chan bool)
defer close(readDone) // ensure that goroutine exits
go readMessageFromPipe(ipcPipeConn, readDone, fn, responseFn, args, flags)
err = sendMessagetoPipe(ipcPipeConn, commandMsg, args)
if err != nil {
log.Errorf("Message is not sent to ipc pipe, %v", err)
return false
}
log.Debugf("Connection to ipc pipe is established - %s and remote address %s", ipcPipeConn.LocalAddr().String(), ipcPipeConn.RemoteAddr().String())
status := <-readDone
log.Debug("read finished normally")
return status
}
// monitor ipc messages
func GetDataFromMonitorIpcPipe(actionMessage *dto.ActionEvent, args []string, flags map[string]bool) bool {
log.Infof("Command %s with args %s", actionMessage.StatusEvent.Op, args)
log.Debug("Connecting to pipe")
timeout := 2000 * time.Millisecond
ipcPipeConn, err := winio.DialPipe(monitorIpcPipe, &timeout)
defer closeConn(ipcPipeConn)
if err != nil {
log.Errorf("Connection to monitor ipc pipe is not established, %v", err)
log.Errorf("Ziti Update service may not be running")
return false
}
readDone := make(chan bool)
defer close(readDone) // ensure that goroutine exits
go readMessageFromMonitorPipe(ipcPipeConn, readDone, args, flags)
err = sendMessageToMonitorPipe(ipcPipeConn, actionMessage, args)
if err != nil {
log.Errorf("Message is not sent to monitor ipc pipe, %v", err)
return false
}
log.Debugf("Connection to monitor ipc pipe is established - %s and remote address %s", ipcPipeConn.LocalAddr().String(), ipcPipeConn.RemoteAddr().String())
status := <-readDone
log.Debug("read finished normally")
return status
}
func sendMessageToMonitorPipe(ipcPipeConn net.Conn, actionMessage *dto.ActionEvent, args []string) error {
writer := bufio.NewWriter(ipcPipeConn)
enc := json.NewEncoder(writer)
err := enc.Encode(actionMessage)
if err != nil {
log.Error("could not encode or write response message, %v", err)
return err
}
log.Debug("Message sent to monitor ipc pipe")
writer.Flush()
return nil
}
func readMessageFromMonitorPipe(ipcPipeConn net.Conn, readDone chan bool, args []string, flags map[string]bool) {
reader := bufio.NewReader(ipcPipeConn)
msg, err := reader.ReadString('\n')
if err != nil {
log.Error(err)
readDone <- false
return
}
dec := json.NewDecoder(strings.NewReader(msg))
var monitorServiceResponse dto.MonitorServiceResponse
if err := dec.Decode(&monitorServiceResponse); err == io.EOF {
readDone <- false
return
} else if err != nil {
log.Fatal(err)
readDone <- false
return
}
if monitorServiceResponse.Code == service.SUCCESS {
log.Infof("Feedback file %s is created", monitorServiceResponse.Message)
readDone <- true
return
} else {
log.Error(monitorServiceResponse.Error)
}
readDone <- false
return
}
func closeConn(conn net.Conn) {
if conn != nil {
err := conn.Close()
if err != nil {
log.Warnf("abnormal error while closing connection. %v", err)
}
}
}
@@ -39,15 +39,29 @@ func convertToIdentityCli(id *dto.Identity) dto.IdentityCli {
}
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,
/*InterceptHost: svc.InterceptHost,
InterceptPort: svc.InterceptPort,
AssignedIP: svc.AssignedIP,
AssignedHost: svc.AssignedHost,
*/
OwnsIntercept: svc.OwnsIntercept,
Name: svc.Name,
Id: svc.Id,
Protocols: strings.Join(svc.Protocols, ","),
Ports: cliPorts,
Addresses: cliAddresses,
}
}
@@ -180,3 +194,35 @@ func generateResponse(dataType string, message string, filteredData interface{},
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
}
+55
View File
@@ -0,0 +1,55 @@
package cli
import (
"strings"
"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)
}
+38
View File
@@ -0,0 +1,38 @@
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"
)
// feedbackCmd represents the feedback command
var feedbackCmd = &cobra.Command{
Use: "feedback",
Short: "fetch system information and logs from ziti-tunnel",
Long: `Fetch the system information and logs, zip it and attach it to the email.
User has to send the email to support@netfoundry.io`,
Run: func(cmd *cobra.Command, args []string) {
cli.GetFeedback(args, nil)
},
}
func init() {
rootCmd.AddCommand(feedbackCmd)
}
+1 -2
View File
@@ -26,7 +26,7 @@ var servicesOfID bool
// identitiesCmd represents the identities command
var identitiesCmd = &cobra.Command{
Use: "identities",
Use: "identities [all] [idname...] [-s]",
Short: "Lists identities from ziti-tunnel",
Long: `View the identities that this user has access to.
The records will be fetched from ziti-tunnel`,
@@ -45,7 +45,6 @@ func init() {
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
//identitiesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
identitiesCmd.Flags().BoolVarP(&servicesOfID, "services", "s", false, "Display all services that belonged to the identity")
}
+55
View File
@@ -0,0 +1,55 @@
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 (
"errors"
"strings"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/cli"
"github.com/spf13/cobra"
)
// identityCmd represents the identity command
var identityCmd = &cobra.Command{
Use: "identity [fingerprint] [on/off]",
Short: "enable or disable the identity",
Long: `Enable or disable identity based on the On Off values.
It accepts finger print of the identity followed by on/off value`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 2 {
return errors.New("requires 2 arguments, usage: identity [fingerprint] [on/off]")
}
if len(args[0]) == 40 && isValidArg(args[1]) {
return nil
}
return errors.New("incorrect arguments are passed, usage: identity [fingerprint] [on/off]")
},
Run: func(cmd *cobra.Command, args []string) {
cli.OnOffIdentity(args, nil)
},
}
func isValidArg(onOff string) bool {
return (strings.EqualFold(onOff, "on") || strings.EqualFold(onOff, "off"))
}
func init() {
rootCmd.AddCommand(identityCmd)
}
+57
View File
@@ -0,0 +1,57 @@
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 (
"errors"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/cli"
"github.com/spf13/cobra"
)
var currentLogLevel bool
// loglevelCmd represents the loglevel command
var loglevelCmd = &cobra.Command{
Use: "loglevel [loglevel]",
Short: "Set the loglevel of the ziti tunnel",
Long: `Allows you to set the log level of ziti tunnel.`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 && !currentLogLevel {
return errors.New("requires 1 argument or a flag, examples of the accepted loglevel arguments are trace, info, debug etc")
}
return nil
},
Run: func(cmd *cobra.Command, args []string) {
flags := map[string]bool{}
flags["query"] = currentLogLevel
cli.SetLogLevel(args, flags)
},
}
func init() {
rootCmd.AddCommand(loglevelCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
loglevelCmd.PersistentFlags().BoolVarP(&currentLogLevel, "query", "q", false, "Query current loglevel")
}
+2 -1
View File
@@ -19,6 +19,7 @@ package cmd
import (
"fmt"
"log"
"os"
"github.com/spf13/cobra"
@@ -75,5 +76,5 @@ func initConfig() {
}
func checkHelp() {
fmt.Println("Use -h or --help option to get the help message")
log.Println("Use -h or --help option to get the help message")
}
+1 -2
View File
@@ -24,7 +24,7 @@ import (
// servicesCmd represents the services command
var servicesCmd = &cobra.Command{
Use: "services",
Use: "services [all] [svc_name...]",
Short: "Lists services from ziti-tunnel",
Long: `View the services that this user has access to.
The records will be fetched from ziti-tunnel`,
@@ -37,5 +37,4 @@ var servicesCmd = &cobra.Command{
func init() {
listCmd.AddCommand(servicesCmd)
}
+4 -4
View File
@@ -17,9 +17,9 @@
package constants
const(
const (
Ipv4ip = "100.64.0.1"
Ipv4MaxMask = 8
Ipv4MinMask = 16
Ipv4MaxMask = 8
Ipv4MinMask = 16
Ipv4DefaultMask = 10
)
)
+46 -37
View File
@@ -1,37 +1,46 @@
package dto
/*
* 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.
*
*/
type IdentityCli struct {
Name string
FingerPrint string
Active bool
Config string
ControllerVersion string
Status string
}
type ServiceCli struct {
Name string
AssignedIP string
InterceptHost string
InterceptPort uint16
Id string
AssignedHost string
OwnsIntercept bool
}
package dto
/*
* 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.
*
*/
type IdentityCli struct {
Name string
FingerPrint string
Active bool
Config string
ControllerVersion string
Status string
}
type ServiceCli struct {
Name string
Id string
Protocols string
Ports string
Addresses string
}
type IdentityOnOffPayload struct {
OnOff string
Fingerprint string
}
type MonitorServiceResponse struct {
Code int
Message string
Error string
}
+7 -1
View File
@@ -18,10 +18,11 @@
package dto
import (
"log"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/config"
idcfg "github.com/openziti/sdk-golang/ziti/config"
"github.com/openziti/sdk-golang/ziti/enroll"
"log"
)
type AddIdentity struct {
@@ -162,6 +163,11 @@ type IdentityEvent struct {
Id Identity
}
type LogLevelEvent struct {
ActionEvent
LogLevel string
}
type MfaEvent struct {
ActionEvent
Fingerprint string
+18 -4
View File
@@ -21,16 +21,20 @@ const (
REMOVED = "removed"
ERROR = "error"
UPDATED = "updated"
CHANGED = "changed"
NORMAL = "Normal"
SERVICE_OP = "service"
IDENTITY_OP = "identity"
LOGLEVEL_OP = "logLevel"
FEEDBACK_OP = "CaptureLogs"
MFA_OP = "mfa"
MFAEnrollmentChallengAtion = "enrollment_challenge"
MFAEnrollmentVerificationAction = "enrollment_verification"
MFAEnrollmentRemovedAction = "enrollment_remove"
MFAEnrollmentChallengAtion = "enrollment_challenge"
MFAEnrollmentVerificationAction = "enrollment_verification"
MFAEnrollmentRemovedAction = "enrollment_remove"
MFA_AUTH_CHALLENGE_ACTION = "auth_challenge"
MFA_AUTH_CHALLENGE_ACTION = "auth_challenge"
)
var SERVICE_ADDED = ActionEvent{
@@ -50,6 +54,16 @@ var IDENTITY_REMOVED = ActionEvent{
StatusEvent: StatusEvent{Op: IDENTITY_OP},
Action: REMOVED,
}
var LOGLEVEL_CHANGED = ActionEvent{
StatusEvent: StatusEvent{Op: LOGLEVEL_OP},
Action: CHANGED,
}
var FEEDBACK_REQUEST = ActionEvent{
StatusEvent: StatusEvent{Op: FEEDBACK_OP},
Action: NORMAL,
}
var IdentityUpdateComplete = ActionEvent{
StatusEvent: StatusEvent{Op: IDENTITY_OP},
Action: UPDATED,
+7 -1
View File
@@ -105,6 +105,12 @@ func main() {
fmt.Println(version())
case "list":
commandline.Execute()
case "identity":
commandline.Execute()
case "loglevel":
commandline.Execute()
case "feedback":
commandline.Execute()
default:
usage(fmt.Sprintf("invalid command %s", cmd))
}
@@ -120,7 +126,7 @@ func usage(errmsg string) {
"%s\n\n"+
"usage: %s <command>\n"+
" where <command> is one of\n"+
" install, remove, debug, start, stop, pause, continue, list or version.\n",
" install, remove, debug, start, stop, pause, continue, list, identity, loglevel, feedback or version.\n",
errmsg, os.Args[0])
os.Exit(2)
}
+5 -5
View File
@@ -18,8 +18,8 @@
package service
import (
idcfg "github.com/openziti/sdk-golang/ziti/config"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto"
idcfg "github.com/openziti/sdk-golang/ziti/config"
)
func dbg() {
@@ -28,15 +28,15 @@ func dbg() {
events.broadcast <- dto.TunnelStatusEvent{
StatusEvent: dto.StatusEvent{Op: "status"},
Status: r,
ApiVersion: API_VERSION,
ApiVersion: API_VERSION,
}
svcs := make([]*dto.Service, 2)
svcs[0] = &dto.Service{
Name: "FakeService1",
Name: "FakeService1",
}
svcs[1] = &dto.Service{
Name: "Second Fake Service",
Name: "Second Fake Service",
}
events.broadcast <- dto.IdentityEvent{
@@ -57,7 +57,7 @@ func dbg() {
events.broadcast <- dto.ServiceEvent{
ActionEvent: dto.SERVICE_ADDED,
Service: &dto.Service{
Name: "New Service",
Name: "New Service",
},
Fingerprint: "new_id_fingerprint",
}
+4 -4
View File
@@ -52,9 +52,9 @@ func InstallService() error {
log.Infof("service installed using path: %s", fullPath)
s, err = m.CreateService(SvcStartName, fullPath, mgr.Config{
StartType: mgr.StartAutomatic,
DisplayName: SvcName,
Description: SvcNameLong,
StartType: mgr.StartAutomatic,
DisplayName: SvcName,
Description: SvcNameLong,
})
if err != nil {
return err
@@ -89,4 +89,4 @@ func RemoveService() error {
return fmt.Errorf("RemoveEventLogSource() failed: %s", err)
}
return nil
}
}
+47 -4
View File
@@ -500,6 +500,10 @@ func serveIpc(conn net.Conn) {
//save the state
rts.SaveState()
case "NotifyLogLevelUIAndUpdateService":
sendLogLevelAndNotify(enc, cmd.Payload["Level"].(string))
case "NotifyIdentityUI":
sendIdentityAndNotifyUI(enc, cmd.Payload["Fingerprint"].(string))
case "ZitiDump":
log.Debug("request to ZitiDump received")
for _, id := range rts.ids {
@@ -732,7 +736,7 @@ func toggleIdentity(out *json.Encoder, fingerprint string, onOff bool) {
msg := fmt.Sprintf("identity with fingerprint %s not found", fingerprint)
log.Warn(msg)
respond(out, dto.Response{
Code: SUCCESS,
Code: IDENTITY_NOT_FOUND,
Message: fmt.Sprintf("no update performed. %s", msg),
Error: "",
Payload: nil,
@@ -1033,7 +1037,15 @@ func handleEvents(isInitialized chan struct{}) {
//Removes the Config from the provided identity and returns a 'cleaned' id
func Clean(src *Id) dto.Identity {
log.Tracef("cleaning identity: %s %v %v", src.Name, src.CId.MfaNeeded, src.CId.MfaEnabled)
mfaNeeded := false
mfaEnabled := false
if src.CId != nil {
mfaNeeded = src.CId.MfaNeeded
mfaEnabled = src.CId.MfaEnabled
}
log.Tracef("cleaning identity: %s", src.Name, mfaNeeded, mfaEnabled)
AddMetrics(src)
nid := dto.Identity{
Name: src.Name,
@@ -1042,8 +1054,8 @@ func Clean(src *Id) dto.Identity {
Config: idcfg.Config{},
ControllerVersion: src.ControllerVersion,
Status: "",
MfaNeeded: src.CId.MfaNeeded,
MfaEnabled: src.CId.MfaEnabled,
MfaNeeded: mfaNeeded,
MfaEnabled: mfaEnabled,
Services: make([]*dto.Service, 0),
Metrics: src.Metrics,
Tags: nil,
@@ -1083,3 +1095,34 @@ func authMfa(out *json.Encoder, fingerprint string, code string) {
respondWithError(out, fmt.Sprintf("AuthMFA failed. the supplied code [%s] was not valid: %s", code, result), 1, result)
}
}
// when the log level is updated through command line, the message is broadcasted to UI and update service as well
func sendLogLevelAndNotify(enc *json.Encoder, loglevel string) {
events.broadcast <- dto.LogLevelEvent{
ActionEvent: dto.LOGLEVEL_CHANGED,
LogLevel: loglevel,
}
message := fmt.Sprintf("Loglevel %s is sent to the events channel", loglevel)
log.Info(message)
resp := dto.Response{Message: "success", Code: SUCCESS, Error: "", Payload: message}
respond(enc, resp)
}
// when the identity status is updated through command line, the message is sent to UI as well
func sendIdentityAndNotifyUI(enc *json.Encoder, fingerprint string) {
for _, id := range rts.ids {
if id.FingerPrint == fingerprint {
events.broadcast <- dto.IdentityEvent{
ActionEvent: dto.IDENTITY_ADDED,
Id: id.Identity,
}
message := fmt.Sprintf("Identity %s - %s updated message is sent to the events channel", id.Identity.Name, id.Identity.FingerPrint)
log.Info(message)
resp := dto.Response{Message: "success", Code: SUCCESS, Error: "", Payload: message}
respond(enc, resp)
return
}
}
resp := dto.Response{Message: "", Code: ERROR, Error: "Could not find id matching fingerprint " + fingerprint, Payload: ""}
respond(enc, resp)
}
+101 -101
View File
@@ -1,101 +1,101 @@
package service
import (
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/config"
)
// After System update, the identity files are not getting copied to the config path
// So we are adding a function to scan for identities in the backtup location
func scanForIdentitiesPostWindowsUpdate() error {
srcBackUpPaths := [2]string{"Windows.~BT\\Windows\\System32\\config\\systemprofile\\AppData\\Roaming\\NetFoundry",
"Windows.old\\Windows\\System32\\config\\systemprofile\\AppData\\Roaming\\NetFoundry"}
systemDrivePath := os.Getenv("SystemDrive")
if systemDrivePath == "" {
return nil
}
for _, srcPath := range srcBackUpPaths {
sourcePath := filepath.Join(systemDrivePath, string(os.PathSeparator), srcPath)
_, err := os.Stat(sourcePath)
if err != nil {
log.Debugf("Folder %s does not exist", sourcePath)
continue
}
err = searchAndCopyFilesFromBackup(sourcePath)
if err != nil {
log.Debugf("Copy files from %s failed, %v", sourcePath, err)
}
}
return nil
}
func searchAndCopyFilesFromBackup(srcPath string) error {
err := filepath.Walk(srcPath, copyFilesFromBackUp)
if err != nil {
return err
}
return nil
}
func copyFilesFromBackUp(path string, f os.FileInfo, err error) error {
if !f.IsDir() {
log.Infof("Found: %s", path)
destinationFile := filepath.Join(config.Path(), string(os.PathSeparator), f.Name())
//check if the file is present in the destination folder
_, err := os.Stat(destinationFile)
if err == nil && !strings.Contains(f.Name(), ConfigFileName) {
log.Debugf("File %s is already present in the config path and it is not %s, So not transfering", f.Name(), ConfigFileName)
deleteFile(path)
return nil
}
_, err = copy(path, destinationFile)
if err != nil {
log.Errorf("Error occurred while copying the Windows backup folder %s --> %s %v", f.Name(), destinationFile, err)
return nil
} else {
log.Infof("Found backup file at %s. Restored this file to %s", path, destinationFile)
deleteFile(path)
}
}
return nil
}
func deleteFile(path string) {
log.Infof("Removing file %s", path)
err := os.Remove(path)
if err != nil {
log.Errorf("Error occured while removing the file %s, %v", path, err)
} else {
log.Infof("Removed file %s", path)
}
}
func copy(src, dst string) (int64, error) {
sourceFileStat, err := os.Stat(src)
if err != nil {
return 0, err
}
if !sourceFileStat.Mode().IsRegular() {
return 0, errors.New(fmt.Sprintf("%s is not a regular file", src))
}
source, err := os.Open(src)
if err != nil {
return 0, err
}
defer source.Close()
destination, err := os.Create(dst)
if err != nil {
return 0, err
}
defer destination.Close()
nBytes, err := io.Copy(destination, source)
return nBytes, err
}
package service
import (
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/config"
)
// After System update, the identity files are not getting copied to the config path
// So we are adding a function to scan for identities in the backtup location
func scanForIdentitiesPostWindowsUpdate() error {
srcBackUpPaths := [2]string{"Windows.~BT\\Windows\\System32\\config\\systemprofile\\AppData\\Roaming\\NetFoundry",
"Windows.old\\Windows\\System32\\config\\systemprofile\\AppData\\Roaming\\NetFoundry"}
systemDrivePath := os.Getenv("SystemDrive")
if systemDrivePath == "" {
return nil
}
for _, srcPath := range srcBackUpPaths {
sourcePath := filepath.Join(systemDrivePath, string(os.PathSeparator), srcPath)
_, err := os.Stat(sourcePath)
if err != nil {
log.Debugf("Folder %s does not exist", sourcePath)
continue
}
err = searchAndCopyFilesFromBackup(sourcePath)
if err != nil {
log.Debugf("Copy files from %s failed, %v", sourcePath, err)
}
}
return nil
}
func searchAndCopyFilesFromBackup(srcPath string) error {
err := filepath.Walk(srcPath, copyFilesFromBackUp)
if err != nil {
return err
}
return nil
}
func copyFilesFromBackUp(path string, f os.FileInfo, err error) error {
if !f.IsDir() {
log.Infof("Found: %s", path)
destinationFile := filepath.Join(config.Path(), string(os.PathSeparator), f.Name())
//check if the file is present in the destination folder
_, err := os.Stat(destinationFile)
if err == nil && !strings.Contains(f.Name(), ConfigFileName) {
log.Debugf("File %s is already present in the config path and it is not %s, So not transfering", f.Name(), ConfigFileName)
deleteFile(path)
return nil
}
_, err = copy(path, destinationFile)
if err != nil {
log.Errorf("Error occurred while copying the Windows backup folder %s --> %s %v", f.Name(), destinationFile, err)
return nil
} else {
log.Infof("Found backup file at %s. Restored this file to %s", path, destinationFile)
deleteFile(path)
}
}
return nil
}
func deleteFile(path string) {
log.Infof("Removing file %s", path)
err := os.Remove(path)
if err != nil {
log.Errorf("Error occured while removing the file %s, %v", path, err)
} else {
log.Infof("Removed file %s", path)
}
}
func copy(src, dst string) (int64, error) {
sourceFileStat, err := os.Stat(src)
if err != nil {
return 0, err
}
if !sourceFileStat.Mode().IsRegular() {
return 0, errors.New(fmt.Sprintf("%s is not a regular file", src))
}
source, err := os.Open(src)
if err != nil {
return 0, err
}
defer source.Close()
destination, err := os.Create(dst)
if err != nil {
return 0, err
}
defer destination.Close()
nBytes, err := io.Copy(destination, source)
return nBytes, err
}
+1 -1
View File
@@ -53,4 +53,4 @@ func EnsurePermissions(group string) string {
}
return sid
}
}
+2 -2
View File
@@ -59,8 +59,8 @@ const (
IDENTITY_NOT_FOUND = 1000
MFA_FAILED_TO_GENERATE_CODES = 200
MFA_FAILED_TO_RETURN_CODES = 201
MFA_FINGERPRINT_NOT_FOUND = 202
MFA_FAILED_TO_RETURN_CODES = 201
MFA_FINGERPRINT_NOT_FOUND = 202
DEFAULT_REFRESH_INTERVAL = 10
+1 -1
View File
@@ -87,7 +87,7 @@ loop:
changes <- svc.Status{State: svc.StopPending}
log.Infof("waiting for shutdown to complete")
<- control
<-control
log.Infof("normal shutdown complete")
return
}
+3 -3
View File
@@ -152,9 +152,9 @@ func (t *RuntimeState) ToMetrics() dto.TunnelStatus {
Name: id.Name,
FingerPrint: id.FingerPrint,
Metrics: id.Metrics,
Active: id.Active,
MfaEnabled: id.MfaEnabled,
MfaNeeded: id.MfaNeeded,
Active: id.Active,
MfaEnabled: id.MfaEnabled,
MfaNeeded: id.MfaNeeded,
}
i++
}
+6 -6
View File
@@ -19,8 +19,8 @@ package service
type topic struct {
broadcast chan interface{}
channels map[int]chan interface{}
done chan bool
channels map[int]chan interface{}
done chan bool
}
func newTopic(cap int16) topic {
@@ -31,19 +31,19 @@ func newTopic(cap int16) topic {
}
}
func(t *topic) register(id int, c chan interface{}) {
func (t *topic) register(id int, c chan interface{}) {
t.channels[id] = c
}
func(t *topic) unregister(id int) {
func (t *topic) unregister(id int) {
delete(t.channels, id)
}
func(t *topic) shutdown() {
func (t *topic) shutdown() {
t.done <- true
}
func(t *topic) run() {
func (t *topic) run() {
go func() {
for {
select {
+1 -1
View File
@@ -8,4 +8,4 @@ import (
type Id struct {
dto.Identity
CId *cziti.ZIdentity
}
}
@@ -29,10 +29,10 @@ var (
modws2_32 = windows.NewLazySystemDLL("ws2_32.dll")
modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
procWSACreateEvent = modws2_32.NewProc("WSACreateEvent")
procNotifyAddrChange = modiphlpapi.NewProc("NotifyAddrChange")
procWSACreateEvent = modws2_32.NewProc("WSACreateEvent")
procNotifyAddrChange = modiphlpapi.NewProc("NotifyAddrChange")
procNotifyRouteChange = modiphlpapi.NewProc("NotifyRouteChange")
log = logging.Logger()
log = logging.Logger()
)
func OnIPChange(callback func()) {
@@ -43,7 +43,7 @@ func OnIPChange(callback func()) {
log.Debugf("Symbol [NotifyAddrChange] loaded at %#v", procNotifyAddrChange.Addr())
var (
err error
err error
overlap *windows.Overlapped = &windows.Overlapped{}
)
@@ -84,4 +84,4 @@ func WSACreateEvent() (windows.Handle, error) {
} else {
return windows.Handle(handlePtr), nil
}
}
}
+1 -1
View File
@@ -35,7 +35,7 @@ func Ipv4Inc(ip net.IP, maskBits int) net.IP {
newIpAsInt := ipAsInt + 1
return Uint32ToIpv4(baseIp + newIpAsInt & uint32(ipMask))
return Uint32ToIpv4(baseIp + newIpAsInt&uint32(ipMask))
}
func Ipv4ToUint32(ip net.IP) uint32 {
if len(ip) == 16 {
@@ -48,16 +48,13 @@ func init() {
setConsoleModeProc := kernel32DLL.NewProc("SetConsoleMode")
setConsoleModeProc.Call(uintptr(handle), 0x0001|0x0002|0x0004)
with := &dateFormatterNoFilename{
}
with := &dateFormatterNoFilename{}
/*with := &dateFormatterWithFilename{
}*/
with.dateFormatter.timeFormat = UTCFormat()
withFilenameLogger.SetFormatter(with)
without := &dateFormatterNoFilename{
}
without := &dateFormatterNoFilename{}
without.dateFormatter.timeFormat = UTCFormat()
noFilenamelogger.SetFormatter(without)
}
@@ -70,7 +67,7 @@ func NoFilenameLogger() *logrus.Logger {
return noFilenamelogger
}
func SetLoggingLevel(goLevel logrus.Level){
func SetLoggingLevel(goLevel logrus.Level) {
withFilenameLogger.SetLevel(goLevel)
noFilenamelogger.SetLevel(goLevel)
}
@@ -84,8 +81,8 @@ func initLogger(logger *logrus.Logger, level logrus.Level) {
logger.SetReportCaller(true)
rl, _ := rotatelogs.New(config.LogFile() + ".%Y%m%d%H%M.log",
rotatelogs.WithRotationTime(24 * time.Hour),
rl, _ := rotatelogs.New(config.LogFile()+".%Y%m%d%H%M.log",
rotatelogs.WithRotationTime(24*time.Hour),
rotatelogs.WithRotationCount(7),
rotatelogs.WithLinkName(config.LogFile()))
@@ -205,4 +202,4 @@ var errorColor = ansi.Red + "ERROR" + ansi.DefaultFG
var warnColor = ansi.Yellow + " WARN" + ansi.DefaultFG
var infoColor = ansi.White + " INFO" + ansi.DefaultFG
var debugColor = ansi.Blue + "DEBUG" + ansi.DefaultFG
var traceColor = ansi.LightBlack + "TRACE" + ansi.DefaultFG
var traceColor = ansi.LightBlack + "TRACE" + ansi.DefaultFG
+1 -1
View File
@@ -1 +1 @@
1.9.1
1.9.2