Skip to content

Commit

Permalink
prelim setup
Browse files Browse the repository at this point in the history
  • Loading branch information
flodesi committed Aug 10, 2020
1 parent f799d51 commit 68b6c33
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 1 deletion.
39 changes: 39 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions forest/src/cli/auth_cmd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2020 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

// Copyright 2020 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

use super::stringify_rpc_err;
use rpc_client::{auth_new, new_client};
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
pub enum AuthCommands {
/// Create a new Authentication token with given permission
#[structopt(about = "<String> Create Authentication token with given permission")]
CreateToken {
#[structopt(
short,
help = "permission to assign to the token, one of: read, write, sign, admin"
)]
perm: String,
},
}

impl AuthCommands {
pub async fn run(&self) {
// TODO handle cli config
match self {
Self::CreateToken { perm } => {
let perm: String = perm.parse().unwrap();
let mut client = new_client();

let obj = auth_new(&mut client, perm)
.await
.map_err(stringify_rpc_err)
.unwrap();
println!("{}", serde_json::to_string_pretty(&obj).unwrap());
}
}
}
}
5 changes: 5 additions & 0 deletions forest/src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// Copyright 2020 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

mod auth_cmd;
mod chain_cmd;
mod config;
mod fetch_params_cmd;
mod genesis;

pub(super) use self::auth_cmd::AuthCommands;
pub(super) use self::chain_cmd::ChainCommands;
pub use self::config::Config;
pub(super) use self::fetch_params_cmd::FetchCommands;
Expand Down Expand Up @@ -47,6 +49,9 @@ pub enum Subcommand {

#[structopt(name = "chain", about = "Interact with Filecoin blockchain")]
Chain(ChainCommands),

#[structopt(name = "auth", about = "Manage RPC Permissions")]
Auth(AuthCommands),
}

/// Daemon process command line options.
Expand Down
3 changes: 3 additions & 0 deletions forest/src/subcommand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@ pub(super) async fn process(command: Subcommand) {
Subcommand::Chain(cmd) => {
cmd.run().await;
}
Subcommand::Auth(cmd) => {
cmd.run().await;
}
}
}
3 changes: 2 additions & 1 deletion node/rpc-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ serde_json = "1.0"
jsonrpc-v2 = { version = "0.5.2", features = ["easy-errors", "macros"] }
log = "0.4.8"
crypto = { package = "forest_crypto", path = "../../crypto", features = ["json"] }
wallet = {package = "key_management", path = "../../key_management", features = ["json"] }
wallet = {package = "key_management", path = "../../key_management", features = ["json"] }
lazy_static = "1.4.0"
35 changes: 35 additions & 0 deletions node/rpc-client/src/auth_ops.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2020 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

// Copyright 2020 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

use super::client::Filecoin;
use jsonrpc_v2::Error as JsonRpcError;
use jsonrpsee::raw::RawClient;
use jsonrpsee::transport::http::HttpTransportClient as HTC;

lazy_static! {
pub static ref ADMIN: Vec<String> = vec![
"read".to_string(),
"write".to_string(),
"sign".to_string(),
"admin".to_string()
];
pub static ref SIGN: Vec<String> =
vec!["read".to_string(), "write".to_string(), "sign".to_string()];
pub static ref WRITE: Vec<String> = vec!["read".to_string(), "write".to_string()];
pub static ref READ: Vec<String> = vec!["read".to_string()];
}

/// Returns a block with specified CID fom chain via RPC
pub async fn auth_new(client: &mut RawClient<HTC>, perm: String) -> Result<String, JsonRpcError> {
let ret: String = match perm.as_str() {
"admin" => Filecoin::auth_new(client, ADMIN.clone()).await?,
"sign" => Filecoin::auth_new(client, SIGN.clone()).await?,
"write" => Filecoin::auth_new(client, WRITE.clone()).await?,
"read" => Filecoin::auth_new(client, READ.clone()).await?,
_ => return Err(JsonRpcError::INVALID_PARAMS),
};
Ok(ret)
}
3 changes: 3 additions & 0 deletions node/rpc-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ use message::unsigned_message::json::UnsignedMessageJson;

jsonrpsee::rpc_api! {
pub Filecoin {
/// Auth
#[rpc(method = "Filecoin.AuthNew", positional_params)]
fn auth_new(perm: Vec<String>) -> String;
/// Chain
#[rpc(method = "Filecoin.ChainGetBlock", positional_params)]
fn chain_get_block(cid: CidJson) -> BlockHeaderJson;
Expand Down
5 changes: 5 additions & 0 deletions node/rpc-client/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
// Copyright 2020 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

#[macro_use]
extern crate lazy_static;

mod auth_ops;
mod chain_ops;
mod client;

pub use self::auth_ops::*;
pub use self::chain_ops::*;
pub use self::client::*;
2 changes: 2 additions & 0 deletions node/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ num-bigint = { path = "../../utils/bigint", package = "forest_bigint" }
thiserror = "1.0"
state_tree = { path = "../../vm/state_tree" }
forest_libp2p = { path = "../forest_libp2p" }
jsonwebtoken = "7.2.0"
lazy_static = "1.4.0"

[dev-dependencies]
db = { path = "../db" }
Expand Down
69 changes: 69 additions & 0 deletions node/rpc/src/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright 2020 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

use jsonrpc_v2::{Error as JsonRpcError, Params};
use jsonwebtoken::errors::Result as JWTResult;
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
use serde::{Deserialize, Serialize};

lazy_static! {
pub static ref ADMIN: Vec<String> = vec![
"read".to_string(),
"write".to_string(),
"sign".to_string(),
"admin".to_string()
];
pub static ref SIGN: Vec<String> =
vec!["read".to_string(), "write".to_string(), "sign".to_string()];
pub static ref WRITE: Vec<String> = vec!["read".to_string(), "write".to_string()];
pub static ref READ: Vec<String> = vec!["read".to_string()];
}

#[derive(Debug, Serialize, Deserialize)]
struct Claims {
// each string is a permission
#[serde(rename = "Allow")]
allow: Vec<String>,
exp: usize,
}

/// Create a new JWT Token
pub fn create_token(perms: Vec<String>) -> JWTResult<String> {
let payload = Claims {
allow: perms,
exp: 10000000000,
};
encode(
&Header::default(),
&payload,
&EncodingKey::from_secret("secret".as_ref()),
)
}

/// Verify JWT Token and return the allowed permissions from token
pub fn verify_token(token: String) -> JWTResult<Vec<String>> {
let token = decode::<Claims>(
&token,
&DecodingKey::from_secret("secret".as_ref()),
&Validation::default(),
)?;
Ok(token.claims.allow)
}

/// RPC call to create a new JWT Token
pub(crate) async fn auth_new(
Params(params): Params<(Vec<String>,)>,
) -> Result<String, JsonRpcError> {
let (perms,) = params;
let token = create_token(perms)?;
Ok(token)
}

/// RPC call to verify JWT Token and return the token's permissions
pub(crate) async fn auth_verify(
Params(params): Params<(String,)>,
) -> Result<Vec<String>, JsonRpcError> {
let (token,) = params;
let perms = verify_token(token)?;
Ok(perms)
}
13 changes: 13 additions & 0 deletions node/rpc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// Copyright 2020 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

#[macro_use]
extern crate lazy_static;

mod auth;
mod chain_api;
mod mpool_api;
mod sync_api;
Expand Down Expand Up @@ -32,6 +36,10 @@ where
}

async fn handle_json_rpc(mut req: Request<Server<MapRouter>>) -> tide::Result {
if let Some(header) = req.header("Authorization") {
println!("{:?}", header);
}
println!("{:?}", req.method());
let call: RequestObject = req.body_json().await?;
let res = req.state().handle(call).await;
Ok(Response::new(StatusCode::Ok).body_json(&res)?)
Expand All @@ -42,13 +50,18 @@ where
DB: BlockStore + Send + Sync + 'static,
KS: KeyStore + Send + Sync + 'static,
{
use auth::*;
use chain_api::*;
use mpool_api::*;
use sync_api::*;
use wallet_api::*;

let rpc = Server::new()
.with_data(Data::new(state))
// Auth API
.with_method("Filecoin.AuthNew", auth_new)
.with_method("Filecoin.AuthVerify", auth_verify)
// Chain API
.with_method(
"Filecoin.ChainGetMessage",
chain_api::chain_get_message::<DB, KS>,
Expand Down

0 comments on commit 68b6c33

Please sign in to comment.