diff --git a/src/client/cluster_client_icache.cpp b/src/client/cluster_client_icache.cpp index 626b2d73..444cd279 100644 --- a/src/client/cluster_client_icache.cpp +++ b/src/client/cluster_client_icache.cpp @@ -109,6 +109,7 @@ std::shared_ptr cluster_client_t::inode_cache_get(inode_t ino) icache->readonly = inode_cfg.readonly; icache->chain.push_back(ino); std::vector chain_cfg; + // FIXME: Allow unencrypted read & write when all chain is encrypted with the same key int enc_key_count = !inode_cfg.enc_key.empty() ? 1 : 0; if (inode_cfg.parent_id) { diff --git a/src/cmd/cli.h b/src/cmd/cli.h index 6947587b..e94e3f75 100644 --- a/src/cmd/cli.h +++ b/src/cmd/cli.h @@ -49,6 +49,7 @@ public: void parse_api_opts(json11::Json::object & cfg); json11::Json parse_tags(std::string tags); + json11::Json::object format_image(const inode_config_t & cfg); void change_parent(inode_t cur, inode_t new_parent, cli_result_t *result); inode_config_t* get_inode_cfg(const std::string & name); diff --git a/src/cmd/cli_common.cpp b/src/cmd/cli_common.cpp index 355a381e..11f827a4 100644 --- a/src/cmd/cli_common.cpp +++ b/src/cmd/cli_common.cpp @@ -6,6 +6,41 @@ #include "cluster_client.h" #include "cli.h" +json11::Json::object cli_tool_t::format_image(const inode_config_t & cfg) +{ + auto pool_it = cli->st_cli.pool_config.find(INODE_POOL(cfg.num)); + bool good_pool = pool_it != cli->st_cli.pool_config.end(); + auto img = json11::Json::object { + { "name", cfg.name }, + { "size", cfg.size }, + { "inode_id", cfg.num }, + { "inode_num", INODE_NO_POOL(cfg.num) }, + { "pool_id", (uint64_t)INODE_POOL(cfg.num) }, + { "pool_name", good_pool ? pool_it->second.name : "? (ID:"+std::to_string(INODE_POOL(cfg.num))+")" }, + { "readonly", cfg.readonly }, + { "deleted", cfg.deleted }, + }; + if (!cfg.enc_key.empty()) + { + img["encrypted"] = true; + // Only show Vault key IDs + if (cfg.enc_key.substr(0, strlen(VAULT_KEY_PREFIX)) == VAULT_KEY_PREFIX) + img["enc_key_id"] = cfg.enc_key; + } + if (cfg.parent_id) + { + auto parent_it = cli->st_cli.inode_config.find(cfg.parent_id); + if (parent_it != cli->st_cli.inode_config.end()) + { + img["parent_name"] = parent_it->second.name; + } + img["parent_inode_id"] = cfg.parent_id; + img["parent_inode_num"] = INODE_NO_POOL(cfg.parent_id); + img["parent_pool_id"] = (uint64_t)INODE_POOL(cfg.parent_id); + } + return img; +} + void cli_tool_t::change_parent(inode_t cur, inode_t new_parent, cli_result_t *result) { auto cur_cfg_it = cli->st_cli.inode_config.find(cur); diff --git a/src/cmd/cli_create.cpp b/src/cmd/cli_create.cpp index b2e6acef..65eadfdc 100644 --- a/src/cmd/cli_create.cpp +++ b/src/cmd/cli_create.cpp @@ -202,27 +202,7 @@ resume_3: // Save into inode_config for library users to be able to take it from there immediately new_cfg.mod_revision = parent->etcd_result["header"]["revision"].uint64_value(); parent->cli->st_cli.insert_inode_config(new_cfg); - auto img = json11::Json::object { - { "inode_id", INODE_WITH_POOL(new_pool_id, new_id) }, - { "inode_num", new_id }, - { "name", image_name }, - { "pool_id", (uint64_t)new_pool_id }, - { "size", size }, - }; - { - auto new_pool_it = parent->cli->st_cli.pool_config.find(new_pool_id); - if (new_pool_it != parent->cli->st_cli.pool_config.end()) - { - img["pool_name"] = new_pool_it->second.name; - } - } - if (new_parent_id) - { - img["parent_name"] = new_parent; - img["parent_inode_id"] = new_parent_id; - img["parent_inode_num"] = INODE_NO_POOL(new_parent_id); - img["parent_pool_id"] = (uint64_t)INODE_POOL(new_parent_id); - } + auto img = parent->format_image(new_cfg); result = (cli_result_t){ .err = 0, .text = "Image "+image_name+" created", diff --git a/src/cmd/cli_ls.cpp b/src/cmd/cli_ls.cpp index 9a7bcdd8..b31760b7 100644 --- a/src/cmd/cli_ls.cpp +++ b/src/cmd/cli_ls.cpp @@ -59,28 +59,7 @@ struct image_lister_t { continue; } - auto pool_it = parent->cli->st_cli.pool_config.find(INODE_POOL(ic.second.num)); - bool good_pool = pool_it != parent->cli->st_cli.pool_config.end(); - auto item = json11::Json::object { - { "name", ic.second.name }, - { "size", ic.second.size }, - { "readonly", ic.second.readonly }, - { "pool_id", (uint64_t)INODE_POOL(ic.second.num) }, - { "pool_name", good_pool ? pool_it->second.name : "? (ID:"+std::to_string(INODE_POOL(ic.second.num))+")" }, - { "inode_num", INODE_NO_POOL(ic.second.num) }, - { "inode_id", ic.second.num }, - { "deleted", ic.second.deleted }, - }; - if (ic.second.parent_id) - { - auto p_it = parent->cli->st_cli.inode_config.find(ic.second.parent_id); - item["parent_name"] = p_it != parent->cli->st_cli.inode_config.end() - ? p_it->second.name : ""; - item["parent_pool_id"] = (uint64_t)INODE_POOL(ic.second.parent_id); - item["parent_inode_num"] = INODE_NO_POOL(ic.second.parent_id); - item["parent_inode_id"] = ic.second.parent_id; - } - stats[ic.second.num] = item; + stats[ic.second.num] = parent->format_image(ic.second); } } @@ -384,7 +363,7 @@ resume_1: } } cols.push_back(json11::Json::object{ - { "key", "ro" }, + { "key", "flags" }, { "title", "FLAGS" }, { "right", true }, }); @@ -412,8 +391,14 @@ resume_1: kv.second["delete_q"] = format_q(kv.second["delete_queue"].number_value()); } kv.second["size_fmt"] = format_size(kv.second["size"].uint64_value()); - kv.second["ro"] = kv.second["deleted"].bool_value() ? "DEL" : - (kv.second["readonly"].bool_value() ? "RO" : "-"); + std::string flags; + if (kv.second["deleted"].bool_value()) + flags += "DEL"; + if (kv.second["readonly"].bool_value()) + flags += (flags.empty() ? "RO" : ",RO"); + if (kv.second["encrypted"].bool_value()) + flags += (flags.empty() ? "ENC" : ",ENC"); + kv.second["flags"] = flags; } result.text = print_table(tree ? to_tree(to_list()) : to_list(), cols, parent->color); state = 100; diff --git a/src/cmd/cli_modify.cpp b/src/cmd/cli_modify.cpp index 18c3d8f3..2b28a702 100644 --- a/src/cmd/cli_modify.cpp +++ b/src/cmd/cli_modify.cpp @@ -90,7 +90,7 @@ struct image_changer_t (!new_size && !force_size || cfg.size == new_size || cfg.size >= new_size && inc_size) && (new_name == "" || new_name == image_name)) { - result = (cli_result_t){ .err = 0, .text = "No change", .data = fill_img(cfg) }; + result = (cli_result_t){ .err = 0, .text = "No change", .data = parent->format_image(cfg) }; state = 100; return; } @@ -252,42 +252,10 @@ resume_2: result = (cli_result_t){ .err = 0, .text = "Image "+image_name+" modified", - .data = fill_img(cfg) + .data = parent->format_image(cfg) }; state = 100; } - - json11::Json fill_img(inode_config_t & cfg) - { - auto img = json11::Json::object { - { "inode_id", inode_num }, - { "inode_num", INODE_NO_POOL(inode_num) }, - { "name", cfg.name }, - { "pool_id", (uint64_t)INODE_POOL(inode_num) }, - { "size", cfg.size }, - { "readonly", cfg.readonly }, - { "deleted", cfg.deleted }, - }; - { - auto pool_it = parent->cli->st_cli.pool_config.find(INODE_POOL(inode_num)); - if (pool_it != parent->cli->st_cli.pool_config.end()) - { - img["pool_name"] = pool_it->second.name; - } - } - if (cfg.parent_id) - { - auto parent_it = parent->cli->st_cli.inode_config.find(cfg.parent_id); - if (parent_it != parent->cli->st_cli.inode_config.end()) - { - img["parent_name"] = parent_it->second.name; - } - img["parent_inode_id"] = cfg.parent_id; - img["parent_inode_num"] = INODE_NO_POOL(cfg.parent_id); - img["parent_pool_id"] = (uint64_t)INODE_POOL(cfg.parent_id); - } - return img; - } }; std::function cli_tool_t::start_modify(json11::Json cfg) diff --git a/src/cmd/openapi.json b/src/cmd/openapi.json index c192b3f9..ae0b424c 100644 --- a/src/cmd/openapi.json +++ b/src/cmd/openapi.json @@ -739,7 +739,9 @@ "size": { "type": "integer", "format": "uint64", "description": "Image size in bytes" }, "used_size": { "type": "integer", "format": "uint64", "description": "Used space in bytes" }, "readonly": { "type": "boolean", "description": "Readonly flag" }, - "deleted": { "type": "boolean", "description": "Deleted flag" } + "deleted": { "type": "boolean", "description": "Deleted flag" }, + "encrypted": { "type": "boolean", "description": "Encrypted flag" }, + "enc_key_id": { "type": "boolean", "description": "Vault key ID" } } }, "ImageList": {