Allow to expose a subset of unsafe RPCs (#5233)

* sc-cli: Use type-safe constructors for RPC/Prometheus interfaces

* service: Simplify rpc handler creation

Could probably be further simplifies once [this][commit] lands.

[commit]: https://github.com/paritytech/jsonrpc/commit/20485387ed06a48f1a70bf4d609a7cde6cf0accf

* service: Streamline some HTTP & WS server start logic

* client: Introduce a simple RPC policy mechanism

* rpc/system: Check unsafe RPCs

* rpc/offchain: Check unsafe RPCs

* rpc/author: Check unsafe RPCs
This commit is contained in:
Igor Matuszewski
2020-04-20 11:03:58 +02:00
committed by GitHub
parent d05dc090a8
commit 4b1f7d187f
20 changed files with 281 additions and 95 deletions
@@ -57,6 +57,8 @@ pub enum Error {
/// Invalid session keys encoding.
#[display(fmt="Session keys are not encoded correctly")]
InvalidSessionKeys,
/// Call to an unsafe RPC was denied.
UnsafeRpcCalled(crate::policy::UnsafeRpcError),
}
impl std::error::Error for Error {
@@ -65,6 +67,7 @@ impl std::error::Error for Error {
Error::Client(ref err) => Some(&**err),
Error::Pool(ref err) => Some(err),
Error::Verification(ref err) => Some(&**err),
Error::UnsafeRpcCalled(ref err) => Some(err),
_ => None,
}
}
@@ -152,6 +155,7 @@ impl From<Error> for rpc::Error {
request to insert the key successfully.".into()
),
},
Error::UnsafeRpcCalled(e) => e.into(),
e => errors::internal(e),
}
}
+2
View File
@@ -22,11 +22,13 @@
mod errors;
mod helpers;
mod policy;
mod subscriptions;
pub use jsonrpc_core::IoHandlerExtension as RpcExtension;
pub use subscriptions::{Subscriptions, TaskExecutor};
pub use helpers::Receiver;
pub use policy::DenyUnsafe;
pub mod author;
pub mod chain;
@@ -27,11 +27,16 @@ pub enum Error {
/// Unavailable storage kind error.
#[display(fmt="This storage kind is not available yet.")]
UnavailableStorageKind,
/// Call to an unsafe RPC was denied.
UnsafeRpcCalled(crate::policy::UnsafeRpcError),
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
match self {
Self::UnsafeRpcCalled(err) => Some(err),
_ => None,
}
}
}
@@ -46,6 +51,7 @@ impl From<Error> for rpc::Error {
message: "This storage kind is not available yet" .into(),
data: None,
},
Error::UnsafeRpcCalled(e) => e.into(),
}
}
}
+60
View File
@@ -0,0 +1,60 @@
// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Policy-related types.
//!
//! Contains a `DenyUnsafe` type that can be used to deny potentially unsafe
//! RPC when accessed externally.
use jsonrpc_core as rpc;
/// Signifies whether a potentially unsafe RPC should be denied.
#[derive(Clone, Copy, Debug)]
pub enum DenyUnsafe {
/// Denies only potentially unsafe RPCs.
Yes,
/// Allows calling every RPCs.
No
}
impl DenyUnsafe {
/// Returns `Ok(())` if the RPCs considered unsafe are safe to call,
/// otherwise returns `Err(UnsafeRpcError)`.
pub fn check_if_safe(self) -> Result<(), UnsafeRpcError> {
match self {
DenyUnsafe::Yes => Err(UnsafeRpcError),
DenyUnsafe::No => Ok(())
}
}
}
/// Signifies whether an RPC considered unsafe is denied to be called externally.
#[derive(Debug)]
pub struct UnsafeRpcError;
impl std::fmt::Display for UnsafeRpcError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "RPC call is unsafe to be called externally")
}
}
impl std::error::Error for UnsafeRpcError {}
impl From<UnsafeRpcError> for rpc::Error {
fn from(_: UnsafeRpcError) -> rpc::Error {
rpc::Error::method_not_found()
}
}
+4 -2
View File
@@ -72,14 +72,16 @@ pub trait SystemApi<Hash, Number> {
/// Returns currently connected peers
#[rpc(name = "system_peers", returns = "Vec<PeerInfo<Hash, Number>>")]
fn system_peers(&self) -> Receiver<Vec<PeerInfo<Hash, Number>>>;
fn system_peers(&self)
-> Compat<BoxFuture<'static, jsonrpc_core::Result<Vec<PeerInfo<Hash, Number>>>>>;
/// Returns current state of the network.
///
/// **Warning**: This API is not stable.
// TODO: make this stable and move structs https://github.com/paritytech/substrate/issues/1890
#[rpc(name = "system_networkState", returns = "jsonrpc_core::Value")]
fn system_network_state(&self) -> Receiver<jsonrpc_core::Value>;
fn system_network_state(&self)
-> Compat<BoxFuture<'static, jsonrpc_core::Result<jsonrpc_core::Value>>>;
/// Adds a reserved peer. Returns the empty string or an error. The string
/// parameter should encode a `p2p` multiaddr.