Skip to content

Commit

Permalink
Add snp_security_policy_file to configuration (#5865)
Browse files Browse the repository at this point in the history
  • Loading branch information
achamayou authored Dec 13, 2023
1 parent cb684d5 commit ccc9c31
Show file tree
Hide file tree
Showing 15 changed files with 118 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .daily_canary
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
-^- ___ ___
(- -) (= =) | Y & +--?
( V ) / . \ | +---=---'
/--x-m- /--n-n---xXx--/--yY------>>>----<<<>>]]{{}}---||-/\-
/--x-m- /--n-n---xXx--/--yY------>>>----<<<>>]]{{}}---||-/\---
1 change: 1 addition & 0 deletions .snpcc_canary
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
(. =) Y (0 0) (x X) Y
O \ o | /
/-xXx--//-----x=x--/-xXx--/---x---->>>--/
...
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
[5.0.0-dev10]: https://github.com/microsoft/CCF/releases/tag/ccf-5.0.0-dev10

- The `url` field in `snp_endorsements_servers` can now contain environment variables that will be resolved at startup, such as "$Fabric_NodeIPOrFQDN:2377" (#5862).
- Add a `new snp_security_policy_file` configuration value under `attestation`, superseding the lookup from `$UVM_SECURITY_CONTEXT_DIR`. The value can contain environment variables, for example: `"snp_security_policy_file": "$UVM_SECURITY_CONTEXT_DIR/security-policy-base64"`.

## [5.0.0-dev9]

Expand Down
4 changes: 4 additions & 0 deletions doc/host_config_schema/cchost_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,10 @@
"required": [],
"additionalProperties": false
},
"snp_security_policy_file": {
"type": ["string", "null"],
"description": "Path to file containing the security policy (SEV-SNP only), can contain environment variables, such as $UVM_SECURITY_CONTEXT_DIR"
},
"snp_endorsements_servers": {
"type": "array",
"items": {
Expand Down
3 changes: 2 additions & 1 deletion doc/operations/platforms/snp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ For non-Azure deployments, the certificate chain for VCEK will need to be retrie
"type": "AMD",
"url": "kdsintf.amd.com"
}
]
],
"snp_security_policy_file": "/path/to/security-policy-base64",
}
.. tip:: See :ccf_repo:`samples/config/start_config_amd_sev_snp.json` for a sample node configuration for non-Azure deployments.
Expand Down
32 changes: 32 additions & 0 deletions include/ccf/ds/nonstd.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <algorithm>
#include <array>
#include <cctype>
#include <filesystem>
#include <string>
#include <string_view>
#include <type_traits>
Expand Down Expand Up @@ -256,4 +257,35 @@ namespace nonstd
return std::string(e);
}
}

static inline std::string expand_envvars_in_path(const std::string& str)
{
std::filesystem::path path(str);

if (path.empty())
{
return str;
}

std::vector<std::filesystem::path> elements;
auto it = path.begin();
if (path.has_root_directory())
{
++it;
elements.push_back(path.root_directory());
}

while (it != path.end())
{
elements.push_back(expand_envvar(*it++));
}

std::filesystem::path resolved;
for (auto& element : elements)
{
resolved /= element;
}

return resolved.lexically_normal().string();
}
}
1 change: 1 addition & 0 deletions include/ccf/node/startup_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ struct CCFConfig
struct Attestation
{
ccf::pal::snp::EndorsementsServers snp_endorsements_servers = {};
std::optional<std::string> snp_security_policy_file = std::nullopt;

struct Environment
{
Expand Down
3 changes: 2 additions & 1 deletion samples/config/start_config_aci_sev_snp.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"type": "THIM",
"url": "169.254.169.254"
}
]
],
"snp_security_policy_file": "$UVM_SECURITY_CONTEXT_DIR/security-policy-base64"
}
}
3 changes: 2 additions & 1 deletion samples/config/start_config_amd_sev_snp.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"type": "AMD",
"url": "kdsintf.amd.com"
}
]
],
"snp_security_policy_file": "/path/to/security-policy-base64"
}
}
5 changes: 4 additions & 1 deletion src/common/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ DECLARE_JSON_OPTIONAL_FIELDS(
DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(CCFConfig::Attestation);
DECLARE_JSON_REQUIRED_FIELDS(CCFConfig::Attestation);
DECLARE_JSON_OPTIONAL_FIELDS(
CCFConfig::Attestation, snp_endorsements_servers, environment);
CCFConfig::Attestation,
snp_endorsements_servers,
environment,
snp_security_policy_file);

DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(CCFConfig);
DECLARE_JSON_REQUIRED_FIELDS(CCFConfig, network);
Expand Down
40 changes: 40 additions & 0 deletions src/ds/test/nonstd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include <stdlib.h>
#include <string>

#define FMT_HEADER_ONLY
#include <fmt/format.h>

TEST_CASE("split" * doctest::test_suite("nonstd"))
{
{
Expand Down Expand Up @@ -278,4 +281,41 @@ TEST_CASE("envvars" * doctest::test_suite("nonstd"))
REQUIRE(
"${ENV_VAR_NOT_SET}" == nonstd::expand_envvar("${ENV_VAR_NOT_SET}"));
}
{
INFO("Expand path");

std::string test_value1("test_value1");
::setenv("TEST_ENV_VAR1", test_value1.c_str(), 1);
std::string test_value2("test_value2");
::setenv("TEST_ENV_VAR2", test_value2.c_str(), 1);

REQUIRE("" == nonstd::expand_envvars_in_path(""));
REQUIRE("foo" == nonstd::expand_envvars_in_path("foo"));
REQUIRE("foo/" == nonstd::expand_envvars_in_path("foo/"));
REQUIRE("foo/bar" == nonstd::expand_envvars_in_path("foo/bar"));
REQUIRE("/" == nonstd::expand_envvars_in_path("/"));
REQUIRE("/foo" == nonstd::expand_envvars_in_path("/foo"));
REQUIRE("/foo/" == nonstd::expand_envvars_in_path("/foo/"));
REQUIRE("/foo/bar" == nonstd::expand_envvars_in_path("/foo/bar"));

REQUIRE(
fmt::format("{}", test_value1) ==
nonstd::expand_envvars_in_path("$TEST_ENV_VAR1"));
REQUIRE(
fmt::format("{}/", test_value1) ==
nonstd::expand_envvars_in_path("$TEST_ENV_VAR1/"));
REQUIRE(
fmt::format("{}/{}", test_value1, test_value2) ==
nonstd::expand_envvars_in_path("$TEST_ENV_VAR1/$TEST_ENV_VAR2"));

REQUIRE(
fmt::format("/{}", test_value1) ==
nonstd::expand_envvars_in_path("/$TEST_ENV_VAR1"));
REQUIRE(
fmt::format("/{}/", test_value1) ==
nonstd::expand_envvars_in_path("/$TEST_ENV_VAR1/"));
REQUIRE(
fmt::format("/{}/{}", test_value1, test_value2) ==
nonstd::expand_envvars_in_path("/$TEST_ENV_VAR1/$TEST_ENV_VAR2"));
}
}
17 changes: 17 additions & 0 deletions src/host/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,8 @@ int main(int argc, char** argv)
config.attestation.environment.security_context_directory.value();
}

// This will be deprecated in favour of explicit configuration entries,
// such as snp_security_policy_file and snp_endorsements_servers
if (config.enclave.platform == host::EnclavePlatform::SNP)
{
auto dir = read_required_environment_variable(
Expand All @@ -542,6 +544,21 @@ int main(int argc, char** argv)
fs::path(dir) / fs::path(report_endorsements_filename));
}

if (startup_config.attestation.snp_security_policy_file.has_value())
{
auto security_policy_file =
startup_config.attestation.snp_security_policy_file.value();
LOG_DEBUG_FMT(
"Resolving snp_security_policy_file: {}", security_policy_file);
security_policy_file =
nonstd::expand_envvars_in_path(security_policy_file);
LOG_DEBUG_FMT(
"Resolved snp_security_policy_file: {}", security_policy_file);

startup_config.attestation.environment.security_policy =
files::try_slurp_string(security_policy_file);
}

for (auto endorsement_servers_it =
startup_config.attestation.snp_endorsements_servers.begin();
endorsement_servers_it !=
Expand Down
3 changes: 2 additions & 1 deletion tests/config.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"node_data_json_file": {{ node_data_json_file|tojson }},
"attestation":
{
"snp_endorsements_servers": {{ snp_endorsements_servers|tojson }}
"snp_endorsements_servers": {{ snp_endorsements_servers|tojson }},
"snp_security_policy_file": "{{ snp_security_policy_file }}"
},
"service_data_json_file": {{ service_data_json_file|tojson }},
"command": {
Expand Down
1 change: 1 addition & 0 deletions tests/infra/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ class Network:
"node_to_node_message_limit",
"tick_ms",
"max_msg_size_bytes",
"snp_security_policy_file",
]

# Maximum delay (seconds) for updates to propagate from the primary to backups
Expand Down
8 changes: 8 additions & 0 deletions tests/infra/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,7 @@ def __init__(
node_container_image=None,
follow_redirect=True,
max_uncommitted_tx_count=0,
snp_security_policy_file=None,
**kwargs,
):
"""
Expand Down Expand Up @@ -735,6 +736,12 @@ def __init__(
s["url"] = url
snp_endorsements_servers_list.append(s)

# Default snp_security_policy_file if not set
if snp_security_policy_file is None:
snp_security_policy_file = (
"$UVM_SECURITY_CONTEXT_DIR/security-policy-base64"
)

# Validate consensus timers
if (
election_timeout_ms is not None
Expand Down Expand Up @@ -795,6 +802,7 @@ def __init__(
node_address=remote_class.get_node_address(node_address),
follow_redirect=follow_redirect,
max_uncommitted_tx_count=max_uncommitted_tx_count,
snp_security_policy_file=snp_security_policy_file,
**kwargs,
)

Expand Down

0 comments on commit ccc9c31

Please sign in to comment.