Skip to content

Commit

Permalink
Add cose signature subsystem (#6707)
Browse files Browse the repository at this point in the history
  • Loading branch information
achamayou authored Dec 17, 2024
1 parent 5bd5e23 commit f54c0f8
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added

- Expose `ccf:http::parse_accept_header()` and `ccf::http::AcceptHeaderField` (#6706).
- Added `ccf::cose::AbstractCOSESignaturesConfig` subsystem to expose COSE signature configuration to application handlers (#6707).

## [6.0.0-dev9]

Expand Down
26 changes: 25 additions & 1 deletion doc/schemas/app_openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@
"info": {
"description": "This CCF sample app implements a simple logging application, securely recording messages at client-specified IDs. It demonstrates most of the features available to CCF apps.",
"title": "CCF Sample Logging App",
"version": "2.7.0"
"version": "2.8.0"
},
"openapi": "3.0.0",
"paths": {
Expand Down Expand Up @@ -328,6 +328,30 @@
}
}
},
"/app/cose_signatures_config": {
"get": {
"operationId": "GetAppCoseSignaturesConfig",
"responses": {
"204": {
"description": "Default response description"
},
"default": {
"$ref": "#/components/responses/default"
}
},
"security": [
{
"jwt": []
},
{
"user_cose_sign1": []
}
],
"x-ccf-forwarding": {
"$ref": "#/components/x-ccf-forwarding/never"
}
}
},
"/app/custom_auth": {
"get": {
"operationId": "GetAppCustomAuth",
Expand Down
28 changes: 28 additions & 0 deletions include/ccf/cose_signatures_config_interface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the Apache 2.0 License.
#pragma once

#include "ccf/node/cose_signatures_config.h"
#include "ccf/node_subsystem_interface.h"

#include <chrono>
#include <memory>

namespace ccf::cose
{
/** Exposes the COSE signatures configuration to the application.
*/
class AbstractCOSESignaturesConfig : public ccf::AbstractNodeSubSystem
{
public:
virtual ~AbstractCOSESignaturesConfig() = default;

static char const* get_subsystem_name()
{
return "COSESignaturesConfig";
}

virtual const ccf::COSESignaturesConfig& get_cose_signatures_config()
const = 0;
};
}
30 changes: 29 additions & 1 deletion samples/apps/logging/logging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// CCF
#include "ccf/app_interface.h"
#include "ccf/common_auth_policies.h"
#include "ccf/cose_signatures_config_interface.h"
#include "ccf/crypto/cose.h"
#include "ccf/crypto/verifier.h"
#include "ccf/ds/hash.h"
Expand Down Expand Up @@ -470,7 +471,7 @@ namespace loggingapp
"recording messages at client-specified IDs. It demonstrates most of "
"the features available to CCF apps.";

openapi_info.document_version = "2.7.0";
openapi_info.document_version = "2.8.0";

index_per_public_key = std::make_shared<RecordsIndexingStrategy>(
PUBLIC_RECORDS, context, 10000, 20);
Expand Down Expand Up @@ -2100,6 +2101,33 @@ namespace loggingapp
.set_auto_schema<void, void>()
.set_forwarding_required(ccf::endpoints::ForwardingRequired::Never)
.install();

auto get_cose_signatures_config =
[&](ccf::endpoints::ReadOnlyEndpointContext& ctx) {
auto subsystem =
context.get_subsystem<ccf::cose::AbstractCOSESignaturesConfig>();
if (!subsystem)
{
ctx.rpc_ctx->set_error(
HTTP_STATUS_INTERNAL_SERVER_ERROR,
ccf::errors::InternalError,
"COSE signatures subsystem not available");
return;
}
auto config = subsystem->get_cose_signatures_config();

ctx.rpc_ctx->set_response_status(HTTP_STATUS_OK);
ctx.rpc_ctx->set_response_body(nlohmann::json(config).dump());
};

make_read_only_endpoint(
"/cose_signatures_config",
HTTP_GET,
get_cose_signatures_config,
auth_policies)
.set_auto_schema<void, void>()
.set_forwarding_required(ccf::endpoints::ForwardingRequired::Never)
.install();
}
};
}
Expand Down
4 changes: 4 additions & 0 deletions src/enclave/enclave.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "node/node_state.h"
#include "node/node_types.h"
#include "node/rpc/acme_subsystem.h"
#include "node/rpc/cosesigconfig_subsystem.h"
#include "node/rpc/custom_protocol_subsystem.h"
#include "node/rpc/forwarder.h"
#include "node/rpc/gov_effects.h"
Expand Down Expand Up @@ -172,6 +173,9 @@ namespace ccf
std::make_shared<ccf::js::InterpreterCache>(max_interpreter_cache_size);
context->install_subsystem(interpreter_cache);

context->install_subsystem(
std::make_shared<ccf::AbstractCOSESignaturesConfigSubsystem>(*node));

LOG_TRACE_FMT("Creating RPC actors / ffi");
rpc_map->register_frontend<ccf::ActorsType::members>(
std::make_unique<ccf::MemberRpcFrontend>(network, *context));
Expand Down
25 changes: 25 additions & 0 deletions src/node/rpc/cosesigconfig_subsystem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the Apache 2.0 License.
#pragma once

#include "ccf/cose_signatures_config_interface.h"

namespace ccf
{
class AbstractCOSESignaturesConfigSubsystem
: public cose::AbstractCOSESignaturesConfig
{
protected:
AbstractNodeState& node_state;

public:
AbstractCOSESignaturesConfigSubsystem(AbstractNodeState& node_state_) :
node_state(node_state_)
{}

virtual const ccf::COSESignaturesConfig& get_cose_signatures_config() const
{
return node_state.get_cose_signatures_config();
}
};
}
18 changes: 18 additions & 0 deletions tests/e2e_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -2251,6 +2251,23 @@ def run_app_space_js(args):
run_main_tests(network, args)


def test_cose_config(network, args):

configs = set()

for node in network.get_joined_nodes():
with node.client("user0") as c:
r = c.get("/cose_signatures_config")
assert r.status_code == http.HTTPStatus.OK.value, r.status_code
configs.add(r.body.text())

assert len(configs) == 1, configs
assert (
configs.pop() == '{"issuer":"service.example.com","subject":"ledger.signature"}'
), configs
return network


def run_main_tests(network, args):
test_basic_constraints(network, args)
test(network, args)
Expand Down Expand Up @@ -2295,6 +2312,7 @@ def run_main_tests(network, args):
test_genesis_receipt(network, args)
if args.package == "samples/apps/logging/liblogging":
test_etags(network, args)
test_cose_config(network, args)


def run_parsing_errors(args):
Expand Down

0 comments on commit f54c0f8

Please sign in to comment.