diff --git a/release-notes.md b/release-notes.md index 343646c7..252f0f39 100644 --- a/release-notes.md +++ b/release-notes.md @@ -1,3 +1,17 @@ +# Release 1.11.1 + +## What's New +* supports reconfiguring an endpoint to point to a new controller address via ziti_api_event + +## Other changes: +* none + +## Bugs fixed: +* none + +## Dependency Updates +* none + # Release 1.10.14 ## What's New diff --git a/service/cziti/sdk.c b/service/cziti/sdk.c index 0af87980..e9a66936 100644 --- a/service/cziti/sdk.c +++ b/service/cziti/sdk.c @@ -95,6 +95,10 @@ struct ziti_service_event* ziti_event_service_event(ziti_event_t *ev) { return &ev->event.service; } +struct ziti_api_event* ziti_event_api_event(ziti_event_t *ev) { + return &ev->event.api; +} + ziti_service* ziti_service_array_get(ziti_service_array arr, int idx) { return arr ? arr[idx] : NULL; } diff --git a/service/cziti/sdk.go b/service/cziti/sdk.go index 9aa3fbc3..fd9a9945 100644 --- a/service/cziti/sdk.go +++ b/service/cziti/sdk.go @@ -757,6 +757,11 @@ func eventCB(ztx C.ziti_context, event *C.ziti_event_t) { } else { log.Debugf("mfa auth event set received with empty finger print, ziti context [%p]", zid) } + case C.ZitiAPIEvent: + apiEvent := C.ziti_event_api_event(event) + newAddress := C.GoString(apiEvent.new_ctrl_address) + cfgPath := C.GoString(zid.Options.config) + goapi.UpdateControllerAddress(cfgPath, newAddress) default: log.Infof("event %d not handled", event._type) } @@ -809,7 +814,7 @@ func LoadZiti(zid *ZIdentity, cfg string, refreshInterval int, apiPageSize int) zid.Options.pq_os_cb = C.ziti_pq_os_cb(C.ziti_pq_os_go) zid.Options.pq_process_cb = C.ziti_pq_process_cb(C.ziti_pq_process_go) zid.Options.api_page_size = C.uint32_t(apiPageSize) - zid.Options.events = C.ZitiContextEvent | C.ZitiServiceEvent | C.ZitiRouterEvent | C.ZitiMfaAuthEvent + zid.Options.events = C.ZitiContextEvent | C.ZitiServiceEvent | C.ZitiRouterEvent | C.ZitiMfaAuthEvent | C.ZitiAPIEvent zid.Options.event_cb = C.ziti_event_cb(C.eventCB) ptr := unsafe.Pointer(zid) diff --git a/service/cziti/sdk.h b/service/cziti/sdk.h index 887221f9..5e1be218 100644 --- a/service/cziti/sdk.h +++ b/service/cziti/sdk.h @@ -67,6 +67,7 @@ void ziti_dump_go_to_log_cb(void *stringsBuffer, char *line); struct ziti_context_event* ziti_event_context_event(ziti_event_t *ev); struct ziti_router_event* ziti_event_router_event(ziti_event_t *ev); struct ziti_service_event* ziti_event_service_event(ziti_event_t *ev); +struct ziti_api_event* ziti_event_api_event(ziti_event_t *ev); ziti_service* ziti_service_array_get(ziti_service_array arr, int idx); diff --git a/service/debug.bat b/service/debug.bat index bb99fe88..1de89cdd 100644 --- a/service/debug.bat +++ b/service/debug.bat @@ -1 +1 @@ -cls & "c:\Program Files\JetBrains\GoLand 2020.1.1\plugins\go\lib\dlv\windows\dlv.exe" --listen=localhost:50000 --headless=true --api-version=2 --check-go-version=false --only-same-user=false exec ziti-tunnel.exe debug +cls & "c:\Program Files\JetBrains\GoLand 2021.3.1\plugins\go\lib\dlv\windows\dlv.exe" --listen=localhost:50000 --headless=true --api-version=2 --check-go-version=false --only-same-user=false exec ziti-tunnel.exe debug diff --git a/service/ziti-tunnel/api/api.go b/service/ziti-tunnel/api/api.go index ac94c876..30b74862 100644 --- a/service/ziti-tunnel/api/api.go +++ b/service/ziti-tunnel/api/api.go @@ -36,6 +36,7 @@ type DesktopEdgeIface interface { BroadcastEvent(event interface{}) Close() UpdateMfa(fingerprint string, mfaEnabled bool, mfaNeeded bool) + UpdateControllerAddress(configFile string, address string) } type DesktopEdgeManager interface { diff --git a/service/ziti-tunnel/service/ipc.go b/service/ziti-tunnel/service/ipc.go index 2c0b8941..5b299c2d 100644 --- a/service/ziti-tunnel/service/ipc.go +++ b/service/ziti-tunnel/service/ipc.go @@ -1079,6 +1079,20 @@ func removeIdentity(out *json.Encoder, fingerprint string) { log.Debugf("identity file removed: %s", id.Path()) } + //remove any ".original" file from the filesystem if there is one... + originalFileName := id.Path() + ".original" + _, err = os.Stat(originalFileName) + if err == nil { + // file does exist and no other errors. remove it. + log.Debugf("removing .original file %s", originalFileName) + err = os.Remove(originalFileName) + if err != nil { + log.Warnf("could not remove file: %s", originalFileName) + } else { + log.Debugf("identity file removed: %s", originalFileName) + } + } + resp := dto.Response{Message: "success", Code: SUCCESS, Error: anyErrs, Payload: nil} respond(out, resp) // call shutdown some day id.CId.Shutdown() diff --git a/service/ziti-tunnel/service/state.go b/service/ziti-tunnel/service/state.go index e6bbf39c..52742ac3 100644 --- a/service/ziti-tunnel/service/state.go +++ b/service/ziti-tunnel/service/state.go @@ -578,6 +578,88 @@ func (t *RuntimeState) UpdateMfa(fingerprint string, mfaEnabled bool, mfaNeeded } } +func (t *RuntimeState) UpdateControllerAddress(configFile string, newAddress string) { + log.Debugf("request to update config file %s with new address: %s", configFile, newAddress) + + f, fe := ioutil.ReadFile(configFile) + if fe != nil { + log.Warnf("Could not read identity file: %s", configFile) + return + } + c := idcfg.Config{} + err := json.Unmarshal(f, &c) + if err != nil { + log.Warnf("Could not unmarshal config file for identity file: %s to newAddress: %s", configFile, newAddress) + return + } + + if strings.Compare(c.ZtAPI, newAddress) == 0 { + log.Debugf("not updating config for identity file %s. address already set to: %s", newAddress) + return + } + + err = saveOriginalIdentity(configFile) + if err != nil { + log.Warnf("unexpected error when saving original identity. cannot change controller address. %v", err) + return + } + + newConfigFileName := configFile + ".address.update" + defer func() { + log.Debugf("removing original file after update: %s", newConfigFileName) + os.Remove(newConfigFileName) + }() + log.Debugf("renaming identity file %s as: %s", configFile, newConfigFileName) + _ = os.Rename(configFile, newConfigFileName) + + var newAddy string + if strings.HasPrefix(newAddress, "https://") { + newAddy = newAddress + } else { + newAddy = "https://" + newAddress + } + log.Infof("updating identity file %s with new address. changing from %s to %s", configFile, c.ZtAPI, newAddy) + c.ZtAPI = newAddy + + idFile, err := os.OpenFile(configFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) + defer idFile.Close() + if err != nil { + log.Warnf("An unexpected error has occurred while trying to update identity file %s with newAddress %s. %v", configFile, newAddress, err) + return + } + + w := bufio.NewWriter(bufio.NewWriter(idFile)) + enc := json.NewEncoder(w) + _ = enc.Encode(c) + _ = w.Flush() + + err = idFile.Close() + if err != nil { + log.Warnf("An unexpected error has occurred while closing the identity file %s with newAddress %s. %v", configFile, newAddress, err) + } +} + +// if a change address header is ever processed - archive the original identity used. it will never be overwritten once created +// it will be deleted when the identity is forgotten +func saveOriginalIdentity(configFile string) error { + originalFileName := configFile + ".original" + + _, err := os.Stat(originalFileName) + if err != nil { + if os.IsNotExist(err) { + //file does not exist. good... + } else { + return err + } + } else { + log.Debugf("original identity already exists. not overwriting") + return nil + } + + log.Debugf("renaming original identity file from %s to %s", configFile, originalFileName) + return os.Rename(configFile, originalFileName) +} + func (t *RuntimeState) SetNotified(fingerprint string, notified bool) { id := t.Find(fingerprint) diff --git a/version b/version index 1cac385c..0eed1a29 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.11.0 +1.12.0