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:
committed by
Gav Wood
parent
68a25d9e14
commit
b9665c7cfe
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -38,6 +38,9 @@ port = 8080
|
||||
user = "username"
|
||||
pass = "password"
|
||||
|
||||
[secretstore]
|
||||
port = 8082
|
||||
|
||||
[ipfs]
|
||||
enable = false
|
||||
port = 5001
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
105
parity/secretstore.rs
Normal 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))
|
||||
}
|
||||
Reference in New Issue
Block a user