Skip to content

Commit

Permalink
[release/4.x] Cherry pick: Pass enclave path as CLI argument rather t…
Browse files Browse the repository at this point in the history
…han in configuration (#5665) (#5737)
  • Loading branch information
eddyashton authored Oct 17, 2023
1 parent 08e2efb commit 74b3481
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 15 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [4.0.11]

[4.0.11]: https://github.com/microsoft/CCF/releases/tag/ccf-4.0.11

- Path to the enclave file should now be passed as `--enclave-file` CLI argument to `cchost`, rather than `enclave.file` entry within configuration file. This is to ensure the path to the application file is attested on Confidential Containers/SNP, even if the configuration itself is provided from un-attested storage. The configuration entry is deprecated, and will be removed in a future release.

## [4.0.10]

[4.0.10]: https://github.com/microsoft/CCF/releases/tag/ccf-4.0.10
Expand Down
4 changes: 2 additions & 2 deletions doc/host_config_schema/cchost_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
}
},
"description": "This section includes configuration for the enclave application launched by this node",
"required": ["file"],
"required": [],
"additionalProperties": false
},
"network": {
Expand Down Expand Up @@ -676,6 +676,6 @@
"minimum": 0
}
},
"required": ["enclave", "network", "command"],
"required": ["network", "command"],
"additionalProperties": false
}
9 changes: 6 additions & 3 deletions src/host/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ namespace host
std::string file;
EnclaveType type;
EnclavePlatform platform;

bool operator==(const Enclave&) const = default;
};
Enclave enclave = {};

Expand Down Expand Up @@ -165,8 +167,8 @@ namespace host
};

DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(CCHostConfig::Enclave);
DECLARE_JSON_REQUIRED_FIELDS(CCHostConfig::Enclave, type, file);
DECLARE_JSON_OPTIONAL_FIELDS(CCHostConfig::Enclave, platform);
DECLARE_JSON_REQUIRED_FIELDS(CCHostConfig::Enclave);
DECLARE_JSON_OPTIONAL_FIELDS(CCHostConfig::Enclave, file, type, platform);

DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(CCHostConfig::OutputFiles);
DECLARE_JSON_REQUIRED_FIELDS(CCHostConfig::OutputFiles);
Expand Down Expand Up @@ -221,9 +223,10 @@ namespace host
CCHostConfig::Command, service_certificate_file, start, join, recover);

DECLARE_JSON_TYPE_WITH_BASE_AND_OPTIONAL_FIELDS(CCHostConfig, CCFConfig);
DECLARE_JSON_REQUIRED_FIELDS(CCHostConfig, enclave, command);
DECLARE_JSON_REQUIRED_FIELDS(CCHostConfig, command);
DECLARE_JSON_OPTIONAL_FIELDS(
CCHostConfig,
enclave,
tick_interval,
slow_io_logging_threshold,
node_client_interface,
Expand Down
36 changes: 33 additions & 3 deletions src/host/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,13 @@ int main(int argc, char** argv)
{
// ignore SIGPIPE
signal(SIGPIPE, SIG_IGN);
CLI::App app{"ccf"};
CLI::App app{
"CCF Host launcher. Runs a single CCF node, based on the given "
"configuration file.\n"
"Some parameters are marked \"(security critical)\" - these must be passed "
"on the CLI rather than within a configuration file, so that (on relevant "
"platforms) their value is captured in an attestation even if the "
"configuration file itself is unattested.\n"};

std::string config_file_path = "config.json";
app.add_option(
Expand Down Expand Up @@ -109,9 +115,15 @@ int main(int argc, char** argv)
.add_option(
"--enclave-log-level",
enclave_log_level,
"Logging level for the enclave code")
"Logging level for the enclave code (security critical)")
->transform(CLI::CheckedTransformer(log_level_options, CLI::ignore_case));

std::string enclave_file_path;
app.add_option(
"--enclave-file",
enclave_file_path,
"Path to enclave application (security critical)");

try
{
app.parse(argc, argv);
Expand Down Expand Up @@ -262,8 +274,26 @@ int main(int argc, char** argv)
config.slow_io_logging_threshold;

// create the enclave
if (!config.enclave.file.empty())
{
LOG_FAIL_FMT(
"DEPRECATED: Enclave path was specified in config file! This should be "
"removed from the config, and passed directly to the CLI instead");

if (enclave_file_path.empty())
{
enclave_file_path = config.enclave.file;
}
}

if (enclave_file_path.empty())
{
LOG_FATAL_FMT("No enclave file path specified");
return static_cast<int>(CLI::ExitCodes::ValidationError);
}

host::Enclave enclave(
config.enclave.file, config.enclave.type, config.enclave.platform);
enclave_file_path, config.enclave.type, config.enclave.platform);

// messaging ring buffers
const auto buffer_size = config.memory.circuit_size;
Expand Down
1 change: 0 additions & 1 deletion tests/config.jinja
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"enclave": {
"file": "{{ enclave_file }}",
"type": "{{ enclave_type }}",
"platform": "{{ enclave_platform }}"
},
Expand Down
17 changes: 12 additions & 5 deletions tests/e2e_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ def run_file_operations(args):
network.stop_all_nodes(skip_verification=True)

test_split_ledger_on_stopped_network(primary, args)
args.common_read_only_ledger_dir = None # Reset for future tests


def run_tls_san_checks(args):
Expand All @@ -306,7 +307,6 @@ def run_tls_san_checks(args):
args.perf_nodes,
pdb=args.pdb,
) as network:
args.common_read_only_ledger_dir = None # Reset from previous test
network.start_and_open(args)
network.verify_service_certificate_validity_period(
args.initial_service_cert_validity_days
Expand Down Expand Up @@ -361,7 +361,8 @@ def run_tls_san_checks(args):
# works as intended. It is difficult to do with the existing framework
# as is because of the indirections and the fact that start() is a
# synchronous call.
start_node_path = network.nodes[0].remote.remote.root
node = network.nodes[0]
start_node_path = node.remote.remote.root
# Remove ledger and pid file to allow a restart
shutil.rmtree(os.path.join(start_node_path, "0.ledger"))
os.remove(os.path.join(start_node_path, "node.pid"))
Expand All @@ -381,7 +382,15 @@ def run_tls_san_checks(args):
env["ASAN_OPTIONS"] = "alloc_dealloc_mismatch=0"

proc = subprocess.Popen(
["./cchost", "--config", "0.config.json", "--config-timeout", "10s"],
[
"./cchost",
"--config",
"0.config.json",
"--config-timeout",
f"{config_timeout}s",
"--enclave-file",
node.remote.enclave_file,
],
cwd=start_node_path,
env=env,
stdout=open(os.path.join(start_node_path, "out"), "wb"),
Expand Down Expand Up @@ -435,7 +444,6 @@ def run_preopen_readiness_check(args):
args.perf_nodes,
pdb=args.pdb,
) as network:
args.common_read_only_ledger_dir = None # Reset from previous test
network.start(args)
primary, _ = network.find_primary()
with primary.client() as c:
Expand All @@ -459,7 +467,6 @@ def run_pid_file_check(args):
args.perf_nodes,
pdb=args.pdb,
) as network:
args.common_read_only_ledger_dir = None # Reset from previous test
network.start_and_open(args)
LOG.info("Check that pid file exists")
node = network.nodes[0]
Expand Down
9 changes: 8 additions & 1 deletion tests/infra/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ def __init__(
t = t_env.get_template(self.TEMPLATE_CONFIGURATION_FILE)
output = t.render(
start_type=start_type.name.title(),
enclave_file=self.enclave_file,
enclave_file=self.enclave_file, # Ignored by current jinja, but passed for LTS compat
enclave_type=enclave_type.title(),
enclave_platform=enclave_platform.title()
if enclave_platform == "virtual"
Expand Down Expand Up @@ -837,6 +837,12 @@ def __init__(
"--enclave-log-level",
enclave_log_level,
]

if v is None or v >= Version("4.0.11"):
cmd += [
"--enclave-file",
self.enclave_file,
]

if start_type == StartType.start:
members_info = kwargs.get("members_info")
Expand Down Expand Up @@ -884,6 +890,7 @@ def __init__(
sig_tx_interval = kwargs.get("sig_tx_interval")

primary_rpc_interface = host.get_primary_interface()

cmd = [
bin_path,
f"--enclave-file={self.enclave_file}",
Expand Down

0 comments on commit 74b3481

Please sign in to comment.