From 2edae8a425ae3442ee73469ca3fd2f3bf9422301 Mon Sep 17 00:00:00 2001
From: liuxu <liuxu156@huawei.com>
Date: Mon, 16 Dec 2024 17:11:04 +0800
Subject: [PATCH 197/198] coco:support confidential containers

Signed-off-by: liuxu <liuxu156@huawei.com>
---
 cmake/options.cmake                           | 11 +++
 src/common/constants.h                        |  6 ++
 src/daemon/common/cri/v1/v1_cri_helpers.cc    | 71 +++++++++++++---
 src/daemon/common/cri/v1/v1_cri_helpers.h     |  4 +
 .../v1/v1_cri_container_manager_service.cc    |  5 ++
 .../v1/v1_cri_pod_sandbox_manager_service.cc  | 14 +++-
 .../executor/container_cb/execution_create.c  | 12 +++
 src/daemon/modules/api/image_api.h            |  3 +
 src/daemon/modules/image/CMakeLists.txt       | 10 +++
 src/daemon/modules/image/image.c              | 46 +++++++++++
 .../modules/image/remote/CMakeLists.txt       | 13 +++
 .../modules/image/remote/remote_image.c       | 81 +++++++++++++++++++
 .../modules/image/remote/remote_image.h       | 40 +++++++++
 .../sandbox/sandboxer/sandboxer_sandbox.cc    | 10 ++-
 14 files changed, 308 insertions(+), 18 deletions(-)
 create mode 100644 src/daemon/modules/image/remote/CMakeLists.txt
 create mode 100644 src/daemon/modules/image/remote/remote_image.c
 create mode 100644 src/daemon/modules/image/remote/remote_image.h

diff --git a/cmake/options.cmake b/cmake/options.cmake
index 018502d7..efbd0a52 100644
--- a/cmake/options.cmake
+++ b/cmake/options.cmake
@@ -62,6 +62,17 @@ if (ENABLE_SANDBOXER STREQUAL "ON")
     endif()
 endif()
 
+option(ENABLE_REMOTE_IMAGE "Enable remote image" OFF)
+if (ENABLE_REMOTE_IMAGE STREQUAL "ON")
+    if (ENABLE_SANDBOXER)
+        add_definitions(-DENABLE_REMOTE_IMAGE)
+        set(ENABLE_REMOTE_IMAGE 1)
+        message("${Green}--  Enable remote image${ColourReset}")
+    else()
+        message("${Yellow}-- Can not enable remote image, remote image need enable sandboxer first ${ColourReset}")
+    endif()
+endif()
+
 option(ENABLE_OOM_MONITOR "Enable oom monitor" ON)
 if (ENABLE_OOM_MONITOR STREQUAL "ON")
     add_definitions(-DENABLE_OOM_MONITOR)
diff --git a/src/common/constants.h b/src/common/constants.h
index 8a6f86d8..7759896f 100644
--- a/src/common/constants.h
+++ b/src/common/constants.h
@@ -218,6 +218,12 @@ typedef enum { WAIT_CONDITION_STOPPED = 0, WAIT_CONDITION_REMOVED = 1 } wait_con
 #define CRI_CONTAINER_TYPE_LABEL_KEY "cri.isulad.type"
 #define CRI_CONTAINER_TYPE_LABEL_SANDBOX "podsandbox"
 
+#ifdef ENABLE_REMOTE_IMAGE
+// Note: Currently, remote image is used only in confidentail container, so the image is supposed to be encrypted
+#define SANDBOX_IMAGE_TYPE_REMOTE "remote"
+#define IMAGE_NAME_COCO "[Encrypted]"
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/daemon/common/cri/v1/v1_cri_helpers.cc b/src/daemon/common/cri/v1/v1_cri_helpers.cc
index d71e3681..48dcfb45 100644
--- a/src/daemon/common/cri/v1/v1_cri_helpers.cc
+++ b/src/daemon/common/cri/v1/v1_cri_helpers.cc
@@ -325,10 +325,32 @@ void AddSecurityOptsToHostConfig(std::vector<std::string> &securityOpts, host_co
 }
 
 #ifdef ENABLE_SANDBOXER
+static defs_map_string_object_sandboxer_element *GetCRISandboxer(
+    const std::string &runtime, struct service_arguments *args)
+{
+    defs_map_string_object_sandboxer_element *criSandboxer = nullptr;
+    defs_map_string_object_sandboxer *criSandboxerList = nullptr;
+
+    criSandboxerList = args->json_confs->cri_sandboxers;
+    for (size_t i = 0; i < criSandboxerList->len; i++) {
+        if (criSandboxerList->keys[i] == nullptr || criSandboxerList->values[i] == nullptr ||
+            criSandboxerList->values[i]->name == nullptr) {
+            WARN("CRI runtimes key or value is null");
+            continue;
+        }
+
+        if (runtime == std::string(criSandboxerList->keys[i])) {
+            criSandboxer = criSandboxerList->values[i];
+            break; 
+        }
+    }
+    return criSandboxer;
+}
+
 std::string CRISandboxerConvert(const std::string &runtime)
 {
     std::string sandboxer;
-    defs_map_string_object_sandboxer *criSandboxerList = nullptr;
+    defs_map_string_object_sandboxer_element *criSandboxer = nullptr;
 
     if (runtime.empty()) {
         return DEFAULT_SANDBOXER_NAME;
@@ -346,24 +368,47 @@ std::string CRISandboxerConvert(const std::string &runtime)
     }
 
     sandboxer = DEFAULT_SANDBOXER_NAME;
-    criSandboxerList = args->json_confs->cri_sandboxers;
-    for (size_t i = 0; i < criSandboxerList->len; i++) {
-        if (criSandboxerList->keys[i] == nullptr || criSandboxerList->values[i] == nullptr ||
-            criSandboxerList->values[i]->name == nullptr) {
-            WARN("CRI runtimes key or value is null");
-            continue;
-        }
-
-        if (runtime == std::string(criSandboxerList->keys[i])) {
-            sandboxer = std::string(criSandboxerList->values[i]->name);
-            break;
-        }
+    criSandboxer = GetCRISandboxer(runtime, args);
+    if (criSandboxer != nullptr) {
+        sandboxer = std::string(criSandboxer->name);
     }
 
 out:
     (void)isulad_server_conf_unlock();
     return sandboxer;
 }
+
+#ifdef ENABLE_REMOTE_IMAGE
+std::string GetCRISandboxerImageType(const std::string &runtime)
+{
+    std::string imageType = "";
+    defs_map_string_object_sandboxer_element *criSandboxer = nullptr;
+
+    if (runtime.empty()) {
+        return imageType;
+    }
+
+    if (isulad_server_conf_rdlock()) {
+        ERROR("Lock isulad server conf failed");
+        return imageType;
+    }
+
+    struct service_arguments *args = conf_get_server_conf();
+    if (args == nullptr || args->json_confs == nullptr || args->json_confs->cri_sandboxers == nullptr) {
+        ERROR("Cannot get cri sandboxer list");
+        goto out;
+    }
+
+    criSandboxer = GetCRISandboxer(runtime, args);
+    if (criSandboxer != nullptr && criSandboxer->image_type != nullptr) {
+        imageType = std::string(criSandboxer->image_type);
+    }
+
+out:
+    (void)isulad_server_conf_unlock();
+    return imageType;
+}
+#endif
 #else
 std::string CRISandboxerConvert(const std::string &runtime)
 {
diff --git a/src/daemon/common/cri/v1/v1_cri_helpers.h b/src/daemon/common/cri/v1/v1_cri_helpers.h
index 6a848581..4fd15d0b 100644
--- a/src/daemon/common/cri/v1/v1_cri_helpers.h
+++ b/src/daemon/common/cri/v1/v1_cri_helpers.h
@@ -69,6 +69,10 @@ void AddSecurityOptsToHostConfig(std::vector<std::string> &securityOpts, host_co
 
 std::string CRISandboxerConvert(const std::string &runtime);
 
+#ifdef ENABLE_REMOTE_IMAGE
+std::string GetCRISandboxerImageType(const std::string &runtime);
+#endif
+
 void ApplySandboxSecurityContextToHostConfig(const runtime::v1::LinuxSandboxSecurityContext &context, host_config *hc,
                                              Errors &error);
 #ifdef ENABLE_CDI
diff --git a/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc b/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc
index fe1cca0c..1cc584fb 100644
--- a/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc
+++ b/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc
@@ -371,6 +371,11 @@ auto ContainerManagerService::GenerateSandboxInfo(
     }
 
     sandbox_info->sandboxer = util_strdup_s(sandbox.GetSandboxer().c_str());
+#ifdef ENABLE_REMOTE_IMAGE
+    sandbox_info->image_type = util_strdup_s(
+        CRIHelpersV1::GetCRISandboxerImageType(sandbox.GetSandboxer()).c_str()
+    );
+#endif
     sandbox_info->id = util_strdup_s(sandbox.GetId().c_str());
     sandbox_info->pid = sandbox.GetPid();
     sandbox_info->task_address = util_strdup_s(sandbox.GetTaskAddress().c_str());
diff --git a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc
index 8a7779ad..fd87e90b 100644
--- a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc
+++ b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc
@@ -468,11 +468,17 @@ auto PodSandboxManagerService::RunPodSandbox(const runtime::v1::PodSandboxConfig
     // But pull image interface is only in CRI image service, and it can't be called in shim controller,
     // so we pull image in CRI pod service.
     const std::string &image = m_podSandboxImage;
-    if (!EnsureSandboxImageExists(image, runtimeInfo.sandboxer, error)) {
-        ERROR("Failed to pull sandbox image %s: %s", image.c_str(), error.NotEmpty() ? error.GetCMessage() : "");
-        error.Errorf("Failed to pull sandbox image %s: %s", image.c_str(), error.NotEmpty() ? error.GetCMessage() : "");
-        return response_id;
+#ifdef ENABLE_REMOTE_IMAGE
+    if (CRIHelpersV1::GetCRISandboxerImageType(runtimeInfo.sandboxer) != std::string(SANDBOX_IMAGE_TYPE_REMOTE)) {
+#endif
+        if (!EnsureSandboxImageExists(image, runtimeInfo.sandboxer, error)) {
+            ERROR("Failed to pull sandbox image %s: %s", image.c_str(), error.NotEmpty() ? error.GetCMessage() : "");
+            error.Errorf("Failed to pull sandbox image %s: %s", image.c_str(), error.NotEmpty() ? error.GetCMessage() : "");
+            return response_id;
+        }
+#ifdef ENABLE_REMOTE_IMAGE
     }
+#endif
 
     // Step 3: Prepare sandbox checkpoint
     PrepareSandboxCheckpoint(config, jsonCheckpoint, error);
diff --git a/src/daemon/executor/container_cb/execution_create.c b/src/daemon/executor/container_cb/execution_create.c
index dcbdd1d3..6cd860c2 100644
--- a/src/daemon/executor/container_cb/execution_create.c
+++ b/src/daemon/executor/container_cb/execution_create.c
@@ -1016,6 +1016,18 @@ static int get_request_container_info(const container_create_request *request, c
 
 static int get_request_image_info(const container_create_request *request, char **image_type, char **image_name)
 {
+#ifdef ENABLE_REMOTE_IMAGE
+    if (is_container_in_sandbox(request->sandbox) &&
+        strcmp(request->sandbox->image_type, IMAGE_TYPE_REMOTE) == 0) {
+        /*
+         * Note: Currently, remote image type and coco image type 
+         * are considered to be the same type.
+         */ 
+        *image_type = util_strdup_s(IMAGE_TYPE_REMOTE);
+        *image_name = util_strdup_s(IMAGE_NAME_COCO);
+        return 0;
+    }
+#endif
     *image_type = im_get_image_type(request->image, request->rootfs);
     if (*image_type == NULL) {
         return -1;
diff --git a/src/daemon/modules/api/image_api.h b/src/daemon/modules/api/image_api.h
index f35cd013..062684c9 100644
--- a/src/daemon/modules/api/image_api.h
+++ b/src/daemon/modules/api/image_api.h
@@ -41,6 +41,9 @@ extern "C" {
 #define IMAGE_TYPE_OCI "oci"
 #define IMAGE_TYPE_EMBEDDED "embedded"
 #define IMAGE_TYPE_EXTERNAL "external"
+#ifdef ENABLE_REMOTE_IMAGE
+#define IMAGE_TYPE_REMOTE SANDBOX_IMAGE_TYPE_REMOTE
+#endif
 
 typedef struct {
     char *image;
diff --git a/src/daemon/modules/image/CMakeLists.txt b/src/daemon/modules/image/CMakeLists.txt
index d8b78ce1..6d31a1ea 100644
--- a/src/daemon/modules/image/CMakeLists.txt
+++ b/src/daemon/modules/image/CMakeLists.txt
@@ -33,6 +33,16 @@ if (ENABLE_EMBEDDED_IMAGE)
         )
 endif()
 
+if (ENABLE_REMOTE_IMAGE)
+    add_subdirectory(remote)
+    list(APPEND local_image_srcs
+        ${REMOTE_SRCS}
+        )
+    list(APPEND local_image_incs
+        ${REMOTE_INCS}
+        )
+endif()
+
 set(IMAGE_SRCS
     ${local_image_srcs}
     PARENT_SCOPE
diff --git a/src/daemon/modules/image/image.c b/src/daemon/modules/image/image.c
index 871f5f39..baf2ba9d 100644
--- a/src/daemon/modules/image/image.c
+++ b/src/daemon/modules/image/image.c
@@ -125,6 +125,10 @@ struct bim_type {
 #include "oci_image.h"
 #endif
 
+#ifdef ENABLE_REMOTE_IMAGE
+#include "remote_image.h"
+#endif
+
 #ifdef ENABLE_EMBEDDED_IMAGE
 #include "embedded_image.h"
 #include "db_all.h"
@@ -243,6 +247,45 @@ static const struct bim_ops g_ext_ops = {
 #endif
 };
 
+#ifdef ENABLE_REMOTE_IMAGE
+/* remote */
+static const struct bim_ops g_remote_ops = {
+    .init = NULL,
+    .clean_resource = NULL,
+    .detect = NULL,
+
+    .prepare_rf = remote_prepare_rf,
+    .mount_rf = remote_mount_rf,
+    .umount_rf = remote_umount_rf,
+    .delete_rf = remote_delete_rf,
+    .delete_broken_rf = remote_delete_broken_rf,
+    .export_rf = NULL,
+    .get_dir_rf = NULL,
+
+    .merge_conf = remote_merge_conf_rf,
+    .get_user_conf = remote_get_user_conf,
+
+    .list_ims = NULL,
+    .get_image_count = NULL,
+    .rm_image = remote_rmi,
+    .inspect_image = NULL,
+    .resolve_image_name = remote_resolve_image_name,
+    .container_fs_usage = remote_container_filesystem_usage,
+    .get_filesystem_info = remote_get_filesystem_info,
+    .image_status = NULL,
+    .load_image = NULL,
+    .pull_image = NULL,
+    .login = NULL,
+    .logout = NULL,
+    .tag_image = NULL,
+    .import = NULL,
+    .image_summary = NULL,
+#ifdef ENABLE_IMAGE_SEARCH
+    .search_image = NULL,
+#endif
+};
+#endif
+
 static const struct bim_type g_bims[] = {
 #ifdef ENABLE_OCI_IMAGE
     {
@@ -254,6 +297,9 @@ static const struct bim_type g_bims[] = {
 #ifdef ENABLE_EMBEDDED_IMAGE
     { .image_type = IMAGE_TYPE_EMBEDDED, .ops = &g_embedded_ops },
 #endif
+#ifdef ENABLE_REMOTE_IMAGE
+    { .image_type = IMAGE_TYPE_REMOTE, .ops = &g_remote_ops },
+#endif
 };
 
 
diff --git a/src/daemon/modules/image/remote/CMakeLists.txt b/src/daemon/modules/image/remote/CMakeLists.txt
new file mode 100644
index 00000000..6e7dab6d
--- /dev/null
+++ b/src/daemon/modules/image/remote/CMakeLists.txt
@@ -0,0 +1,13 @@
+# get current directory sources files
+aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} local_remote_srcs)
+
+set(REMOTE_SRCS
+    ${local_remote_srcs}
+    PARENT_SCOPE
+    )
+
+set(REMOTE_INCS
+    ${CMAKE_CURRENT_SOURCE_DIR}
+        PARENT_SCOPE
+    )
+
diff --git a/src/daemon/modules/image/remote/remote_image.c b/src/daemon/modules/image/remote/remote_image.c
new file mode 100644
index 00000000..87b7593d
--- /dev/null
+++ b/src/daemon/modules/image/remote/remote_image.c
@@ -0,0 +1,81 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2025-2026. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ *     http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: liuxu
+ * Create: 2025-02-11
+ * Explanation: provide remote image function
+ ******************************************************************************/
+#include "remote_image.h"
+
+#include <isula_libutils/log.h>
+
+#include "utils.h"
+
+
+char *remote_resolve_image_name(const char *name)
+{
+    return util_strdup_s(IMAGE_NAME_COCO);
+}
+
+int remote_prepare_rf(const im_prepare_request *request, char **real_rootfs)
+{
+    if (real_rootfs == NULL) {
+        ERROR("Failed to prepare remote rootfs, rootfs is NULL.");
+        return -1;
+    }
+    // real_rootfs will be changed by runtime when sandbox image type is "remote"
+    *real_rootfs = util_strdup_s("rootfs");
+    return 0;
+}
+
+int remote_rmi(const im_rmi_request *request)
+{
+    return 0;
+}
+
+int remote_get_filesystem_info(im_fs_info_response **response)
+{
+    return 0;
+}
+
+int remote_container_filesystem_usage(const im_container_fs_usage_request *request, imagetool_fs_info **fs_usage)
+{
+    return 0;
+}
+
+int remote_delete_broken_rf(const im_delete_rootfs_request *request)
+{
+    return 0;
+}
+
+int remote_delete_rf(const im_delete_rootfs_request *request)
+{
+    return 0;
+}
+
+int remote_umount_rf(const im_umount_request *request)
+{
+    return 0;
+}
+
+int remote_mount_rf(const im_mount_request *request)
+{
+    return 0;
+}
+
+int remote_merge_conf_rf(const char *img_name, container_config *container_spec)
+{
+    return 0;
+}
+
+int remote_get_user_conf(const char *basefs, host_config *hc, const char *userstr, defs_process_user *puser)
+{
+    return 0;
+}
diff --git a/src/daemon/modules/image/remote/remote_image.h b/src/daemon/modules/image/remote/remote_image.h
new file mode 100644
index 00000000..be952129
--- /dev/null
+++ b/src/daemon/modules/image/remote/remote_image.h
@@ -0,0 +1,40 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2025-2026. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ *     http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: liuxu
+ * Create: 2025-02-11
+ * Explanation: provide remote image function definition
+ ******************************************************************************/
+#ifndef DAEMON_MODULES_IMAGE_REMOTE_IMAGE_H
+#define DAEMON_MODULES_IMAGE_REMOTE_IMAGE_H
+
+#include "image_api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char *remote_resolve_image_name(const char *name);
+int remote_prepare_rf(const im_prepare_request *request, char **real_rootfs);
+int remote_rmi(const im_rmi_request *request);
+int remote_get_filesystem_info(im_fs_info_response **response);
+int remote_container_filesystem_usage(const im_container_fs_usage_request *request, imagetool_fs_info **fs_usage);
+int remote_delete_broken_rf(const im_delete_rootfs_request *request);
+int remote_delete_rf(const im_delete_rootfs_request *request);
+int remote_umount_rf(const im_umount_request *request);
+int remote_mount_rf(const im_mount_request *request);
+int remote_merge_conf_rf(const char *img_name, container_config *container_spec);
+int remote_get_user_conf(const char *basefs, host_config *hc, const char *userstr, defs_process_user *puser);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/daemon/sandbox/sandboxer/sandboxer_sandbox.cc b/src/daemon/sandbox/sandboxer/sandboxer_sandbox.cc
index b2e2fb32..e26b87c8 100644
--- a/src/daemon/sandbox/sandboxer/sandboxer_sandbox.cc
+++ b/src/daemon/sandbox/sandboxer/sandboxer_sandbox.cc
@@ -31,6 +31,8 @@
 #include "cxxutils.h"
 #include "utils_timestamp.h"
 #include "utils_array.h"
+#include "constants.h"
+#include "v1_cri_helpers.h"
 
 namespace sandbox {
 
@@ -297,6 +299,12 @@ static defs_process *clone_defs_process(defs_process *process_spec)
 
 auto SandboxerSandbox::GenerateCtrlRootfs(sandbox_task *task, const char *baseFs) -> int
 {
+#ifdef ENABLE_REMOTE_IMAGE
+    // do not mount image to vm for remote or confidential containers
+    if (CRIHelpersV1::GetCRISandboxerImageType(GetSandboxer()) == std::string(SANDBOX_IMAGE_TYPE_REMOTE)) {
+        return 0;
+    }
+#endif
     size_t len = 1;
     if (nullptr == baseFs) {
         ERROR("Container %s has no base fs", task->task_id);
@@ -573,7 +581,7 @@ auto SandboxerSandbox::PrepareExec(const char *containerId, const char *execId,
     }
     process = process_wrapper->move();
     if (InitApiSandbox(apiSandbox) != 0) {
-        ERROR("Failed to init %s api sandbox.", containerId);
+        ERROR("Failed to update %s api sandbox.", containerId);
         goto del_out;
     }
     if (DoSandboxUpdate(apiSandbox) != 0) {
-- 
2.34.1

