Skip to content

Commit

Permalink
allow unsafe rpc (#1573)
Browse files Browse the repository at this point in the history
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
  • Loading branch information
turuslan authored May 2, 2023
1 parent d4c3ac9 commit 1f75bc0
Show file tree
Hide file tree
Showing 24 changed files with 234 additions and 83 deletions.
30 changes: 30 additions & 0 deletions core/api/allow_unsafe.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef KAGOME_API_ALLOW_UNSAFE_HPP
#define KAGOME_API_ALLOW_UNSAFE_HPP

#include <boost/asio/ip/tcp.hpp>

#include "application/app_configuration.hpp"

namespace kagome::api {
struct AllowUnsafe {
using Config = application::AppConfiguration::AllowUnsafeRpc;
AllowUnsafe(const application::AppConfiguration &config)
: config{config.allowUnsafeRpc()} {}

bool allow(const boost::asio::ip::tcp::endpoint &endpoint) const {
if (config == Config::kAuto) {
return endpoint.address().is_loopback();
}
return config == Config::kUnsafe;
}

Config config;
};
} // namespace kagome::api

#endif // KAGOME_API_ALLOW_UNSAFE_HPP
16 changes: 15 additions & 1 deletion core/api/jrpc/jrpc_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,20 @@ namespace kagome::api {
* @brief registers rpc request handler lambda
* @param name rpc method name
* @param method handler functor
* @param unsafe method is unsafe
*/
virtual void registerHandler(const std::string &name, Method method) = 0;
virtual void registerHandler(const std::string &name,
Method method,
bool unsafe = false) = 0;

/**
* @brief registers unsafe rpc request handler lambda
* @param name rpc method name
* @param method handler functor
*/
void registerHandlerUnsafe(const std::string &name, Method method) {
registerHandler(name, std::move(method), true);
}

/**
* @return name of handlers
Expand All @@ -58,9 +70,11 @@ namespace kagome::api {
/**
* @brief handles decoded network message
* @param request json request string
* @param allow_unsafe allow unsafe methods
* @param cb callback
*/
virtual void processData(std::string_view request,
bool allow_unsafe,
const ResponseHandler &cb) = 0;
};

Expand Down
13 changes: 11 additions & 2 deletions core/api/jrpc/jrpc_server_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ namespace kagome::api {
JRpcServerImpl::JRpcServerImpl() {
// register json format handler
jsonrpc_handler_.RegisterFormatHandler(format_handler_);
jsonrpc_handler_safe_.RegisterFormatHandler(format_handler_);

// Register metrics
metrics_registry_->registerCounterFamily(rpcRequestsCountMetricName,
Expand All @@ -35,8 +36,14 @@ namespace kagome::api {
metrics_registry_->registerCounterMetric(rpcRequestsCountMetricName);
}

void JRpcServerImpl::registerHandler(const std::string &name, Method method) {
void JRpcServerImpl::registerHandler(const std::string &name,
Method method,
bool unsafe) {
auto &dispatcher = jsonrpc_handler_.GetDispatcher();
auto &dispatcher_safe = jsonrpc_handler_safe_.GetDispatcher();
if (not unsafe) {
dispatcher_safe.AddMethod(name, method);
}
dispatcher.AddMethod(name, std::move(method));
}

Expand Down Expand Up @@ -79,8 +86,10 @@ namespace kagome::api {
}

void JRpcServerImpl::processData(std::string_view request,
bool allow_unsafe,
const ResponseHandler &cb) {
JrpcHandleBatch response(jsonrpc_handler_, request);
JrpcHandleBatch response(
allow_unsafe ? jsonrpc_handler_ : jsonrpc_handler_safe_, request);
cb(response.response());
}

Expand Down
19 changes: 6 additions & 13 deletions core/api/jrpc/jrpc_server_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,17 @@ namespace kagome::api {

JRpcServerImpl();

~JRpcServerImpl() override = default;

/**
* @brief registers rpc request handler lambda
* @param name rpc method name
* @param method handler functor
*/
void registerHandler(const std::string &name, Method method) override;
void registerHandler(const std::string &name,
Method method,
bool unsafe) override;

/**
* @return name of handlers
*/
std::vector<std::string> getHandlerNames() override;

/**
* @brief handles decoded network message
* @param request json request string
* @param cb callback
*/
void processData(std::string_view request,
bool allow_unsafe,
const ResponseHandler &cb) override;

/**
Expand All @@ -55,6 +46,8 @@ namespace kagome::api {
private:
/// json rpc server instance
jsonrpc::Server jsonrpc_handler_{};
/// json rpc server instance for subset of safe methods
jsonrpc::Server jsonrpc_handler_safe_{};
/// format handler instance
jsonrpc::JsonFormatHandler format_handler_{};

Expand Down
15 changes: 8 additions & 7 deletions core/api/service/author/author_jrpc_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,17 @@ namespace kagome::api::author {
server_->registerHandler("author_submitExtrinsic",
Handler<request::SubmitExtrinsic>(api_));

server_->registerHandler("author_insertKey",
Handler<request::InsertKey>(api_));
server_->registerHandlerUnsafe("author_insertKey",
Handler<request::InsertKey>(api_));

server_->registerHandler("author_hasSessionKeys",
Handler<request::HasSessionKeys>(api_));
server_->registerHandlerUnsafe("author_hasSessionKeys",
Handler<request::HasSessionKeys>(api_));

server_->registerHandler("author_hasKey", Handler<request::HasKey>(api_));
server_->registerHandlerUnsafe("author_hasKey",
Handler<request::HasKey>(api_));

server_->registerHandler("author_rotateKeys",
Handler<request::RotateKeys>(api_));
server_->registerHandlerUnsafe("author_rotateKeys",
Handler<request::RotateKeys>(api_));

server_->registerHandler("author_submitAndWatchExtrinsic",
Handler<request::SubmitAndWatchExtrinsic>(api_));
Expand Down
10 changes: 6 additions & 4 deletions core/api/service/impl/api_service_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,10 +510,12 @@ namespace kagome::api {
boost::replace_first(str_request, "\"params\":null", "\"params\":[null]");

// process new request
server_->processData(str_request, [&](std::string_view response) mutable {
// process response
session->respond(response);
});
server_->processData(str_request,
session->isUnsafeAllowed(),
[&](std::string_view response) mutable {
// process response
session->respond(response);
});

try {
withSession(session->id(), [&](SessionSubscriptions &session_context) {
Expand Down
4 changes: 2 additions & 2 deletions core/api/service/internal/internal_jrpc_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ namespace kagome::api::internal {
using Handler = Method<Request, InternalApi>;

void InternalJrpcProcessor::registerHandlers() {
server_->registerHandler("internal_setLogLevel",
Handler<request::SetLogLevel>(api_));
server_->registerHandlerUnsafe("internal_setLogLevel",
Handler<request::SetLogLevel>(api_));
}

} // namespace kagome::api::internal
4 changes: 2 additions & 2 deletions core/api/service/state/state_jrpc_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ namespace kagome::api::state {
server_->registerHandler("state_getStorageAt",
Handler<request::GetStorage>(api_));

server_->registerHandler("state_queryStorage",
Handler<request::QueryStorage>(api_));
server_->registerHandlerUnsafe("state_queryStorage",
Handler<request::QueryStorage>(api_));
server_->registerHandler("state_queryStorageAt",
Handler<request::QueryStorageAt>(api_));

Expand Down
3 changes: 2 additions & 1 deletion core/api/service/system/system_jrpc_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ namespace kagome::api::system {
"account_nextIndex",
Handler<request::AccountNextIndex>(api_)); // an alias

server_->registerHandler("system_peers", Handler<request::Peers>(api_));
server_->registerHandlerUnsafe("system_peers",
Handler<request::Peers>(api_));
}

} // namespace kagome::api::system
4 changes: 3 additions & 1 deletion core/api/transport/impl/http/http_listener_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace kagome::api {
const application::AppConfiguration &app_config,
SessionImpl::Configuration session_config)
: context_{std::move(context)},
allow_unsafe_{app_config},
endpoint_(app_config.rpcHttpEndpoint()),
session_config_{session_config},
logger_{log::createLogger("RpcHttpListener", "rpc_transport")} {
Expand Down Expand Up @@ -77,7 +78,8 @@ namespace kagome::api {
}

void HttpListenerImpl::acceptOnce() {
new_session_ = std::make_shared<SessionImpl>(*context_, session_config_);
new_session_ = std::make_shared<SessionImpl>(
*context_, allow_unsafe_, session_config_);

auto on_accept = [wp = weak_from_this()](boost::system::error_code ec) {
if (auto self = wp.lock()) {
Expand Down
1 change: 1 addition & 0 deletions core/api/transport/impl/http/http_listener_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ namespace kagome::api {
void acceptOnce() override;

std::shared_ptr<Context> context_;
AllowUnsafe allow_unsafe_;
const Endpoint endpoint_;
const SessionImpl::Configuration session_config_;

Expand Down
9 changes: 8 additions & 1 deletion core/api/transport/impl/http/http_session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@

namespace kagome::api {

HttpSession::HttpSession(Context &context, Configuration config)
HttpSession::HttpSession(Context &context,
AllowUnsafe allow_unsafe,
Configuration config)
: strand_(boost::asio::make_strand(context)),
allow_unsafe_{allow_unsafe},
config_{config},
stream_(boost::asio::ip::tcp::socket(strand_)) {}

Expand Down Expand Up @@ -133,4 +136,8 @@ namespace kagome::api {
void HttpSession::post(std::function<void()> cb) {
boost::asio::post(strand_, std::move(cb));
}

bool HttpSession::isUnsafeAllowed() const {
return allow_unsafe_.allow(stream_.socket().remote_endpoint());
}
} // namespace kagome::api
8 changes: 7 additions & 1 deletion core/api/transport/impl/http/http_session.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <cstdlib>
#include <memory>

#include "api/allow_unsafe.hpp"
#include "api/transport/session.hpp"
#include "log/logger.hpp"

Expand Down Expand Up @@ -52,7 +53,9 @@ namespace kagome::api {
* @param socket socket instance
* @param config session configuration
*/
HttpSession(Context &context, Configuration config);
HttpSession(Context &context,
AllowUnsafe allow_unsafe,
Configuration config);

Socket &socket() override {
return stream_.socket();
Expand Down Expand Up @@ -87,6 +90,8 @@ namespace kagome::api {

void post(std::function<void()> cb) override;

bool isUnsafeAllowed() const override;

private:
/**
* @brief stops session
Expand Down Expand Up @@ -148,6 +153,7 @@ namespace kagome::api {
/// Strand to ensure the connection's handlers are not called concurrently.
boost::asio::strand<boost::asio::io_context::executor_type> strand_;

AllowUnsafe allow_unsafe_;
Configuration config_; ///< session configuration
boost::beast::tcp_stream stream_; ///< stream
boost::beast::flat_buffer buffer_; ///< read buffer
Expand Down
12 changes: 8 additions & 4 deletions core/api/transport/impl/ws/ws_listener_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace kagome::api {
const application::AppConfiguration &app_config,
SessionImpl::Configuration session_config)
: context_{std::move(context)},
allow_unsafe_{app_config},
endpoint_(app_config.rpcWsEndpoint()),
session_config_{session_config},
max_ws_connections_{app_config.maxWsConnections()},
Expand All @@ -43,8 +44,8 @@ namespace kagome::api {

bool WsListenerImpl::prepare() {
try {
acceptor_ = acceptOnFreePort(
context_, endpoint_, kDefaultPortTolerance, log_);
acceptor_ =
acceptOnFreePort(context_, endpoint_, kDefaultPortTolerance, log_);
} catch (const boost::wrapexcept<boost::system::system_error> &exception) {
SL_CRITICAL(log_, "Failed to prepare a listener: {}", exception.what());
return false;
Expand Down Expand Up @@ -92,8 +93,11 @@ namespace kagome::api {
}

void WsListenerImpl::acceptOnce() {
new_session_ = std::make_shared<SessionImpl>(
*context_, session_config_, next_session_id_.fetch_add(1ull));
new_session_ =
std::make_shared<SessionImpl>(*context_,
allow_unsafe_,
session_config_,
next_session_id_.fetch_add(1ull));
auto session_stopped_handler = [wp = weak_from_this()] {
if (auto self = wp.lock()) {
self->closed_session_->inc();
Expand Down
1 change: 1 addition & 0 deletions core/api/transport/impl/ws/ws_listener_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ namespace kagome::api {
void acceptOnce() override;

std::shared_ptr<Context> context_;
AllowUnsafe allow_unsafe_;
const Endpoint endpoint_;
const SessionImpl::Configuration session_config_;
const uint32_t max_ws_connections_;
Expand Down
10 changes: 9 additions & 1 deletion core/api/transport/impl/ws/ws_session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@

namespace kagome::api {

WsSession::WsSession(Context &context, Configuration config, SessionId id)
WsSession::WsSession(Context &context,
AllowUnsafe allow_unsafe,
Configuration config,
SessionId id)
: strand_(boost::asio::make_strand(context)),
socket_(strand_),
allow_unsafe_{allow_unsafe},
config_{config},
stream_(socket_),
id_(id) {}
Expand Down Expand Up @@ -165,4 +169,8 @@ namespace kagome::api {
void WsSession::post(std::function<void()> cb) {
boost::asio::post(strand_, std::move(cb));
}

bool WsSession::isUnsafeAllowed() const {
return allow_unsafe_.allow(socket_.remote_endpoint());
}
} // namespace kagome::api
Loading

0 comments on commit 1f75bc0

Please sign in to comment.