Secret store - initial version (#4567)

* initial secret store commit

* various fixes

* license

* (sstore, secstore) -> secretstore

* marked KeyServer trait as IPC-ready

* fixed style

* ignore requests with Origin header

* fixed tests

* fixed Origin header check
This commit is contained in:
Svyatoslav Nikolsky
2017-02-20 18:13:21 +03:00
committed by Gav Wood
parent 68a25d9e14
commit b9665c7cfe
23 changed files with 931 additions and 8 deletions

View File

@@ -185,7 +185,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result<(), String> {
execute_upgrades(&cmd.dirs.base, &db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.db_root_path().as_path()))?;
// create dirs used by parity
cmd.dirs.create_dirs(false, false)?;
cmd.dirs.create_dirs(false, false, false)?;
// prepare client config
let mut client_config = to_client_config(
@@ -356,7 +356,7 @@ fn start_client(
execute_upgrades(&dirs.base, &db_dirs, algorithm, compaction.compaction_profile(db_dirs.db_root_path().as_path()))?;
// create dirs used by parity
dirs.create_dirs(false, false)?;
dirs.create_dirs(false, false, false)?;
// prepare client config
let client_config = to_client_config(

View File

@@ -67,6 +67,12 @@ path = "$HOME/.parity/dapps"
user = "test_user"
pass = "test_pass"
[secretstore]
disable = false
port = 8082
interface = "local"
path = "$HOME/.parity/secretstore"
[ipfs]
enable = false
port = 5001

View File

@@ -38,6 +38,9 @@ port = 8080
user = "username"
pass = "password"
[secretstore]
port = 8082
[ipfs]
enable = false
port = 5001

View File

@@ -189,6 +189,16 @@ usage! {
or |c: &Config| otry!(c.dapps).pass.clone().map(Some),
flag_dapps_apis_all: bool = false, or |_| None,
// Secret Store
flag_no_secretstore: bool = false,
or |c: &Config| otry!(c.secretstore).disable.clone(),
flag_secretstore_port: u16 = 8082u16,
or |c: &Config| otry!(c.secretstore).port.clone(),
flag_secretstore_interface: String = "local",
or |c: &Config| otry!(c.secretstore).interface.clone(),
flag_secretstore_path: String = "$BASE/secretstore",
or |c: &Config| otry!(c.secretstore).path.clone(),
// IPFS
flag_ipfs_api: bool = false,
or |c: &Config| otry!(c.ipfs).enable.clone(),
@@ -327,6 +337,7 @@ struct Config {
rpc: Option<Rpc>,
ipc: Option<Ipc>,
dapps: Option<Dapps>,
secretstore: Option<SecretStore>,
ipfs: Option<Ipfs>,
mining: Option<Mining>,
footprint: Option<Footprint>,
@@ -416,6 +427,14 @@ struct Dapps {
pass: Option<String>,
}
#[derive(Default, Debug, PartialEq, RustcDecodable)]
struct SecretStore {
disable: Option<bool>,
port: Option<u16>,
interface: Option<String>,
path: Option<String>,
}
#[derive(Default, Debug, PartialEq, RustcDecodable)]
struct Ipfs {
enable: Option<bool>,
@@ -495,7 +514,8 @@ struct Misc {
mod tests {
use super::{
Args, ArgsError,
Config, Operating, Account, Ui, Network, Rpc, Ipc, Dapps, Ipfs, Mining, Footprint, Snapshots, VM, Misc
Config, Operating, Account, Ui, Network, Rpc, Ipc, Dapps, Ipfs, Mining, Footprint,
Snapshots, VM, Misc, SecretStore,
};
use toml;
@@ -650,6 +670,11 @@ mod tests {
flag_dapps_pass: Some("test_pass".into()),
flag_dapps_apis_all: false,
flag_no_secretstore: false,
flag_secretstore_port: 8082u16,
flag_secretstore_interface: "local".into(),
flag_secretstore_path: "$HOME/.parity/secretstore".into(),
// IPFS
flag_ipfs_api: false,
flag_ipfs_api_port: 5001u16,
@@ -839,6 +864,12 @@ mod tests {
user: Some("username".into()),
pass: Some("password".into())
}),
secretstore: Some(SecretStore {
disable: None,
port: Some(8082),
interface: None,
path: None,
}),
ipfs: Some(Ipfs {
enable: Some(false),
port: Some(5001)

View File

@@ -179,6 +179,16 @@ API and Console Options:
--ipfs-api-port PORT Configure on which port the IPFS HTTP API should listen.
(default: {flag_ipfs_api_port})
Secret Store Options:
--no-secretstore Disable Secret Store functionality. (default: {flag_no_secretstore})
--secretstore-port PORT Specify the port portion for Secret Store Key Server
(default: {flag_secretstore_port}).
--secretstore-interface IP Specify the hostname portion for Secret Store Key Server, IP
should be an interface's IP address, or local
(default: {flag_secretstore_interface}).
--secretstore-path PATH Specify directory where Secret Store should save its data.
(default: {flag_secretstore_path})
Sealing/Mining Options:
--author ADDRESS Specify the block author (aka "coinbase") address
for sending block rewards from sealed blocks.

View File

@@ -39,6 +39,7 @@ use dir::{self, Directories, default_hypervisor_path, default_local_path, defaul
use dapps::Configuration as DappsConfiguration;
use ipfs::Configuration as IpfsConfiguration;
use signer::{Configuration as SignerConfiguration};
use secretstore::Configuration as SecretStoreConfiguration;
use updater::{UpdatePolicy, UpdateFilter, ReleaseTrack};
use run::RunCmd;
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, KillBlockchain, ExportState, DataFormat};
@@ -121,6 +122,7 @@ impl Configuration {
let dapps_conf = self.dapps_config();
let ipfs_conf = self.ipfs_config();
let signer_conf = self.signer_config();
let secretstore_conf = self.secretstore_config();
let format = self.format()?;
let cmd = if self.args.flag_version {
@@ -346,6 +348,7 @@ impl Configuration {
dapps_conf: dapps_conf,
ipfs_conf: ipfs_conf,
signer_conf: signer_conf,
secretstore_conf: secretstore_conf,
dapp: self.dapp_to_open()?,
ui: self.args.cmd_ui,
name: self.args.flag_identity,
@@ -542,6 +545,15 @@ impl Configuration {
}
}
fn secretstore_config(&self) -> SecretStoreConfiguration {
SecretStoreConfiguration {
enabled: self.secretstore_enabled(),
interface: self.secretstore_interface(),
port: self.args.flag_secretstore_port,
data_path: self.directories().secretstore,
}
}
fn ipfs_config(&self) -> IpfsConfiguration {
IpfsConfiguration {
enabled: self.args.flag_ipfs_api,
@@ -787,6 +799,7 @@ impl Configuration {
let db_path = replace_home_for_db(&data_path, &local_path, &base_db_path);
let keys_path = replace_home(&data_path, &self.args.flag_keys_path);
let dapps_path = replace_home(&data_path, &self.args.flag_dapps_path);
let secretstore_path = replace_home(&data_path, &self.args.flag_secretstore_path);
let ui_path = replace_home(&data_path, &self.args.flag_ui_path);
if self.args.flag_geth && !cfg!(windows) {
@@ -810,6 +823,7 @@ impl Configuration {
db: db_path,
dapps: dapps_path,
signer: ui_path,
secretstore: secretstore_path,
}
}
@@ -851,6 +865,13 @@ impl Configuration {
}.into()
}
fn secretstore_interface(&self) -> String {
match self.args.flag_secretstore_interface.as_str() {
"local" => "127.0.0.1",
x => x,
}.into()
}
fn stratum_interface(&self) -> String {
match self.args.flag_stratum_interface.as_str() {
"local" => "127.0.0.1",
@@ -863,6 +884,10 @@ impl Configuration {
!self.args.flag_dapps_off && !self.args.flag_no_dapps && cfg!(feature = "dapps")
}
fn secretstore_enabled(&self) -> bool {
!self.args.flag_no_secretstore && cfg!(feature = "secretstore")
}
fn ui_enabled(&self) -> bool {
if self.args.flag_force_ui {
return true;
@@ -1083,7 +1108,7 @@ mod tests {
fn test_run_cmd() {
let args = vec!["parity"];
let conf = parse(&args);
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Run(RunCmd {
let mut expected = RunCmd {
cache_config: Default::default(),
dirs: Default::default(),
spec: Default::default(),
@@ -1113,6 +1138,7 @@ mod tests {
dapps_conf: Default::default(),
ipfs_conf: Default::default(),
signer_conf: Default::default(),
secretstore_conf: Default::default(),
ui: false,
dapp: None,
name: "".into(),
@@ -1123,7 +1149,9 @@ mod tests {
check_seal: true,
download_old_blocks: true,
verifier_settings: Default::default(),
}));
};
expected.secretstore_conf.enabled = cfg!(feature = "secretstore");
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Run(expected));
}
#[test]

View File

@@ -45,6 +45,7 @@ pub struct Directories {
pub keys: String,
pub signer: String,
pub dapps: String,
pub secretstore: String,
}
impl Default for Directories {
@@ -57,12 +58,13 @@ impl Default for Directories {
keys: replace_home(&data_dir, "$BASE/keys"),
signer: replace_home(&data_dir, "$BASE/signer"),
dapps: replace_home(&data_dir, "$BASE/dapps"),
secretstore: replace_home(&data_dir, "$BASE/secretstore"),
}
}
}
impl Directories {
pub fn create_dirs(&self, dapps_enabled: bool, signer_enabled: bool) -> Result<(), String> {
pub fn create_dirs(&self, dapps_enabled: bool, signer_enabled: bool, secretstore_enabled: bool) -> Result<(), String> {
fs::create_dir_all(&self.base).map_err(|e| e.to_string())?;
fs::create_dir_all(&self.db).map_err(|e| e.to_string())?;
fs::create_dir_all(&self.keys).map_err(|e| e.to_string())?;
@@ -72,6 +74,9 @@ impl Directories {
if dapps_enabled {
fs::create_dir_all(&self.dapps).map_err(|e| e.to_string())?;
}
if secretstore_enabled {
fs::create_dir_all(&self.secretstore).map_err(|e| e.to_string())?;
}
Ok(())
}
@@ -241,6 +246,7 @@ mod tests {
keys: replace_home(&data_dir, "$BASE/keys"),
signer: replace_home(&data_dir, "$BASE/signer"),
dapps: replace_home(&data_dir, "$BASE/dapps"),
secretstore: replace_home(&data_dir, "$BASE/secretstore"),
};
assert_eq!(expected, Directories::default());
}

View File

@@ -66,6 +66,10 @@ extern crate log as rlog;
#[cfg(feature="stratum")]
extern crate ethcore_stratum;
#[cfg(feature="secretstore")]
extern crate ethcore_secretstore;
#[cfg(feature = "dapps")]
extern crate ethcore_dapps;
@@ -101,6 +105,7 @@ mod rpc_apis;
mod run;
mod signer;
mod snapshot;
mod secretstore;
mod upgrade;
mod url;
mod user_defaults;

View File

@@ -49,6 +49,7 @@ use user_defaults::UserDefaults;
use dapps;
use ipfs;
use signer;
use secretstore;
use modules;
use rpc_apis;
use rpc;
@@ -96,6 +97,7 @@ pub struct RunCmd {
pub dapps_conf: dapps::Configuration,
pub ipfs_conf: ipfs::Configuration,
pub signer_conf: signer::Configuration,
pub secretstore_conf: secretstore::Configuration,
pub dapp: Option<String>,
pub ui: bool,
pub name: String,
@@ -190,7 +192,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
execute_upgrades(&cmd.dirs.base, &db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.db_root_path().as_path()))?;
// create dirs used by parity
cmd.dirs.create_dirs(cmd.dapps_conf.enabled, cmd.signer_conf.enabled)?;
cmd.dirs.create_dirs(cmd.dapps_conf.enabled, cmd.signer_conf.enabled, cmd.secretstore_conf.enabled)?;
// run in daemon mode
if let Some(pid_file) = cmd.daemon {
@@ -422,6 +424,10 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
};
let signer_server = signer::start(cmd.signer_conf.clone(), signer_deps)?;
// secret store key server
let secretstore_deps = secretstore::Dependencies { };
let secretstore_key_server = secretstore::start(cmd.secretstore_conf.clone(), secretstore_deps);
// the ipfs server
let ipfs_server = match cmd.ipfs_conf.enabled {
true => Some(ipfs::start_server(cmd.ipfs_conf.port, client.clone())?),
@@ -484,7 +490,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
let restart = wait_for_exit(panic_handler, Some(updater), can_restart);
// drop this stuff as soon as exit detected.
drop((http_server, ipc_server, dapps_server, signer_server, ipfs_server, event_loop));
drop((http_server, ipc_server, dapps_server, signer_server, secretstore_key_server, ipfs_server, event_loop));
info!("Finishing work, please wait...");

105
parity/secretstore.rs Normal file
View File

@@ -0,0 +1,105 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity 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.
// Parity 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 Parity. If not, see <http://www.gnu.org/licenses/>.
use dir::default_data_path;
use helpers::replace_home;
#[derive(Debug, PartialEq, Clone)]
/// Secret store configuration
pub struct Configuration {
/// Is secret store functionality enabled?
pub enabled: bool,
/// Interface to listen to
pub interface: String,
/// Port to listen to
pub port: u16,
/// Data directory path for secret store
pub data_path: String,
}
#[derive(Debug, PartialEq, Clone)]
/// Secret store dependencies
pub struct Dependencies {
// the only dependency will be BlockChainClient
}
#[cfg(not(feature = "secretstore"))]
mod server {
use super::{Configuration, Dependencies};
/// Noop key server implementation
pub struct KeyServer;
impl KeyServer {
/// Create new noop key server
pub fn new(_conf: Configuration, _deps: Dependencies) -> Result<Self, String> {
Ok(KeyServer)
}
}
}
#[cfg(feature="secretstore")]
mod server {
use ethcore_secretstore;
use super::{Configuration, Dependencies};
/// Key server
pub struct KeyServer {
_key_server: Box<ethcore_secretstore::KeyServer>,
}
impl KeyServer {
/// Create new key server
pub fn new(conf: Configuration, _deps: Dependencies) -> Result<Self, String> {
let conf = ethcore_secretstore::ServiceConfiguration {
listener_addr: conf.interface,
listener_port: conf.port,
data_path: conf.data_path,
};
let key_server = ethcore_secretstore::start(conf)
.map_err(Into::<String>::into)?;
Ok(KeyServer {
_key_server: key_server,
})
}
}
}
pub use self::server::KeyServer;
impl Default for Configuration {
fn default() -> Self {
let data_dir = default_data_path();
Configuration {
enabled: true,
interface: "127.0.0.1".to_owned(),
port: 8082,
data_path: replace_home(&data_dir, "$BASE/secretstore"),
}
}
}
/// Start secret store-related functionality
pub fn start(conf: Configuration, deps: Dependencies) -> Result<Option<KeyServer>, String> {
if !conf.enabled {
return Ok(None);
}
KeyServer::new(conf, deps)
.map(|s| Some(s))
}