Pin UVM roots of trust and add snp_uvm_endorsements_file to configuration (#5867)

This commit is contained in:
Amaury Chamayou 2023-12-15 16:12:43 +00:00 коммит произвёл GitHub
Родитель 085a22c81d
Коммит 7b3f22fb62
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
14 изменённых файлов: 90 добавлений и 10 удалений

Просмотреть файл

@ -2,4 +2,4 @@
(. =) Y (0 0) (x X) Y (. =) Y (0 0) (x X) Y
O \ o | / O \ o | /
/-xXx--//-----x=x--/-xXx--/---x---->>>--/ /-xXx--//-----x=x--/-xXx--/---x---->>>--/
... ......

Просмотреть файл

@ -10,7 +10,8 @@ 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 [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). - 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"`. - 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"`.
- Add a new `snp_uvm_endorsements_file` configuration value under `attestation`, superseding the lookup from `$UVM_SECURITY_CONTEXT_DIR`. The value can contain environment variables, for example: `"snp_uvm_endorsements_file": "$UVM_SECURITY_CONTEXT_DIR/reference-info-base64"`. This value can come from an untrusted location, like `snp_security_policy_file` and AMD endorsements (fetched from `snp_endorsements_servers`), because the CCF code contains pre-defined roots of trust.
## [5.0.0-dev9] ## [5.0.0-dev9]

Просмотреть файл

@ -460,6 +460,10 @@
"type": ["string", "null"], "type": ["string", "null"],
"description": "Path to file containing the security policy (SEV-SNP only), can contain environment variables, such as $UVM_SECURITY_CONTEXT_DIR" "description": "Path to file containing the security policy (SEV-SNP only), can contain environment variables, such as $UVM_SECURITY_CONTEXT_DIR"
}, },
"snp_uvm_endorsements_file": {
"type": ["string", "null"],
"description": "Path to file containing UVM endorsements as a base64-encoded COSE Sign1 (SEV-SNP only). Can contain environment variables, such as $UVM_SECURITY_CONTEXT_DIR"
},
"snp_endorsements_servers": { "snp_endorsements_servers": {
"type": "array", "type": "array",
"items": { "items": {

Просмотреть файл

@ -61,6 +61,7 @@ For non-Azure deployments, the certificate chain for VCEK will need to be retrie
} }
], ],
"snp_security_policy_file": "/path/to/security-policy-base64", "snp_security_policy_file": "/path/to/security-policy-base64",
"snp_uvm_endorsements_file": "/path/to/reference-info-base64"
} }
.. tip:: See :ccf_repo:`samples/config/start_config_amd_sev_snp.json` for a sample node configuration for non-Azure deployments. .. tip:: See :ccf_repo:`samples/config/start_config_amd_sev_snp.json` for a sample node configuration for non-Azure deployments.

Просмотреть файл

@ -57,6 +57,7 @@ struct CCFConfig
{ {
ccf::pal::snp::EndorsementsServers snp_endorsements_servers = {}; ccf::pal::snp::EndorsementsServers snp_endorsements_servers = {};
std::optional<std::string> snp_security_policy_file = std::nullopt; std::optional<std::string> snp_security_policy_file = std::nullopt;
std::optional<std::string> snp_uvm_endorsements_file = std::nullopt;
struct Environment struct Environment
{ {

Просмотреть файл

@ -43,6 +43,7 @@
"url": "169.254.169.254" "url": "169.254.169.254"
} }
], ],
"snp_security_policy_file": "$UVM_SECURITY_CONTEXT_DIR/security-policy-base64" "snp_security_policy_file": "$UVM_SECURITY_CONTEXT_DIR/security-policy-base64",
"snp_uvm_endorsements_file": "$UVM_SECURITY_CONTEXT_DIR/reference-info-base64"
} }
} }

Просмотреть файл

@ -34,8 +34,13 @@
} }
}, },
"attestation": { "attestation": {
"environment": { "snp_endorsements_servers": [
"security_context_directory": "UVM_SECURITY_CONTEXT_DIR" {
} "type": "THIM",
"url": "169.254.169.254"
}
],
"snp_security_policy_file": "/path/to/security-policy-base64",
"snp_uvm_endorsements_file": "/opt/confidential-containers/share/kata-containers/reference-info-base64"
} }
} }

Просмотреть файл

@ -40,6 +40,7 @@
"url": "kdsintf.amd.com" "url": "kdsintf.amd.com"
} }
], ],
"snp_security_policy_file": "/path/to/security-policy-base64" "snp_security_policy_file": "/path/to/security-policy-base64",
"snp_uvm_endorsements_file": "/path/to/reference-info-base64"
} }
} }

Просмотреть файл

@ -83,7 +83,8 @@ DECLARE_JSON_OPTIONAL_FIELDS(
CCFConfig::Attestation, CCFConfig::Attestation,
snp_endorsements_servers, snp_endorsements_servers,
environment, environment,
snp_security_policy_file); snp_security_policy_file,
snp_uvm_endorsements_file);
DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(CCFConfig); DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(CCFConfig);
DECLARE_JSON_REQUIRED_FIELDS(CCFConfig, network); DECLARE_JSON_REQUIRED_FIELDS(CCFConfig, network);

Просмотреть файл

@ -559,6 +559,21 @@ int main(int argc, char** argv)
files::try_slurp_string(security_policy_file); files::try_slurp_string(security_policy_file);
} }
if (startup_config.attestation.snp_uvm_endorsements_file.has_value())
{
auto snp_uvm_endorsements_file =
startup_config.attestation.snp_uvm_endorsements_file.value();
LOG_DEBUG_FMT(
"Resolving snp_uvm_endorsements_file: {}", snp_uvm_endorsements_file);
snp_uvm_endorsements_file =
nonstd::expand_envvars_in_path(snp_uvm_endorsements_file);
LOG_DEBUG_FMT(
"Resolved snp_uvm_endorsements_file: {}", snp_uvm_endorsements_file);
startup_config.attestation.environment.uvm_endorsements =
files::try_slurp_string(snp_uvm_endorsements_file);
}
for (auto endorsement_servers_it = for (auto endorsement_servers_it =
startup_config.attestation.snp_endorsements_servers.begin(); startup_config.attestation.snp_endorsements_servers.begin();
endorsement_servers_it != endorsement_servers_it !=

Просмотреть файл

@ -51,6 +51,34 @@ namespace ccf
std::string feed; std::string feed;
}; };
// Roots of trust for UVM endorsements/measurement in AMD SEV-SNP attestations
static std::vector<UVMEndorsements> uvm_roots_of_trust = {
// Confidential Azure Kubertnetes Service (AKS)
{"did:x509:0:sha256:I__iuL25oXEVFdTP_aBLx_eT1RPHbCQ_ECBQfYZpt9s::eku:1.3.6."
"1.4.1.311.76.59.1.2",
"ContainerPlat-AMD-UVM",
"0"},
// Confidential Azure Container Instances (ACI)
{"did:x509:0:sha256:I__iuL25oXEVFdTP_aBLx_eT1RPHbCQ_ECBQfYZpt9s::eku:1.3.6."
"1.4.1.311.76.59.1.5",
"ConfAKS-AMD-UVM",
"0"}};
bool inline matches_uvm_roots_of_trust(const UVMEndorsements& endorsements)
{
for (const auto& uvm_root_of_trust : uvm_roots_of_trust)
{
if (
uvm_root_of_trust.did == endorsements.did &&
uvm_root_of_trust.feed == endorsements.feed &&
uvm_root_of_trust.svn <= endorsements.svn)
{
return true;
}
}
return false;
}
namespace cose namespace cose
{ {
static constexpr auto HEADER_PARAM_ISSUER = "iss"; static constexpr auto HEADER_PARAM_ISSUER = "iss";
@ -311,6 +339,18 @@ namespace ccf
phdr.feed, phdr.feed,
payload.sevsnpvm_guest_svn); payload.sevsnpvm_guest_svn);
return {did, phdr.feed, payload.sevsnpvm_guest_svn}; UVMEndorsements end{did, phdr.feed, payload.sevsnpvm_guest_svn};
if (!matches_uvm_roots_of_trust(end))
{
throw std::logic_error(fmt::format(
"UVM endorsements did {}, feed {}, svn {} "
"do not match any of the known UVM roots of trust",
end.did,
end.feed,
end.svn));
}
return end;
} }
} }

Просмотреть файл

@ -21,7 +21,8 @@
"attestation": "attestation":
{ {
"snp_endorsements_servers": {{ snp_endorsements_servers|tojson }}, "snp_endorsements_servers": {{ snp_endorsements_servers|tojson }},
"snp_security_policy_file": "{{ snp_security_policy_file }}" "snp_security_policy_file": "{{ snp_security_policy_file }}",
"snp_uvm_endorsements_file": "{{ snp_uvm_endorsements_file }}"
}, },
"service_data_json_file": {{ service_data_json_file|tojson }}, "service_data_json_file": {{ service_data_json_file|tojson }},
"command": { "command": {

Просмотреть файл

@ -197,6 +197,7 @@ class Network:
"tick_ms", "tick_ms",
"max_msg_size_bytes", "max_msg_size_bytes",
"snp_security_policy_file", "snp_security_policy_file",
"snp_uvm_endorsements_file",
] ]
# Maximum delay (seconds) for updates to propagate from the primary to backups # Maximum delay (seconds) for updates to propagate from the primary to backups

Просмотреть файл

@ -620,6 +620,7 @@ class CCFRemote(object):
follow_redirect=True, follow_redirect=True,
max_uncommitted_tx_count=0, max_uncommitted_tx_count=0,
snp_security_policy_file=None, snp_security_policy_file=None,
snp_uvm_endorsements_file=None,
**kwargs, **kwargs,
): ):
""" """
@ -742,6 +743,12 @@ class CCFRemote(object):
"$UVM_SECURITY_CONTEXT_DIR/security-policy-base64" "$UVM_SECURITY_CONTEXT_DIR/security-policy-base64"
) )
# Default snp_uvm_endorsements_file if not set
if snp_uvm_endorsements_file is None:
snp_uvm_endorsements_file = (
"$UVM_SECURITY_CONTEXT_DIR/reference-info-base64"
)
# Validate consensus timers # Validate consensus timers
if ( if (
election_timeout_ms is not None election_timeout_ms is not None
@ -803,6 +810,7 @@ class CCFRemote(object):
follow_redirect=follow_redirect, follow_redirect=follow_redirect,
max_uncommitted_tx_count=max_uncommitted_tx_count, max_uncommitted_tx_count=max_uncommitted_tx_count,
snp_security_policy_file=snp_security_policy_file, snp_security_policy_file=snp_security_policy_file,
snp_uvm_endorsements_file=snp_uvm_endorsements_file,
**kwargs, **kwargs,
) )