Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow unsafe rpc #1573

Merged
merged 9 commits into from
May 2, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions core/api/allow_unsafe.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* 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 {
AllowUnsafe(const application::AppConfiguration &config)
: config{config.allowUnsafeRpc()} {}

bool allow(const boost::asio::ip::tcp::endpoint &endpoint) const {
return config ? *config : endpoint.address().is_loopback();
}

std::optional<bool> config;
turuslan marked this conversation as resolved.
Show resolved Hide resolved
};
} // namespace kagome::api

#endif // KAGOME_API_ALLOW_UNSAFE_HPP
5 changes: 4 additions & 1 deletion core/api/jrpc/jrpc_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ namespace kagome::api {
* @param name rpc method name
* @param method handler functor
*/
virtual void registerHandler(const std::string &name, Method method) = 0;
virtual void registerHandler(const std::string &name,
Method method,
bool unsafe = false) = 0;
turuslan marked this conversation as resolved.
Show resolved Hide resolved

/**
* @return name of handlers
Expand Down Expand Up @@ -61,6 +63,7 @@ namespace kagome::api {
* @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
7 changes: 6 additions & 1 deletion core/api/jrpc/jrpc_server_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ namespace kagome::api {
* @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
Expand All @@ -41,6 +43,7 @@ namespace kagome::api {
* @param cb callback
*/
void processData(std::string_view request,
bool allow_unsafe,
const ResponseHandler &cb) override;

/**
Expand All @@ -55,6 +58,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_->registerHandler(
"author_insertKey", Handler<request::InsertKey>(api_), true);

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

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

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

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->allowUnsafe(),
[&](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_->registerHandler(
"internal_setLogLevel", Handler<request::SetLogLevel>(api_), true);
}

} // 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_->registerHandler(
"state_queryStorage", Handler<request::QueryStorage>(api_), true);
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_->registerHandler(
"system_peers", Handler<request::Peers>(api_), true);
}

} // 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::allowUnsafe() const {
turuslan marked this conversation as resolved.
Show resolved Hide resolved
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 allowUnsafe() 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::allowUnsafe() const {
return allow_unsafe_.allow(socket_.remote_endpoint());
}
} // namespace kagome::api
11 changes: 9 additions & 2 deletions core/api/transport/impl/ws/ws_session.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <boost/beast/core/tcp_stream.hpp>
#include <boost/beast/websocket.hpp>

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

Expand Down Expand Up @@ -43,7 +44,10 @@ namespace kagome::api {
* @param config session configuration
* @param id session id
*/
WsSession(Context &context, Configuration config, SessionId id);
WsSession(Context &context,
AllowUnsafe allow_unsafe,
Configuration config,
SessionId id);

Socket &socket() override {
return socket_;
Expand Down Expand Up @@ -76,6 +80,8 @@ namespace kagome::api {

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

bool allowUnsafe() const override;

/**
* @brief Closes the incoming connection with "try again later" response
*/
Expand Down Expand Up @@ -150,6 +156,7 @@ namespace kagome::api {
/// Socket for the connection.
boost::asio::ip::tcp::socket socket_;

AllowUnsafe allow_unsafe_;
Configuration config_; ///< session configuration
boost::beast::websocket::stream<boost::asio::ip::tcp::socket &> stream_;
boost::beast::flat_buffer rbuffer_; ///< read buffer
Expand All @@ -159,7 +166,7 @@ namespace kagome::api {
bool writing_in_progress_ = false;
std::atomic_bool stopped_ = false;

SessionId const id_;
const SessionId id_;
OnWsSessionCloseHandler on_ws_close_;
log::Logger logger_ = log::createLogger("WsSession", "rpc_transport");
};
Expand Down
Loading