33#pragma once
44
55#include " ccf/common_auth_policies.h"
6+ #include " ccf/crypto/verifier.h"
67#include " ccf/endpoint_context.h"
78#include " ccf/json_handler.h"
89#include " ccf/node_context.h"
910#include " ccf/odata_error.h"
11+ #include " ccf/service/operator_feature.h"
12+ #include " ccf/service/tables/nodes.h"
1013#include " ccf/service/tables/self_healing_open.h"
1114#include " node/node_configuration_subsystem.h"
1215#include " node/rpc/node_frontend_utils.h"
@@ -22,7 +25,7 @@ namespace ccf::node
2225 static HandlerJsonParamsAndForward wrap_self_healing_open (
2326 SelfHealingOpenHandler<Input> cb, ccf::AbstractNodeContext& node_context)
2427 {
25- return [cb = std::move (cb), node_context](
28+ return [cb = std::move (cb), & node_context](
2629 endpoints::EndpointContext& args, const nlohmann::json& params) {
2730 auto config = node_context.get_subsystem <NodeConfigurationSubsystem>();
2831 auto node_operation = node_context.get_subsystem <AbstractNodeOperation>();
@@ -45,7 +48,7 @@ namespace ccf::node
4548 auto in = params.get <Input>();
4649 self_healing_open::RequestNodeInfo info = in.info ;
4750
48- // ---- Validate the quote and store the node info ----
51+ // ---- Validate the quote against our store and store the node info ----
4952
5053 auto cert_der = ccf::crypto::public_key_der_from_cert (
5154 args.rpc_ctx ->get_session_context ()->caller_cert );
@@ -68,6 +71,8 @@ namespace ccf::node
6871 " Self-healing-open message from intrinsic id {} has a valid quote" ,
6972 info.identity .intrinsic_id );
7073
74+ // ---- The sender now has trusted code ----
75+
7176 // Validating that we haven't heard from this node before, of if we have
7277 // that the cert hasn't changed
7378 auto * node_info_handle = args.tx .rw <self_healing_open::NodeInfoMap>(
@@ -78,11 +83,11 @@ namespace ccf::node
7883 if (existing_node_info.has_value ())
7984 {
8085 // If we have seen this node before, check that the cert is the same
81- if (existing_node_info->cert_der != cert_der)
86+ if (existing_node_info->node_cert_der != cert_der)
8287 {
8388 auto message = fmt::format (
8489 " Self-healing-open message from intrinsic id {} is invalid: "
85- " certificate has changed" ,
90+ " certificate public key has changed" ,
8691 info.identity .intrinsic_id );
8792 LOG_FAIL_FMT (" {}" , message);
8893 return make_error (
@@ -92,10 +97,9 @@ namespace ccf::node
9297 else
9398 {
9499 self_healing_open::NodeInfo src_info{
95- .quote_info = info.quote_info ,
96- .identity = info.identity ,
97- .cert_der = cert_der,
98- .service_identity = info.service_identity };
100+ info,
101+ cert_der,
102+ };
99103 node_info_handle->put (info.identity .intrinsic_id , src_info);
100104 }
101105
@@ -201,8 +205,52 @@ namespace ccf::node
201205 .install ();
202206
203207 auto self_healing_open_iamopen =
204- [](auto & args, self_healing_open::TaggedWithNodeInfo in)
205- -> std::optional<ErrorDetails> {
208+ [&node_context](
209+ auto & args,
210+ self_healing_open::IAmOpenRequest in) -> std::optional<ErrorDetails> {
211+ auto sm_state = args.tx
212+ .template ro <self_healing_open::SMState>(
213+ Tables::SELF_HEALING_OPEN_SM_STATE)
214+ ->get ();
215+ if (!sm_state.has_value ())
216+ {
217+ throw std::logic_error (
218+ " Self-healing-open state machine state is not set" );
219+ }
220+
221+ if (
222+ sm_state.value () == self_healing_open::StateMachine::OPENING ||
223+ sm_state.value () == self_healing_open::StateMachine::OPEN)
224+ {
225+ auto node_operation =
226+ node_context.get_subsystem <AbstractNodeOperation>();
227+ auto & self_iamopen_request =
228+ node_operation->self_healing_open ().get_iamopen_request (args.tx );
229+
230+ auto myid = fmt::format (
231+ " {}:{} previously {}@{}" ,
232+ self_iamopen_request.info .identity .intrinsic_id ,
233+ self_healing_open::service_fingerprint_from_pem (
234+ crypto::cert_der_to_pem (
235+ self_iamopen_request.info .service_cert_der )),
236+ self_iamopen_request.prev_service_fingerprint ,
237+ self_iamopen_request.txid .to_str ());
238+ auto inid = fmt::format (
239+ " {}:{} previously {}@{}" ,
240+ in.info .identity .intrinsic_id ,
241+ self_healing_open::service_fingerprint_from_pem (
242+ crypto::cert_der_to_pem (in.info .service_cert_der )),
243+ in.prev_service_fingerprint ,
244+ in.txid .to_str ());
245+ LOG_INFO_FMT (
246+ " {} is already open, ignoring IAmOpen from {}" , myid, inid);
247+
248+ return ErrorDetails{
249+ .status = HTTP_STATUS_BAD_REQUEST,
250+ .code = ccf::errors::InvalidNodeState,
251+ .msg = " Node is already open, ignoring iamopen request" };
252+ }
253+
206254 LOG_TRACE_FMT (
207255 " Self-healing-open: receive IAmOpen from {}" ,
208256 in.info .identity .intrinsic_id );
@@ -220,9 +268,8 @@ namespace ccf::node
220268 .make_endpoint (
221269 " /self_healing_open/iamopen" ,
222270 HTTP_PUT,
223- json_adapter (
224- wrap_self_healing_open<self_healing_open::TaggedWithNodeInfo>(
225- self_healing_open_iamopen, node_context)),
271+ json_adapter (wrap_self_healing_open<self_healing_open::IAmOpenRequest>(
272+ self_healing_open_iamopen, node_context)),
226273 no_auth_required)
227274 .set_forwarding_required (endpoints::ForwardingRequired::Never)
228275 .set_openapi_hidden (true )
0 commit comments