Skip to content
This repository has been archived by the owner on Jan 26, 2023. It is now read-only.

Commit

Permalink
Impl allow-addr in (many-)ledger and kvstore (#259)
Browse files Browse the repository at this point in the history
  • Loading branch information
fmorency authored Oct 12, 2022
1 parent 2d7addf commit 367cb3f
Show file tree
Hide file tree
Showing 17 changed files with 289 additions and 67 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ jobs:
- bats/install
- run:
name: running BATs tests
command: bats .
command: bats *
working_directory: ./tests/e2e/
coverage:
parameters:
Expand Down
21 changes: 20 additions & 1 deletion src/many-kvstore/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use crate::module::account::AccountFeatureModule;
use clap::Parser;
use many_identity::verifiers::AnonymousVerifier;
use many_identity::Address;
use many_identity_dsa::{CoseKeyIdentity, CoseKeyVerifier};
use many_modules::account::features::Feature;
use many_modules::{abci_backend, account, events, kvstore};
use many_server::transport::http::HttpServer;
use many_server::ManyServer;
use std::collections::BTreeSet;
use std::net::SocketAddr;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
Expand Down Expand Up @@ -62,6 +64,12 @@ struct Opts {
/// Use given logging strategy
#[clap(long, arg_enum, default_value_t = LogStrategy::Terminal)]
logmode: LogStrategy,

/// Path to a JSON file containing an array of MANY addresses
/// Only addresses from this array will be able to execute commands, e.g., send, put, ...
/// Any addresses will be able to execute queries, e.g., balance, get, ...
#[clap(long)]
allow_addrs: Option<PathBuf>,
}

fn main() {
Expand All @@ -75,6 +83,7 @@ fn main() {
persistent,
clean,
logmode,
allow_addrs,
} = Opts::parse();

let verbose_level = 2 + verbose - quiet;
Expand Down Expand Up @@ -143,7 +152,17 @@ fn main() {
{
let mut s = many.lock().unwrap();
s.add_module(kvstore::KvStoreModule::new(module.clone()));
s.add_module(kvstore::KvStoreCommandsModule::new(module.clone()));
let kvstore_command_module = kvstore::KvStoreCommandsModule::new(module.clone());
if let Some(path) = allow_addrs {
let allow_addrs: BTreeSet<Address> =
json5::from_str(&std::fs::read_to_string(&path).unwrap()).unwrap();
s.add_module(allow_addrs::AllowAddrsModule {
inner: kvstore_command_module,
allow_addrs,
});
} else {
s.add_module(kvstore_command_module);
}
s.add_module(events::EventsModule::new(module.clone()));

s.add_module(AccountFeatureModule::new(
Expand Down
1 change: 1 addition & 0 deletions src/many-kvstore/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use std::path::Path;
use tracing::info;

pub mod account;
pub mod allow_addrs;
mod event;

// The initial state schema, loaded from JSON.
Expand Down
37 changes: 37 additions & 0 deletions src/many-kvstore/src/module/allow_addrs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use coset::CoseSign1;
use many_error::ManyError;
use many_identity::Address;
use many_modules::{kvstore, ManyModule, ManyModuleInfo};
use many_protocol::{RequestMessage, ResponseMessage};
use std::collections::BTreeSet;
use std::fmt::{Debug, Formatter};

pub struct AllowAddrsModule<T: kvstore::KvStoreCommandsModuleBackend> {
pub inner: kvstore::KvStoreCommandsModule<T>,
pub allow_addrs: BTreeSet<Address>,
}

impl<T: kvstore::KvStoreCommandsModuleBackend> Debug for AllowAddrsModule<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str("AllowAddrsModule")
}
}

#[async_trait::async_trait]
impl<T: kvstore::KvStoreCommandsModuleBackend> ManyModule for AllowAddrsModule<T> {
fn info(&self) -> &ManyModuleInfo {
self.inner.info()
}

fn validate(&self, message: &RequestMessage, envelope: &CoseSign1) -> Result<(), ManyError> {
self.inner.validate(message, envelope)
}

async fn execute(&self, message: RequestMessage) -> Result<ResponseMessage, ManyError> {
if !self.allow_addrs.contains(&message.from()) {
return Err(ManyError::invalid_from_identity());
}

self.inner.execute(message).await
}
}
20 changes: 19 additions & 1 deletion src/many-ledger/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use many_modules::{abci_backend, account, events, idstore, ledger};
use many_protocol::ManyUrl;
use many_server::transport::http::HttpServer;
use many_server::ManyServer;
use std::collections::BTreeSet;
use std::net::SocketAddr;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
Expand Down Expand Up @@ -93,6 +94,12 @@ struct Opts {
/// Use given logging strategy
#[clap(long, arg_enum, default_value_t = LogStrategy::Terminal)]
logmode: LogStrategy,

/// Path to a JSON file containing an array of MANY addresses
/// Only addresses from this array will be able to execute commands, e.g., send, put, ...
/// Any addresses will be able to execute queries, e.g., balance, get, ...
#[clap(long)]
allow_addrs: Option<PathBuf>,
}

fn main() {
Expand All @@ -106,6 +113,7 @@ fn main() {
persistent,
clean,
logmode,
allow_addrs,
..
} = Opts::parse();

Expand Down Expand Up @@ -203,7 +211,17 @@ fn main() {
{
let mut s = many.lock().unwrap();
s.add_module(ledger::LedgerModule::new(module_impl.clone()));
s.add_module(ledger::LedgerCommandsModule::new(module_impl.clone()));
let ledger_command_module = ledger::LedgerCommandsModule::new(module_impl.clone());
if let Some(path) = allow_addrs {
let allow_addrs: BTreeSet<Address> =
json5::from_str(&std::fs::read_to_string(&path).unwrap()).unwrap();
s.add_module(AllowAddrsModule {
inner: ledger_command_module,
allow_addrs,
});
} else {
s.add_module(ledger_command_module);
}
s.add_module(events::EventsModule::new(module_impl.clone()));

let idstore_module = idstore::IdStoreModule::new(module_impl.clone());
Expand Down
30 changes: 30 additions & 0 deletions src/many-ledger/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,36 @@ impl<T: idstore::IdStoreModuleBackend> ManyModule for IdStoreWebAuthnModule<T> {
}
}

pub struct AllowAddrsModule<T: ledger::LedgerCommandsModuleBackend> {
pub inner: ledger::LedgerCommandsModule<T>,
pub allow_addrs: BTreeSet<Address>,
}

impl<T: ledger::LedgerCommandsModuleBackend> Debug for AllowAddrsModule<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str("AllowAddrsModule")
}
}

#[async_trait::async_trait]
impl<T: ledger::LedgerCommandsModuleBackend> ManyModule for AllowAddrsModule<T> {
fn info(&self) -> &ManyModuleInfo {
self.inner.info()
}

fn validate(&self, message: &RequestMessage, envelope: &CoseSign1) -> Result<(), ManyError> {
self.inner.validate(message, envelope)
}

async fn execute(&self, message: RequestMessage) -> Result<ResponseMessage, ManyError> {
if !self.allow_addrs.contains(&message.from()) {
return Err(ManyError::invalid_from_identity());
}

self.inner.execute(message).await
}
}

#[cfg(test)]
mod tests {
use crate::json::InitialStateJson;
Expand Down
45 changes: 45 additions & 0 deletions tests/e2e/kvstore/allow_addrs.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
GIT_ROOT="$BATS_TEST_DIRNAME/../../../"

load '../../test_helper/load'
load '../../test_helper/kvstore'

function setup() {
mkdir "$BATS_TEST_ROOTDIR"

skip_if_missing_background_utilities

if ! [ $CI ]; then
(
cd "$GIT_ROOT"
cargo build
)
fi

local ALLOW_ADDRS_CONFIG=$(generate_allow_addrs_config 1 2)

start_kvstore --pem "$(pem 0)" \
--allow-addrs "$ALLOW_ADDRS_CONFIG"
}

function teardown() {
stop_background_run
}

@test "$SUITE: allow addrs" {
call_kvstore --pem=1 --port=8000 put "01" "one"
call_kvstore --pem=1 --port=8000 get "01"
assert_output --partial "one"

call_kvstore --pem=2 --port=8000 put "02" "two"
call_kvstore --pem=2 --port=8000 get "02"
assert_output --partial "two"

call_kvstore --pem=3 --port=8000 put "03" "three"
assert_output --partial "The identity of the from field is invalid or unexpected."

call_kvstore --pem=3 --port=8000 get "02"
assert_output --partial "two"

call_kvstore --pem=3 --port=8000 get "03"
assert_output --partial "None"
}
15 changes: 4 additions & 11 deletions tests/e2e/kvstore.bats → tests/e2e/kvstore/kvstore.bats
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
GIT_ROOT="$BATS_TEST_DIRNAME/../../"
GIT_ROOT="$BATS_TEST_DIRNAME/../../../"

load '../test_helper/load'
load '../test_helper/kvstore'
load '../../test_helper/load'
load '../../test_helper/kvstore'

function setup() {
mkdir "$BATS_TEST_ROOTDIR"
Expand All @@ -15,14 +15,7 @@ function setup() {
)
fi

run_in_background "$GIT_ROOT/target/debug/many-kvstore" \
-v \
--clean \
--persistent "$(mktemp -d)" \
--state "$GIT_ROOT/staging/kvstore_state.json5" \
--pem "$(pem 0)"

wait_for_background_output "Running accept thread"
start_kvstore --pem "$(pem 0)"
}

function teardown() {
Expand Down
49 changes: 49 additions & 0 deletions tests/e2e/ledger/allow_addrs.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
GIT_ROOT="$BATS_TEST_DIRNAME/../../../"
START_BALANCE=1000000
MFX_ADDRESS=mqbfbahksdwaqeenayy2gxke32hgb7aq4ao4wt745lsfs6wiaaaaqnz

load '../../test_helper/load'
load '../../test_helper/ledger'

function setup() {
mkdir "$BATS_TEST_ROOTDIR"

skip_if_missing_background_utilities

if ! [ $CI ]; then
(
cd "$GIT_ROOT"
cargo build
)
fi

local ALLOW_ADDRS_CONFIG=$(generate_allow_addrs_config 1 2)

start_ledger --pem "$(pem 0)" \
--allow-addrs "$ALLOW_ADDRS_CONFIG" \
"--balance-only-for-testing=$(identity 1):$START_BALANCE:$MFX_ADDRESS"
}

function teardown() {
stop_background_run
}

@test "$SUITE: allow addrs" {
check_consistency --pem=1 --balance=1000000 8000

call_ledger --pem=1 --port=8000 send "$(identity 2)" 2000 MFX
check_consistency --pem=1 --balance=998000 8000
check_consistency --pem=2 --balance=2000 8000

call_ledger --pem=2 --port=8000 send "$(identity 3)" 1000 MFX
check_consistency --pem=1 --balance=998000 8000
check_consistency --pem=2 --balance=1000 8000
check_consistency --pem=3 --balance=1000 8000

call_ledger --pem=3 --port=8000 send "$(identity 1)" 500 MFX
assert_output --partial "The identity of the from field is invalid or unexpected."

check_consistency --pem=1 --balance=998000 8000
check_consistency --pem=2 --balance=1000 8000
check_consistency --pem=3 --balance=1000 8000
}
15 changes: 4 additions & 11 deletions tests/e2e/ledger.bats → tests/e2e/ledger/ledger.bats
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
GIT_ROOT="$BATS_TEST_DIRNAME/../../"
GIT_ROOT="$BATS_TEST_DIRNAME/../../../"
START_BALANCE=100000000000
MFX_ADDRESS=mqbfbahksdwaqeenayy2gxke32hgb7aq4ao4wt745lsfs6wiaaaaqnz

load '../test_helper/load'
load '../test_helper/ledger'
load '../../test_helper/load'
load '../../test_helper/ledger'

function setup() {
mkdir "$BATS_TEST_ROOTDIR"
Expand All @@ -17,16 +17,9 @@ function setup() {
)
fi

run_in_background "$GIT_ROOT/target/debug/many-ledger" \
-v \
--clean \
--persistent "$(mktemp -d)" \
--state "$GIT_ROOT/staging/ledger_state.json5" \
--pem "$(pem 0)" \
start_ledger --pem "$(pem 0)" \
"--balance-only-for-testing=$(identity 1):$START_BALANCE:$MFX_ADDRESS" \
"--balance-only-for-testing=$(identity 2):$START_BALANCE:$MFX_ADDRESS"

wait_for_background_output "Running accept thread"
}

function teardown() {
Expand Down
15 changes: 4 additions & 11 deletions tests/e2e/multisig.bats → tests/e2e/ledger/multisig.bats
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
GIT_ROOT="$BATS_TEST_DIRNAME/../../"
GIT_ROOT="$BATS_TEST_DIRNAME/../../../"
START_BALANCE=100000000000
MFX_ADDRESS=mqbfbahksdwaqeenayy2gxke32hgb7aq4ao4wt745lsfs6wiaaaaqnz

load '../test_helper/load'
load '../test_helper/ledger'
load '../../test_helper/load'
load '../../test_helper/ledger'

function setup() {
mkdir "$BATS_TEST_ROOTDIR"
Expand All @@ -17,16 +17,9 @@ function setup() {
)
fi

run_in_background "$GIT_ROOT/target/debug/many-ledger" \
-v \
--clean \
--persistent "$(mktemp -d)" \
--state "$GIT_ROOT/staging/ledger_state.json5" \
--pem "$(pem 0)" \
start_ledger --pem "$(pem 0)" \
"--balance-only-for-testing=$(identity 1):$START_BALANCE:$MFX_ADDRESS" \
"--balance-only-for-testing=$(identity 2):$START_BALANCE:$MFX_ADDRESS"

wait_for_background_output "Running accept thread"
}

function teardown() {
Expand Down
8 changes: 4 additions & 4 deletions tests/e2e/webauthn.bats → tests/e2e/ledger/webauthn.bats
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
GIT_ROOT="$BATS_TEST_DIRNAME/../../"
GIT_ROOT="$BATS_TEST_DIRNAME/../../../"

load '../test_helper/load'
load '../test_helper/ledger'
load '../../test_helper/load'
load '../../test_helper/ledger'

# Pass in the recall phrase, the identity, the cred id and the key cose.
function assert_idstore() {
Expand Down Expand Up @@ -62,7 +62,7 @@ function teardown() {
local ledger_db
local state
ledger_db="$(mktemp -d)"
state="$GIT_ROOT/tests/e2e/webauthn_state.json"
state="$GIT_ROOT/tests/e2e/ledger/webauthn_state.json"

start_ledger \
"--persistent=$ledger_db" \
Expand Down
File renamed without changes.
Loading

0 comments on commit 367cb3f

Please sign in to comment.