mirror of
https://github.com/openziti/desktop-edge-win.git
synced 2026-10-13 00:02:50 +00:00
Merge pull request #323 from openziti/identity-onOff-cmdline
Identity on off cmdline
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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" });
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -7,3 +7,4 @@ NFWintunInstaller.msi
|
||||
wintun.dll
|
||||
|
||||
gdb.txt
|
||||
logs
|
||||
|
||||
@@ -321,4 +321,4 @@ Set-NetIPInterface -InterfaceIndex $i.ifIndex -InterfaceMetric %d`, interfaceNam
|
||||
if err != nil {
|
||||
log.Errorf("ERROR setting interface metric: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
+55
-37
@@ -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()
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
-8
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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")
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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(¤tLogLevel, "query", "q", false, "Query current loglevel")
|
||||
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
|
||||
package constants
|
||||
|
||||
const(
|
||||
const (
|
||||
Ipv4ip = "100.64.0.1"
|
||||
Ipv4MaxMask = 8
|
||||
Ipv4MinMask = 16
|
||||
Ipv4MaxMask = 8
|
||||
Ipv4MinMask = 16
|
||||
Ipv4DefaultMask = 10
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -53,4 +53,4 @@ func EnsurePermissions(group string) string {
|
||||
}
|
||||
|
||||
return sid
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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++
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user