diff --git a/lib/ziti-tunnel-cbs/include/ziti/ziti_tunnel_cbs.h b/lib/ziti-tunnel-cbs/include/ziti/ziti_tunnel_cbs.h index fea53ede..6ee7d5c8 100644 --- a/lib/ziti-tunnel-cbs/include/ziti/ziti_tunnel_cbs.h +++ b/lib/ziti-tunnel-cbs/include/ziti/ziti_tunnel_cbs.h @@ -279,7 +279,8 @@ XX(recovery_codes, model_string, array, recovery_codes, __VA_ARGS__) \ XX(code, model_number, none, code, __VA_ARGS__) #define ZTX_API_EVENT_MODEL(XX, ...) \ -BASE_EVENT_MODEL(XX, __VA_ARGS__) \ +BASE_EVENT_MODEL(XX, __VA_ARGS__) \ +XX(config_json, json, none, config, __VA_ARGS__) \ XX(new_ctrl_address, model_string, none, new_ctrl_address, __VA_ARGS__) \ XX(new_ca_bundle, model_string, none, new_ca_bundle, __VA_ARGS__) diff --git a/lib/ziti-tunnel-cbs/ziti_tunnel_ctrl.c b/lib/ziti-tunnel-cbs/ziti_tunnel_ctrl.c index d83c98b3..24f86588 100644 --- a/lib/ziti-tunnel-cbs/ziti_tunnel_ctrl.c +++ b/lib/ziti-tunnel-cbs/ziti_tunnel_ctrl.c @@ -79,14 +79,6 @@ struct tunnel_cb_s { void *cmd_ctx; }; -typedef struct api_update_req_s { - uv_work_t wr; - struct ziti_instance_s *inst; - char *config_json; - int err; - const char *errmsg; -} api_update_req; - static uv_signal_t sigusr1; const ziti_tunnel_ctrl* ziti_tunnel_init_cmd(uv_loop_t *loop, tunneler_context tunnel_ctx, event_cb on_event) { @@ -1102,20 +1094,15 @@ static void on_ziti_event(ziti_context ztx, const ziti_event_t *event) { case ZitiConfigEvent: { if (event->cfg.config) { - if (instance->identifier) { - api_update_req *req = calloc(1, sizeof(api_update_req)); - req->wr.data = req; - req->inst = instance; - req->config_json = ziti_config_to_json(event->cfg.config, 0, NULL); - uv_queue_work(CMD_CTX.loop, &req->wr, update_config, update_config_done); - } - + char *cfg_json = ziti_config_to_json(event->cfg.config, 0, NULL); api_event ev = {0}; ev.event_type = TunnelEvents.APIEvent; ev.identifier = instance->identifier; ev.new_ctrl_address = event->cfg.config->controller_url; ev.new_ca_bundle = event->cfg.config->id.ca; + ev.config_json = cfg_json; CMD_CTX.on_event((const base_event *) &ev); + free(cfg_json); } else { ZITI_LOG(WARN, "unexpected config event: config is missing"); } @@ -1467,95 +1454,7 @@ static void on_sigdump(uv_signal_t *sig, int signum) { } -static int update_file(const char *path, char *content, size_t content_len) { -#define CHECK_UV(desc, op) do{ \ - uv_fs_req_cleanup(&fs_req); \ - rc = op; \ - if (rc < 0) { \ - ZITI_LOG(ERROR, "op[" desc "] failed: %d(%s)", rc, uv_strerror(rc)); \ - goto DONE; \ - }} while(0) - - int rc = 0; - uv_fs_t fs_req = {0}; - CHECK_UV("check exiting config", uv_fs_stat(NULL, &fs_req, path, NULL)); - uint64_t mode = fs_req.statbuf.st_mode; - - char backup[FILENAME_MAX]; - snprintf(backup, sizeof(backup), "%s.bak", path); - CHECK_UV("create backup", uv_fs_rename(NULL, &fs_req, path, backup, NULL)); - - uv_os_fd_t f; - CHECK_UV("open new config", f = uv_fs_open(NULL, &fs_req, path, UV_FS_O_WRONLY | UV_FS_O_CREAT, (int) mode, NULL)); - uv_buf_t buf = uv_buf_init(content, content_len); - CHECK_UV("write new config", uv_fs_write(NULL, &fs_req, f, &buf, 1, 0, NULL)); - CHECK_UV("close new config", uv_fs_close(NULL, &fs_req, f, NULL)); - DONE: - return rc; -#undef CHECK_UV -} - -#define CHECK_UV(desc, op) do{ \ -int rc = op; \ -if (rc < 0) { \ -req->err = rc; \ -req->errmsg = uv_strerror(rc); \ -ZITI_LOG(ERROR, "op[" desc "] failed: %d(%s)", req->err, req->errmsg); \ -goto DONE; \ -}} while(0) - -static void update_config(uv_work_t *wr) { - api_update_req *req = wr->data; - const char *config_file = req->inst->identifier; - size_t cfg_len; - char *cfg_buf = NULL; - uv_file f; - - ziti_config cfg = {0}; - if (ziti_load_config(&cfg, config_file) != ZITI_OK) { - ZITI_LOG(ERROR, "failed to parse config file[%s]", config_file); - req->err = -1; - req->errmsg = "failed to parse existing config"; - goto DONE; - } - - ziti_config new_cfg = {0}; - parse_ziti_config(&new_cfg, req->config_json, strlen(req->config_json)); - - // attempt to update CA bundle external to config file - if (strncmp(cfg.id.ca, "file://", strlen("file://")) == 0) { - struct tlsuv_url_s path_uri; - CHECK_UV("parse CA bundle path", tlsuv_parse_url(&path_uri, cfg.id.ca)); - const char *path = path_uri.path; - CHECK_UV("update CA bundle file", update_file(path, (char*)new_cfg.id.ca, strlen(new_cfg.id.ca))); - FREE(new_cfg.id.ca); - new_cfg.id.ca = cfg.id.ca; - cfg.id.ca = NULL; - } - - bool write_new_cfg = true; - - if (write_new_cfg) { - cfg_buf = ziti_config_to_json(&new_cfg, 0, &cfg_len); - CHECK_UV("update config", update_file(config_file, cfg_buf, cfg_len)); - } - DONE: - free_ziti_config(&cfg); - free_ziti_config(&new_cfg); - FREE(cfg_buf); -} - -static void update_config_done(uv_work_t *wr, int err) { - api_update_req *req = wr->data; - if (req->err != 0) { - ZITI_LOG(ERROR, "failed to update config file[%s]: %d(%s)", req->inst->identifier, req->err, req->errmsg); - } else { - ZITI_LOG(INFO, "updated config file ztx[%s]", req->inst->identifier); - } - free(req->config_json); - free(req); -} IMPL_ENUM(TunnelCommand, TUNNEL_COMMANDS) diff --git a/programs/ziti-edge-tunnel/config-utils.c b/programs/ziti-edge-tunnel/config-utils.c index 0f94c974..a50355a3 100644 --- a/programs/ziti-edge-tunnel/config-utils.c +++ b/programs/ziti-edge-tunnel/config-utils.c @@ -17,6 +17,12 @@ #include #include #include +#include +#include +#include +#include +#include "tlsuv/http.h" + #if __linux__ #include #include @@ -66,3 +72,113 @@ char* get_backup_config_file_name(char* config_path) { } } +typedef struct api_update_req_s { + uv_work_t wr; + char *identifier; + char *config_json; + int err; + const char *errmsg; +} api_update_req; + + +static int update_file(const char *path, char *content, size_t content_len) { +#define CHECK_UV(desc, op) do{ \ + uv_fs_req_cleanup(&fs_req); \ + rc = op; \ + if (rc < 0) { \ + ZITI_LOG(ERROR, "op[" desc "] failed: %d(%s)", rc, uv_strerror(rc)); \ + goto DONE; \ + }} while(0) + + int rc = 0; + uv_fs_t fs_req = {0}; + CHECK_UV("check exiting config", uv_fs_stat(NULL, &fs_req, path, NULL)); + uint64_t mode = fs_req.statbuf.st_mode; + + char backup[FILENAME_MAX]; + snprintf(backup, sizeof(backup), "%s.bak", path); + CHECK_UV("create backup", uv_fs_rename(NULL, &fs_req, path, backup, NULL)); + + uv_os_fd_t f; + CHECK_UV("open new config", f = uv_fs_open(NULL, &fs_req, path, UV_FS_O_WRONLY | UV_FS_O_CREAT, (int) mode, NULL)); + uv_buf_t buf = uv_buf_init(content, content_len); + CHECK_UV("write new config", uv_fs_write(NULL, &fs_req, f, &buf, 1, 0, NULL)); + CHECK_UV("close new config", uv_fs_close(NULL, &fs_req, f, NULL)); + + DONE: + return rc; +#undef CHECK_UV +} + +#define CHECK_UV(desc, op) do{ \ +int rc = op; \ +if (rc < 0) { \ +req->err = rc; \ +req->errmsg = uv_strerror(rc); \ +ZITI_LOG(ERROR, "op[" desc "] failed: %d(%s)", req->err, req->errmsg); \ +goto DONE; \ +}} while(0) + +static void update_config(uv_work_t *wr) { + api_update_req *req = wr->data; + const char *config_file = req->identifier; + size_t cfg_len; + char *cfg_buf = NULL; + uv_file f; + + ziti_config cfg = {0}; + ziti_config new_cfg = {0}; + if (ziti_load_config(&cfg, config_file) != ZITI_OK) { + ZITI_LOG(ERROR, "failed to parse config file[%s]", config_file); + req->err = -1; + req->errmsg = "failed to parse existing config"; + goto DONE; + } + + parse_ziti_config(&new_cfg, req->config_json, strlen(req->config_json)); + + // attempt to update CA bundle external to config file + if (strncmp(cfg.id.ca, "file://", strlen("file://")) == 0) { + struct tlsuv_url_s path_uri; + CHECK_UV("parse CA bundle path", tlsuv_parse_url(&path_uri, cfg.id.ca)); + const char *path = path_uri.path; + CHECK_UV("update CA bundle file", update_file(path, (char*)new_cfg.id.ca, strlen(new_cfg.id.ca))); + free((void*)new_cfg.id.ca); + new_cfg.id.ca = cfg.id.ca; + cfg.id.ca = NULL; + } + + bool write_new_cfg = true; + + if (write_new_cfg) { + cfg_buf = ziti_config_to_json(&new_cfg, 0, &cfg_len); + CHECK_UV("update config", update_file(config_file, cfg_buf, cfg_len)); + } + DONE: + free_ziti_config(&cfg); + free_ziti_config(&new_cfg); + free(cfg_buf); +} + +static void update_config_done(uv_work_t *wr, int err) { + api_update_req *req = wr->data; + if (req->err != 0) { + ZITI_LOG(ERROR, "failed to update config file[%s]: %d(%s)", req->identifier, req->err, req->errmsg); + } else { + ZITI_LOG(INFO, "updated config file ztx[%s]", req->identifier); + } + free(req->config_json); + free(req->identifier); + free(req); +} + +void update_identity_config(uv_loop_t *l, const char *identifier, const char *cfg_json) { + if (identifier) { + api_update_req *req = calloc(1, sizeof(api_update_req)); + req->wr.data = req; + req->identifier = strdup(identifier); + req->config_json = strdup(cfg_json); + uv_queue_work(l, &req->wr, update_config, update_config_done); + } +} + diff --git a/programs/ziti-edge-tunnel/include/config-utils.h b/programs/ziti-edge-tunnel/include/config-utils.h index 9cccd1e1..4ae217c9 100644 --- a/programs/ziti-edge-tunnel/include/config-utils.h +++ b/programs/ziti-edge-tunnel/include/config-utils.h @@ -16,6 +16,7 @@ #ifndef ZITI_TUNNEL_SDK_C_CONFIG_UTILS_H #define ZITI_TUNNEL_SDK_C_CONFIG_UTILS_H +#include char* get_system_config_path(); void set_identifier_path(char* id_dir); @@ -23,4 +24,6 @@ char* get_identifier_path(); char* get_config_file_name(char* config_path); char* get_backup_config_file_name(char* config_path); +void update_identity_config(uv_loop_t *l, const char *identifier, const char *cfg_json); + #endif //ZITI_TUNNEL_SDK_C_CONFIG_UTILS_H diff --git a/programs/ziti-edge-tunnel/ziti-edge-tunnel.c b/programs/ziti-edge-tunnel/ziti-edge-tunnel.c index 7484bff9..75b06e82 100644 --- a/programs/ziti-edge-tunnel/ziti-edge-tunnel.c +++ b/programs/ziti-edge-tunnel/ziti-edge-tunnel.c @@ -729,6 +729,7 @@ static void on_event(const base_event *ev) { break; } + update_identity_config(global_loop_ref, api_ev->identifier, api_ev->config_json); identity_event id_event = {0}; id_event.Op = strdup("identity"); id_event.Action = strdup(event_name(event_updated));