diff --git a/cmake/ccf_app.cmake b/cmake/ccf_app.cmake index 1ce54cd68e7..43332af124f 100644 --- a/cmake/ccf_app.cmake +++ b/cmake/ccf_app.cmake @@ -38,11 +38,44 @@ find_package(OpenEnclave 0.8 CONFIG REQUIRED) # Sign a built enclave library with oesign function(sign_app_library name app_oe_conf_path enclave_sign_key_path) if(TARGET ${name}) + # Produce a debuggable variant. This doesn't need to be signed, but oesign + # also stamps the other config (heap size etc) which _are_ needed + set(DEBUG_CONF_NAME ${CMAKE_CURRENT_BINARY_DIR}/${name}.debuggable.conf) + + # Need to put in a temp folder, as oesign has a fixed output path, so + # multiple calls will force unnecessary rebuilds + set(TMP_FOLDER ${CMAKE_CURRENT_BINARY_DIR}/${name}_tmp) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so.debuggable + COMMAND cp ${app_oe_conf_path} ${DEBUG_CONF_NAME} + COMMAND echo "Debug=1" >> ${DEBUG_CONF_NAME} + COMMAND mkdir -p ${TMP_FOLDER} + COMMAND ln -s ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so + ${TMP_FOLDER}/lib${name}.so + COMMAND openenclave::oesign sign -e ${TMP_FOLDER}/lib${name}.so -c + ${DEBUG_CONF_NAME} -k ${enclave_sign_key_path} + COMMAND mv ${TMP_FOLDER}/lib${name}.so.signed + ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so.debuggable + COMMAND rm -rf ${TMP_FOLDER} + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so ${app_oe_conf_path} + ${enclave_sign_key_path} + ) + + add_custom_target( + ${name}_debuggable ALL + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so.debuggable + ) + + # Produce a releaseable signed variant. This is NOT debuggable - oegdb + # cannot be attached + set(SIGNED_CONF_NAME ${CMAKE_CURRENT_BINARY_DIR}/${name}.signed.conf) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so.signed + COMMAND cp ${app_oe_conf_path} ${SIGNED_CONF_NAME} + COMMAND echo "Debug=0" >> ${SIGNED_CONF_NAME} COMMAND openenclave::oesign sign -e ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so -c - ${app_oe_conf_path} -k ${enclave_sign_key_path} + ${SIGNED_CONF_NAME} -k ${enclave_sign_key_path} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so ${app_oe_conf_path} ${enclave_sign_key_path} ) diff --git a/cmake/common.cmake b/cmake/common.cmake index c12b4fd2157..3984fa131fa 100644 --- a/cmake/common.cmake +++ b/cmake/common.cmake @@ -117,6 +117,10 @@ if("sgx" IN_LIST COMPILE_TARGETS) set(QUOTES_ENABLED ON) endif() endif() + + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(TEST_ENCLAVE_TYPE -e debug) + endif() else() set(TEST_ENCLAVE_TYPE -e virtual) endif() diff --git a/samples/apps/smallbank/app/oe_sign.conf b/samples/apps/smallbank/app/oe_sign.conf index c2ea4dbeb69..8d675d9e9f3 100644 --- a/samples/apps/smallbank/app/oe_sign.conf +++ b/samples/apps/smallbank/app/oe_sign.conf @@ -1,5 +1,4 @@ # Enclave settings: -Debug=1 NumHeapPages=327680 NumStackPages=1024 NumTCS=8 diff --git a/samples/apps/txregulator/app/oe_sign.conf b/samples/apps/txregulator/app/oe_sign.conf index 69255f0058a..2181cf78844 100644 --- a/samples/apps/txregulator/app/oe_sign.conf +++ b/samples/apps/txregulator/app/oe_sign.conf @@ -1,5 +1,4 @@ # Enclave settings: -Debug=1 NumHeapPages=50000 NumStackPages=1024 NumTCS=8 diff --git a/sphinx/source/developers/build_app.rst b/sphinx/source/developers/build_app.rst index dc61e3d6cc4..1fec3d84703 100644 --- a/sphinx/source/developers/build_app.rst +++ b/sphinx/source/developers/build_app.rst @@ -62,3 +62,14 @@ Running the Application $ cchost --enclave-file liblua_generic.signed.so [args] .. note:: When deploying the ``lua_generic`` application, members should also :ref:`register the Lua application ` before the network is opened to users. + +Debugging +--------- + +To connect a debugger to a CCF node, the configuration passed to `oesign sign` must have debugging enabled (``Debug=1``). This should be disabled for production enclaves, to ensure confidentiality is maintained. If using the ``sign_app_library`` function defined in ``ccf_app.cmake``, 2 variants will be produced for each enclave. ``name.enclave.so.debuggable`` will have debugging enabled (meaning a debugger may be attached - the optimisation level is handled indepdently), while ``name.enclave.so.signed`` produces a final debugging-disabled enclave. The produced binaries are otherwise identical. + +Additionally, the `cchost` binary must be told that the enclave type is debug: + +.. code-block:: bash + + $ cchost --enclave-file liblua_generic.enclave.so.debuggable --enclave-type debug [args] diff --git a/sphinx/source/operators/recovery.rst b/sphinx/source/operators/recovery.rst index d11bc281aed..edd58912a29 100644 --- a/sphinx/source/operators/recovery.rst +++ b/sphinx/source/operators/recovery.rst @@ -24,7 +24,6 @@ To initiate the first phase of the recovery protocol, one or several nodes shoul $ cchost --enclave-file /path/to/enclave_library - --enclave-type debug --node-address node_ip:node_port --rpc-address --public-rpc-address diff --git a/sphinx/source/operators/start_network.rst b/sphinx/source/operators/start_network.rst index 0cb63e6c631..857009cbc40 100644 --- a/sphinx/source/operators/start_network.rst +++ b/sphinx/source/operators/start_network.rst @@ -15,7 +15,6 @@ To create a new CCF network, the first node of the network should be started wit $ cchost --enclave-file /path/to/enclave_library - --enclave-type debug --node-address node_ip:node_port --rpc-address --public-rpc-address @@ -54,7 +53,6 @@ To add a new node to an existing opening network, other nodes should be started $ cchost --enclave-file /path/to/enclave_library - --enclave-type debug --node-address node_ip:node_port --rpc-address --public-rpc-address diff --git a/src/apps/batched/oe_sign.conf b/src/apps/batched/oe_sign.conf index 69255f0058a..2181cf78844 100644 --- a/src/apps/batched/oe_sign.conf +++ b/src/apps/batched/oe_sign.conf @@ -1,5 +1,4 @@ # Enclave settings: -Debug=1 NumHeapPages=50000 NumStackPages=1024 NumTCS=8 diff --git a/src/apps/js_generic/oe_sign.conf b/src/apps/js_generic/oe_sign.conf index 6a1fdb71275..d9fc0156dc3 100644 --- a/src/apps/js_generic/oe_sign.conf +++ b/src/apps/js_generic/oe_sign.conf @@ -1,5 +1,4 @@ # Enclave settings: -Debug=1 NumHeapPages=131072 NumStackPages=1024 NumTCS=8 diff --git a/src/apps/logging/oe_sign.conf b/src/apps/logging/oe_sign.conf index 69255f0058a..2181cf78844 100644 --- a/src/apps/logging/oe_sign.conf +++ b/src/apps/logging/oe_sign.conf @@ -1,5 +1,4 @@ # Enclave settings: -Debug=1 NumHeapPages=50000 NumStackPages=1024 NumTCS=8 diff --git a/src/apps/lua_generic/oe_sign.conf b/src/apps/lua_generic/oe_sign.conf index e454890f66d..aaab860797f 100644 --- a/src/apps/lua_generic/oe_sign.conf +++ b/src/apps/lua_generic/oe_sign.conf @@ -1,5 +1,4 @@ # Enclave settings: -Debug=1 NumHeapPages=32768 NumStackPages=1024 NumTCS=8 diff --git a/src/host/main.cpp b/src/host/main.cpp index 739f7794edf..05e2eab63ba 100644 --- a/src/host/main.cpp +++ b/src/host/main.cpp @@ -48,12 +48,15 @@ int main(int argc, char** argv) enum EnclaveType { + RELEASE, DEBUG, VIRTUAL }; std::vector> enclave_type_map = { - {"debug", EnclaveType::DEBUG}, {"virtual", EnclaveType::VIRTUAL}}; + {"release", EnclaveType::RELEASE}, + {"debug", EnclaveType::DEBUG}, + {"virtual", EnclaveType::VIRTUAL}}; EnclaveType enclave_type; app.add_option("-t,--enclave-type", enclave_type, "Enclave type") @@ -400,6 +403,10 @@ int main(int argc, char** argv) switch (enclave_type) { + case EnclaveType::RELEASE: + { + break; + } case EnclaveType::DEBUG: { oe_flags |= OE_ENCLAVE_FLAG_DEBUG; diff --git a/tests/code_update.py b/tests/code_update.py index 5d014f10bc7..824a1e16553 100644 --- a/tests/code_update.py +++ b/tests/code_update.py @@ -37,7 +37,9 @@ def run(args): new_node = network.create_and_trust_node(args.package, "localhost", args) assert new_node - new_code_id = get_code_id(infra.path.build_lib_path(args.patched_file_name)) + new_code_id = get_code_id( + infra.path.build_lib_path(args.patched_file_name, args.enclave_type) + ) LOG.info(f"Adding a node with unsupported code id {new_code_id}") code_not_found_exception = None @@ -110,7 +112,7 @@ def add(parser): ) args = infra.e2e_args.cli_args(add) - if args.enclave_type != "debug": + if args.enclave_type == "virtual": LOG.warning("Skipping code update test with virtual enclave") sys.exit() diff --git a/tests/governance.py b/tests/governance.py index fafa19eed50..4a1cf9b5b07 100644 --- a/tests/governance.py +++ b/tests/governance.py @@ -31,7 +31,12 @@ def run(args): mrenclave = primary_quote["mrenclave"] oed = subprocess.run( - [args.oesign, "dump", "-e", infra.path.build_lib_path(args.package)], + [ + args.oesign, + "dump", + "-e", + infra.path.build_lib_path(args.package, args.enclave_type), + ], capture_output=True, check=True, ) @@ -53,7 +58,7 @@ def add(parser): args = infra.e2e_args.cli_args(add=add) - if args.enclave_type != "debug": + if args.enclave_type == "virtual": LOG.warning("This test can only run in real enclaves, skipping") sys.exit(0) diff --git a/tests/infra/e2e_args.py b/tests/infra/e2e_args.py index e8880be13d2..ff18b328eee 100644 --- a/tests/infra/e2e_args.py +++ b/tests/infra/e2e_args.py @@ -35,8 +35,8 @@ def cli_args(add=lambda x: None, parser=None, accept_unknown=False): "-e", "--enclave-type", help="Enclave type", - default=os.getenv("TEST_ENCLAVE", "debug"), - choices=("debug", "virtual"), + default=os.getenv("TEST_ENCLAVE", "release"), + choices=("release", "debug", "virtual"), ) parser.add_argument( "-l", diff --git a/tests/infra/node.py b/tests/infra/node.py index cc03cbab4ff..9f737916f23 100644 --- a/tests/infra/node.py +++ b/tests/infra/node.py @@ -137,7 +137,7 @@ def _start( If self.debug is set to True, it will not actually start up the node, but will prompt the user to do so manually Raises exception if failed to prepare or start the node :param lib_name: the enclave package to load - :param enclave_type: default: debug. Choices: 'debug', 'virtual' + :param enclave_type: default: release. Choices: 'release', 'debug', 'virtual' :param workspace: directory where node is started :param label: label for this node (to differentiate nodes from different test runs) :return: void diff --git a/tests/infra/path.py b/tests/infra/path.py index 409afc5418a..fe0894fb63c 100644 --- a/tests/infra/path.py +++ b/tests/infra/path.py @@ -18,17 +18,21 @@ def mk_new(name, contents): mk(name, contents) -def build_lib_path(lib_name, enclave_type="debug"): - VIRTUAL_EXT = ".virtual.so" - SIGNED_EXT = ".enclave.so.signed" +def build_lib_path(lib_name, enclave_type=None): + if enclave_type == "virtual": + ext = ".virtual.so" + mode = "Virtual mode" + elif enclave_type == "debug": + ext = ".enclave.so.debuggable" + mode = "Debuggable enclave" + else: + ext = ".enclave.so.signed" + mode = "Real enclave" if os.path.isfile(lib_name): - if enclave_type == "virtual" and VIRTUAL_EXT not in lib_name: - raise ValueError(f"Virtual mode requires {VIRTUAL_EXT} enclave image") - elif enclave_type == "debug" and SIGNED_EXT not in lib_name: - raise ValueError(f"Real enclave requires {SIGNED_EXT} enclave image") + if ext not in lib_name: + raise ValueError(f"{mode} requires {ext} enclave image") return lib_name else: - ext = VIRTUAL_EXT if enclave_type == "virtual" else SIGNED_EXT # Make sure relative paths include current directory. Absolute paths will be unaffected return os.path.join(".", os.path.normpath(f"{lib_name}{ext}")) diff --git a/tests/reconfiguration.py b/tests/reconfiguration.py index 57ed6e78953..ac28cc9c93d 100644 --- a/tests/reconfiguration.py +++ b/tests/reconfiguration.py @@ -48,7 +48,7 @@ def test_add_as_many_pending_nodes(network, args): @reqs.description("Add node with untrusted code version") def test_add_node_untrusted_code(network, args): - if args.enclave_type == "debug": + if args.enclave_type != "virtual": LOG.info("Adding an invalid node (unknown code id)") code_not_found_exception = None try: