[release/2.x] Support new quote formats in 2.x (#4098)

This commit is contained in:
Julien Maffre 2022-08-05 08:54:51 +01:00 коммит произвёл GitHub
Родитель 2503f65b18
Коммит bde145a643
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 106 добавлений и 9 удалений

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

@ -1 +1 @@
It's a new dawn, there is a new heatwave...
It's a new dawn, there is a new heatwave....

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

@ -591,7 +591,9 @@
},
"QuoteFormat": {
"enum": [
"OE_SGX_v1"
"OE_SGX_v1",
"Insecure_Virtual",
"AMD_SEV_SNP_v1"
],
"type": "string"
},
@ -813,7 +815,7 @@
"info": {
"description": "This API provides public, uncredentialed access to service and node state.",
"title": "CCF Public Node API",
"version": "2.28.0"
"version": "2.29.0"
},
"openapi": "3.0.0",
"paths": {

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

@ -10,10 +10,16 @@ namespace ccf
{
enum class QuoteFormat
{
oe_sgx_v1 = 0
oe_sgx_v1 = 0,
insecure_virtual = 1,
amd_sev_snp_v1 = 2
};
DECLARE_JSON_ENUM(QuoteFormat, {{QuoteFormat::oe_sgx_v1, "OE_SGX_v1"}})
DECLARE_JSON_ENUM(
QuoteFormat,
{{QuoteFormat::oe_sgx_v1, "OE_SGX_v1"},
{QuoteFormat::insecure_virtual, "Insecure_Virtual"},
{QuoteFormat::amd_sev_snp_v1, "AMD_SEV_SNP_v1"}})
struct QuoteInfo
{

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

@ -139,14 +139,14 @@ namespace ccf
{
case QuoteVerificationResult::Failed:
return std::make_pair(
HTTP_STATUS_INTERNAL_SERVER_ERROR, "Quote could not be verified");
HTTP_STATUS_UNAUTHORIZED, "Quote could not be verified");
case QuoteVerificationResult::FailedCodeIdNotFound:
return std::make_pair(
HTTP_STATUS_INTERNAL_SERVER_ERROR,
HTTP_STATUS_UNAUTHORIZED,
"Quote does not contain known enclave measurement");
case QuoteVerificationResult::FailedInvalidQuotedPublicKey:
return std::make_pair(
HTTP_STATUS_INTERNAL_SERVER_ERROR,
HTTP_STATUS_UNAUTHORIZED,
"Quote report data does not contain node's public key hash");
default:
return std::make_pair(
@ -370,7 +370,7 @@ namespace ccf
openapi_info.description =
"This API provides public, uncredentialed access to service and node "
"state.";
openapi_info.document_version = "2.28.0";
openapi_info.document_version = "2.29.0";
}
void init_handlers() override

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

@ -16,6 +16,7 @@ import infra.crypto
from datetime import datetime
from infra.checker import check_can_progress
from infra.runner import ConcurrentRunner
import http
from loguru import logger as LOG
@ -375,6 +376,93 @@ def test_version(network, args):
)
@reqs.description("Issue fake join requests as untrusted client")
def test_issue_fake_join(network, args):
primary, _ = network.find_primary()
# Assemble dummy join request body
net = {"bind_address": "0:0"}
req = {}
req["node_info_network"] = {
"node_to_node_interface": net,
"rpc_interfaces": {"name": net},
}
req["consensus_type"] = "CFT"
req["startup_seqno"] = 0
with open(
os.path.join(network.common_dir, "member0_enc_pubk.pem"), "r", encoding="utf-8"
) as f:
req["public_encryption_key"] = f.read()
with primary.client(identity="user0") as c:
LOG.info("Join with SGX dummy quote (2.x node)")
req["quote_info"] = {"format": "OE_SGX_v1", "quote": "", "endorsements": ""}
r = c.post("/node/join", body=req)
if args.enclave_type == "virtual":
assert r.status_code == http.HTTPStatus.OK
assert r.body.json()["node_status"] == ccf.ledger.NodeStatus.PENDING.value
else:
assert r.status_code == http.HTTPStatus.UNAUTHORIZED
assert (
r.body.json()["error"]["code"] == "InvalidQuote"
), "Quote verification should fail when OE_SGX_v1 is specified"
LOG.info("Join with SGX real quote, but different TLS key")
# First, retrieve real quote from primary node
r = c.get("/node/quotes/self").body.json()
req["quote_info"] = {
"format": "OE_SGX_v1",
"quote": r["raw"],
"endorsements": r["endorsements"],
}
r = c.post("/node/join", body=req)
if args.enclave_type == "virtual":
# Quote is not verified by virtual node
assert r.status_code == http.HTTPStatus.OK
assert r.body.json()["node_status"] == ccf.ledger.NodeStatus.PENDING.value
else:
assert r.status_code == http.HTTPStatus.UNAUTHORIZED
assert r.body.json()["error"]["code"] == "InvalidQuote"
assert (
r.body.json()["error"]["message"]
== "Quote report data does not contain node's public key hash"
)
LOG.info("Join with virtual quote (3.x node)")
req["quote_info"] = {
"format": "Insecure_Virtual",
"quote": "",
"endorsements": "",
}
r = c.post("/node/join", body=req)
if args.enclave_type == "virtual":
assert r.status_code == http.HTTPStatus.OK
assert r.body.json()["node_status"] == ccf.ledger.NodeStatus.PENDING.value
else:
assert r.status_code == http.HTTPStatus.UNAUTHORIZED
assert (
r.body.json()["error"]["code"] == "InvalidQuote"
), "Virtual node must never join SGX network"
LOG.info("Join with AMD SEV-SNP quote")
req["quote_info"] = {
"format": "AMD_SEV_SNP_v1",
"quote": "",
"endorsements": "",
}
r = c.post("/node/join", body=req)
if args.enclave_type == "virtual":
assert r.status_code == http.HTTPStatus.OK
assert r.body.json()["node_status"] == ccf.ledger.NodeStatus.PENDING.value
else:
assert r.status_code == http.HTTPStatus.UNAUTHORIZED
# https://github.com/microsoft/CCF/issues/4072
assert (
r.body.json()["error"]["code"] == "InvalidQuote"
), "SEV-SNP node cannot currently join SGX network"
return network
@reqs.description("Replace a node on the same addresses")
@reqs.can_kill_n_nodes(1)
def test_node_replacement(network, args):
@ -590,6 +678,7 @@ def run(args):
network.start_and_open(args)
test_version(network, args)
test_issue_fake_join(network, args)
if args.consensus != "BFT":
test_add_node_invalid_service_cert(network, args)