From 49588a698705a3e233458ef6de0cb38651dd2265 Mon Sep 17 00:00:00 2001 From: Dave Parfitt Date: Mon, 11 Apr 2016 16:02:50 -0400 Subject: [PATCH 1/4] wip replace GPG with NaCl --- components/bpm/bin/hab-bpm.sh | 16 +- components/common/src/config_file.rs | 3 + components/core/Cargo.lock | 40 -- components/core/Cargo.toml | 1 - components/core/src/crypto.rs | 18 +- components/core/src/error.rs | 16 - components/core/src/fs.rs | 2 - components/core/src/gpg.rs | 431 ---------------- components/core/src/lib.rs | 2 - components/core/src/package/archive.rs | 38 +- components/depot/Cargo.lock | 36 -- components/depot/Cargo.toml | 1 - components/depot/plan/plan.sh | 5 +- components/depot/tests/server.rs | 2 +- components/depot/tests/support/path.rs | 4 + components/depot/tests/support/setup.rs | 26 +- components/hab/Cargo.lock | 40 -- components/hab/plan.sh | 5 +- components/hab/src/command/artifact/crypto.rs | 3 +- components/plan-build/bin/hab-plan-build.sh | 62 +-- components/sup/Cargo.lock | 36 -- components/sup/Cargo.toml | 1 - components/sup/plan.sh | 6 +- components/sup/src/command/key.rs | 470 ------------------ components/sup/src/command/mod.rs | 1 - components/sup/src/config.rs | 14 - components/sup/src/error.rs | 10 - components/sup/src/lib.rs | 1 - components/sup/src/main.rs | 173 +------ components/sup/tests/bldr_build/mod.rs | 1 - .../sup/tests/fixtures/chef-private.gpg | 105 ---- components/sup/tests/fixtures/chef-public.gpg | 51 -- .../tests/fixtures/habitat-20160408144426.pub | 1 + .../fixtures/habitat-20160408144426.sig.key | 1 + components/sup/tests/functional.rs | 240 +-------- components/sup/tests/sup_tests/gossip.rs | 14 +- components/sup/tests/sup_tests/key.rs | 424 +--------------- components/sup/tests/sup_tests/start.rs | 12 +- .../sup/tests/sup_tests/topology/leader.rs | 8 +- components/sup/tests/util/command.rs | 6 +- components/sup/tests/util/path.rs | 6 + 41 files changed, 124 insertions(+), 2208 deletions(-) delete mode 100644 components/core/src/gpg.rs delete mode 100644 components/sup/src/command/key.rs delete mode 100644 components/sup/tests/fixtures/chef-private.gpg delete mode 100644 components/sup/tests/fixtures/chef-public.gpg create mode 100644 components/sup/tests/fixtures/habitat-20160408144426.pub create mode 100644 components/sup/tests/fixtures/habitat-20160408144426.sig.key diff --git a/components/bpm/bin/hab-bpm.sh b/components/bpm/bin/hab-bpm.sh index 5bf2b96ea3..a0cc0890d6 100755 --- a/components/bpm/bin/hab-bpm.sh +++ b/components/bpm/bin/hab-bpm.sh @@ -635,9 +635,13 @@ install_package() { $wget $pkg_source -O $pkg_filename $wui info "Unpacking $($bb basename $pkg_filename)" - local gpg_cmd="$gpg --homedir $HAB_CACHE_GPG_PATH --decrypt $pkg_filename" - if [ -n "$VERBOSE" ]; then $gpg_cmd; else $gpg_cmd 2>/dev/null; fi \ - | $bb tar x -C $FS_ROOT/ + + /src/components/hab/target/debug/hab verify $pkg_filename + if [ $? -ne 0 ]; then + exit_with "Error verifying artifact" 99 + fi + + tail -n +4 $pkg_filename | $bb tar Xj -C $FS_ROOT/ # Clear the file download and extraction clean trap trap - INT TERM EXIT @@ -798,8 +802,6 @@ unset PATH bb="$libexec_path/busybox" # Absolute path to the `coreutils` command cu="$libexec_path/coreutils" -# Absolute path to the `gpg` command -gpg="$libexec_path/gpg" # Absolute path to the `jq` command jq="$libexec_path/jq" # Absolute path to the `wget` command @@ -857,8 +859,8 @@ HAB_PKG_PATH=$HAB_ROOT_PATH/pkgs # The default download root path for package artifacts, used on package # installation HAB_CACHE_ARTIFACT_PATH=$HAB_ROOT_PATH/cache/artifacts -# The default path where gpg keys are stored -HAB_CACHE_GPG_PATH=$HAB_ROOT_PATH/cache/gpg +# The default path where libsodium keys are stored +HAB_CACHE_KEY_PATH=$HAB_ROOT_PATH/cache/keys # The default bldr package repository from where to download dependencies : ${BLDR_REPO:=http://52.37.151.35:9632} # Whether or not more verbose output has been requested. An unset or empty diff --git a/components/common/src/config_file.rs b/components/common/src/config_file.rs index 268ede82bb..a54554845a 100644 --- a/components/common/src/config_file.rs +++ b/components/common/src/config_file.rs @@ -272,6 +272,8 @@ mod test { .join(name) } + /* + * DP TODO: GPG -> NaCl #[test] fn new_from_file() { let cf = ConfigFile::from_file(ServiceGroup::from("petty.gunslingers").unwrap(), @@ -285,6 +287,7 @@ mod test { "437ee1b702f1d14b9e2b322810b510bb25d43a260098b7820b85f3b0c09c45fa"); assert_eq!(cf.version_number, 2); } + */ #[test] fn new_from_body() { diff --git a/components/core/Cargo.lock b/components/core/Cargo.lock index 57ccff018e..c2e5ab767c 100644 --- a/components/core/Cargo.lock +++ b/components/core/Cargo.lock @@ -2,7 +2,6 @@ name = "habitat_core" version = "0.4.0" dependencies = [ - "gpgme 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "libarchive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libsodium-sys 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -22,45 +21,11 @@ dependencies = [ "memchr 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bitflags" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "gcc" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "gpg-error" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libgpg-error-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gpgme" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "gpg-error 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "gpgme-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gpgme-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libgpg-error-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "kernel32-sys" version = "0.2.1" @@ -103,11 +68,6 @@ name = "libc" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "libgpg-error-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "libsodium-sys" version = "0.0.10" diff --git a/components/core/Cargo.toml b/components/core/Cargo.toml index f70a0f5941..31ece985a3 100644 --- a/components/core/Cargo.toml +++ b/components/core/Cargo.toml @@ -4,7 +4,6 @@ version = "0.4.0" authors = ["Adam Jacob ", "Jamie Winsor ", "Fletcher Nichol ", "Joshua Timberman ", "Dave Parfitt "] [dependencies] -gpgme = "*" lazy_static = "*" libarchive = "*" log = "*" diff --git a/components/core/src/crypto.rs b/components/core/src/crypto.rs index c3092a1d7e..aa54731fee 100644 --- a/components/core/src/crypto.rs +++ b/components/core/src/crypto.rs @@ -187,9 +187,9 @@ fn nacl_key_dir() -> String { /// Calculate the BLAKE2b hash of a file /// NOTE: the key is empty -pub fn hash_file(filename: &str) -> Result { +pub fn hash_file>(filename: &P) -> Result { let key = [0u8; libsodium_sys::crypto_generichash_KEYBYTES]; - let mut file = try!(File::open(filename)); + let mut file = try!(File::open(filename.as_ref())); let mut out = [0u8; libsodium_sys::crypto_generichash_BYTES]; let mut st = vec![0u8; (unsafe { libsodium_sys::crypto_generichash_statebytes() })]; let pst = unsafe { @@ -282,6 +282,19 @@ pub fn artifact_sign(infilename: &str, Ok(()) } +pub fn get_artifact_reader(infilename: &str) -> Result> { + let f = try!(File::open(infilename)); + let mut your_key_name = String::new(); + let mut your_hash_type = String::new(); + let mut your_signature_raw = String::new(); + + let mut reader = BufReader::new(f); + let _result = reader.read_line(&mut your_key_name); + let _result = reader.read_line(&mut your_hash_type); + let _result = reader.read_line(&mut your_signature_raw); + Ok(reader) +} + pub fn artifact_verify(infilename: &str) -> Result<()> { nacl_init(); @@ -342,7 +355,6 @@ pub fn artifact_verify(infilename: &str) -> Result<()> { debug!("My hash {}", my_hash); debug!("Your hash {}", your_hash); if my_hash == your_hash { - println!("Habitat package is valid"); Ok(()) } else { Err(Error::CryptoError("Habitat package is invalid".to_string())) diff --git a/components/core/src/error.rs b/components/core/src/error.rs index 6b4cf98aac..ab020edc74 100644 --- a/components/core/src/error.rs +++ b/components/core/src/error.rs @@ -12,7 +12,6 @@ use std::num; use std::result; use std::string; -use gpgme; use libarchive; use regex; @@ -31,10 +30,6 @@ pub enum Error { CryptoError(String), /// Occurs when a file that should exist does not or could not be read. FileNotFound(String), - /// When an error occurs in GpgME library calls. - GPG(gpgme::Error), - /// Occurs when a required GPG key is not found. - InvalidKeyParameter(String), /// Occurs when a package identifier string cannot be successfully parsed. InvalidPackageIdent(String), /// Occurs when a service group string cannot be successfully parsed. @@ -69,10 +64,6 @@ impl fmt::Display for Error { } Error::CryptoError(ref e) => format!("Crypto error: {}", e), Error::FileNotFound(ref e) => format!("File not found at: {}", e), - Error::GPG(ref e) => format!("{}", e), - Error::InvalidKeyParameter(ref e) => { - format!("Invalid parameter for key generation: {:?}", e) - } Error::InvalidPackageIdent(ref e) => { format!("Invalid package identifier: {:?}. A valid identifier is in the form \ origin/name (example: chef/redis)", @@ -112,8 +103,6 @@ impl error::Error for Error { Error::BadKeyPath(_) => "An absolute path to a file on disk is required", Error::CryptoError(_) => "Crypto error", Error::FileNotFound(_) => "File not found", - Error::GPG(_) => "gpgme error", - Error::InvalidKeyParameter(_) => "Key parameter error", Error::InvalidPackageIdent(_) => "Package identifiers must be in origin/name format (example: chef/redis)", Error::InvalidServiceGroup(_) => "Service group strings must be in service.group format (example: redis.production)", Error::IO(ref err) => err.description(), @@ -135,11 +124,6 @@ impl From for Error { } } -impl From for Error { - fn from(err: gpgme::Error) -> Error { - Error::GPG(err) - } -} impl From for Error { fn from(err: io::Error) -> Error { diff --git a/components/core/src/fs.rs b/components/core/src/fs.rs index 6a955ad75a..7f2e3b6420 100644 --- a/components/core/src/fs.rs +++ b/components/core/src/fs.rs @@ -10,8 +10,6 @@ use std::path::PathBuf; pub const ROOT_PATH: &'static str = "/opt/bldr"; /// The default download root path for package artifacts, used on package installation pub const CACHE_ARTIFACT_PATH: &'static str = "/opt/bldr/cache/artifacts"; -/// The default path where gpg keys are stored -pub const CACHE_GPG_PATH: &'static str = "/opt/bldr/cache/gpg"; /// The default path where cryptographic keys are stored pub const CACHE_KEY_PATH: &'static str = "/opt/bldr/cache/keys"; /// The default path where source artifacts are downloaded, extracted, & compiled diff --git a/components/core/src/gpg.rs b/components/core/src/gpg.rs deleted file mode 100644 index dc04549e7c..0000000000 --- a/components/core/src/gpg.rs +++ /dev/null @@ -1,431 +0,0 @@ -// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers -// -// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc. -// and the party accessing this file ("Licensee") apply to Licensee's use of -// the Software until such time that the Software is made available under an -// open source license such as the Apache 2.0 License. - -use std::fs::{self, File}; -use std::io; -use std::io::Write; -use std::env; -use std::result; - -use gpgme; -use gpgme::ops; - -use error::{Error, Result}; -use fs::CACHE_GPG_PATH; -use util::perm; - -static CACHE_GPG_PATH_ENV_VAR: &'static str = "HAB_CACHE_GPG_PATH"; - -static DEFAULT_KEY_TYPE: &'static str = "RSA"; -const DEFAULT_KEY_LENGTH: u16 = 2048; - -static DEFAULT_SUBKEY_TYPE: &'static str = "RSA"; -const DEFAULT_SUBKEY_LENGTH: u16 = 2048; - -static CACHE_DIR_PERMS: &'static str = "0700"; - -#[derive(Clone, Debug)] -pub struct KeygenParams<'a> { - pub keyname: &'a str, - pub email: &'a str, - pub comment: &'a str, - pub expire_days: u16, - pub passphrase: Option<&'a String>, - pub key_type: String, - pub key_length: u16, - pub subkey_type: String, - pub subkey_length: u16, -} - -impl<'a> KeygenParams<'a> { - /// Create a `KeygenParams` with several values defaulted - pub fn new(keyname: &'a str, email: &'a str, comment: &'a str) -> KeygenParams<'a> { - KeygenParams { - keyname: keyname, - email: email, - comment: comment, - expire_days: 0, - passphrase: None, - key_type: DEFAULT_KEY_TYPE.to_string(), - key_length: DEFAULT_KEY_LENGTH, - subkey_type: DEFAULT_SUBKEY_TYPE.to_string(), - subkey_length: DEFAULT_SUBKEY_LENGTH, - } - } - - #[cfg_attr(rustfmt, rustfmt_skip)] - pub fn to_gpg_params_string(&self) -> String { - let ptext = match self.passphrase.as_ref() { - Some(p) => format!("Passphrase: {}", p), - None => "".to_string(), - }; - - // NOTE: you can't pass Passphrase: with an empty string - // so don't pass the string at all if a value doesn't exist - format!(" - - Key-Type: {key_type} - Key-Length: {key_length} - Subkey-Type: {subkey_type} - Subkey-Length: {subkey_length} - Name-Real: {name_real} - Name-Comment: {name_comment} - Name-Email: {name_email} - Expire-Date: {expire_date} - {passphrase_text} - \n", - key_type = self.key_type, - key_length = self.key_length, - subkey_type = self.subkey_type, - subkey_length = self.subkey_length, - name_real = self.keyname, - name_comment = self.comment, - name_email = self.email, - expire_date = self.expire_days, - passphrase_text = ptext) - } -} - -/// Use either the hardcoded bldr GPG path -/// or use the value from CACHE_GPG_PATH_ENV_VAR -fn gpg_cache_dir() -> String { - let gpgcache = match env::var(CACHE_GPG_PATH_ENV_VAR) { - Ok(val) => String::from(val), - Err(_) => String::from(CACHE_GPG_PATH), - }; - debug!("GPG cache = {}", gpgcache); - gpgcache -} - -/// Initialize the gpgme context w/ OpenPGP protocol and -/// GPG cache directory (which may come from an env var) -fn init_ctx() -> Result { - let mut ctx = try!(gpgme::create_context()); - try!(ctx.set_engine_info(gpgme::PROTOCOL_OPENPGP, None, Some(gpg_cache_dir()))); - Ok(ctx) -} - -/// Create the GPG cache directory if it doesn't exist -/// Set the permissions on the directory so the user has r/w/x only -fn ensure_gpg_dir() -> Result<()> { - try!(fs::create_dir_all(gpg_cache_dir())); - try!(perm::set_permissions(&gpg_cache_dir(), CACHE_DIR_PERMS)); - Ok(()) -} - -pub fn decrypt<'a>(file: &str) -> Result> { - let mut ctx = try!(init_ctx()); - try!(ensure_gpg_dir()); - let mut signature = { - let f = match File::open(&file) { - Ok(f) => f, - Err(e) => return Err(Error::from(e)), - }; - match gpgme::Data::from_seekable_reader(f) { - Ok(data) => data, - Err(wrapped_error) => return Err(Error::from(wrapped_error.error())), - } - }; - let mut out = try!(gpgme::Data::new()); - try!(ctx.decrypt(&mut signature, &mut out)); - Ok(out) -} - -/// encrypt and sign a file -/// Encrypt uses a service public key and a user public key as recipients, -/// message signing uses a **user** *private* key. -pub fn encrypt_and_sign(userkey: &str, - password: &str, - servicekey: &str, - infile: &str, - outfile: &str) - -> Result<()> { - let mut ctx = try!(init_ctx()); - - let mut infiledata = { - let f = match File::open(&infile) { - Ok(f) => f, - Err(e) => return Err(Error::from(e)), - }; - match gpgme::Data::from_seekable_reader(f) { - Ok(data) => data, - Err(wrapped_error) => return Err(Error::from(wrapped_error.error())), - - } - }; - - debug!("Loading keys"); - let ukey = try!(find_key(userkey)); - // let ukey2 = try!(find_key(userkey)); - let skey = try!(find_key(servicekey)); - - if ukey.is_none() { - return Err(Error::InvalidKeyParameter(String::from("User key not found"))); - } - if skey.is_none() { - return Err(Error::InvalidKeyParameter(String::from("Service key not \ - found"))); - } - - let ukey = ukey.unwrap(); - let skey = skey.unwrap(); - - let recipients = vec![skey, ukey]; - debug!("Keys loaded"); - - // generate text output, including BEGIN GPG MESSAGE / ENG GPG MESSAGE - ctx.set_armor(true); - - // ensure we don't pick up any stragglers - ctx.clear_signers(); - - // user signs this key for a service - try!(ctx.add_signer(&recipients[1])); - - // move the password to the heap for the closure below - let p = password.to_string(); - - // NOTE: with_passphase_cb will probably change it's parameter types - // in a future version of rust-gpgme - let mut guard = ctx.with_passphrase_cb(move |_: Option<&str>, - _: Option<&str>, - _, - out: &mut io::Write| { - debug!("Using password '{}'", p.clone()); - try!(out.write_all(p.as_bytes())); - Ok(()) - }); - - // store the encrypted output here - let mut output = try!(gpgme::Data::new()); - - // NOTE: ENCRYPT_ALWAYS_TRUST is being used below, - // This assumes that any key in your GPG keystore is trusted. - // see also: https://www.gnupg.org/gph/en/manual/x334.html - try!(guard.encrypt_and_sign(&recipients, - ops::ENCRYPT_ALWAYS_TRUST, - &mut infiledata, - &mut output)); - try!(write_output(outfile, output)); - Ok(()) -} - -/// Decrypt uses a service private key and a user public key to verify an encrypted message. -/// A service OR a user should be able to decrypt bldr-encrypted a message. -pub fn decrypt_and_verify(infile: &str, outfile: &str) -> Result<()> { - let mut ctx = try!(init_ctx()); - let mut infiledata = { - let f = match File::open(&infile) { - Ok(f) => f, - Err(e) => return Err(Error::from(e)), - }; - match gpgme::Data::from_seekable_reader(f) { - Ok(data) => data, - Err(wrapped_error) => return Err(Error::from(wrapped_error.error())), - } - }; - let mut output = try!(gpgme::Data::new()); - - match ctx.decrypt_and_verify(&mut infiledata, &mut output) { - Ok((decrypt_result, verify_result)) => { - debug!("Wrong key usage? {}", decrypt_result.wrong_key_usage()); - debug!("unsupported_algorithm? {:?}", - decrypt_result.unsupported_algorithm()); - debug!("recipients? {:?}", decrypt_result.recipients()); - debug!("filename? {:?}", decrypt_result.filename()); - debug!("signatures? {:?}", verify_result.signatures()); - debug!("filename? {:?}", verify_result.filename()); - } - Err(e) => return Err(Error::from(e)), - }; - - try!(write_output(outfile, output)); - Ok(()) -} - -/// Keep me, I'm useful for troubleshooting key import errors. -fn debug_import_result(result: ops::ImportResult) { - for i in result.imports() { - debug!("Fingerprint: {}", i.fingerprint().unwrap_or("none")); - debug!("Error: {:?}", i.result().err()); - let status = i.status(); - if status.contains(ops::IMPORT_NEW) { - debug!("NEW"); - } - if status.contains(ops::IMPORT_SECRET) { - debug!("SECRET"); - } - if status.contains(ops::IMPORT_SIG) { - debug!("SIG"); - } - if status.contains(ops::IMPORT_SUBKEY) { - debug!("SUBKEY"); - } - if status.contains(ops::IMPORT_UID) { - debug!("UID"); - } - } - - debug!("Considered: {}", result.considered()); - debug!("Imported: {}", result.imported()); - debug!("Imported RSA: {}", result.imported_rsa()); - debug!("Not imported: {}", result.not_imported()); - debug!("Unchanged: {}", result.unchanged()); - - debug!("No user id: {}", result.no_user_id()); - - debug!("New user ids: {}", result.new_user_ids()); - debug!("New subkeys: {}", result.new_subkeys()); - debug!("New signatures: {}", result.new_signatures()); - debug!("New revocations: {}", result.new_revocations()); - - debug!("Secret read: {}", result.secret_read()); - debug!("Secret imported: {}", result.secret_imported()); - debug!("Secret unchanged: {}", result.secret_unchanged()); -} - -/// Import a public key into the GPG cache -pub fn import(keyfile: &str) -> Result<()> { - try!(ensure_gpg_dir()); - let mut ctx = try!(init_ctx()); - let mut data = try!(gpgme::Data::load(&keyfile)); - ctx.set_protocol(gpgme::PROTOCOL_OPENPGP).unwrap(); - match ctx.import(&mut data) { - Ok(result) => { - debug_import_result(result); - Ok(()) - } - Err(e) => Err(Error::from(e)), - } -} - -/// Export a public key from the GPG cache. -pub fn export(key: &str, outfile: &str) -> Result<()> { - let mut ctx = try!(init_ctx()); - let key_search = try!(find_key(&key)); - if key_search.is_none() { - return Err(Error::InvalidKeyParameter(String::from("Key not found"))); - } - let k = key_search.unwrap(); - let keys = vec![k]; - let mode = ops::ExportMode::empty(); - let mut output = gpgme::Data::new().unwrap(); - ctx.set_armor(true); - if let Err(e) = ctx.export_keys(&keys, mode, Some(&mut output)) { - return Err(Error::from(e)); - }; - - try!(write_output(outfile, output)); - Ok(()) -} - -pub fn verify<'a>(file: &str) -> Result> { - let mut ctx = try!(init_ctx()); - - let mut signature = { - let f = match File::open(&file) { - Ok(f) => f, - Err(_) => return Err(Error::FileNotFound(String::from(file))), - }; - match gpgme::Data::from_seekable_reader(f) { - Ok(data) => data, - Err(e) => return Err(Error::from(e.error())), - } - }; - - let mut plain = try!(gpgme::Data::new()); - match ctx.verify(&mut signature, None, Some(&mut plain)) { - Ok(_) => Ok(plain), - Err(e) => Err(Error::from(e)), - } -} - -/// Generate a key with the given params. It must not already exist -/// in the GPG cache. -/// `RUST_LOG=bldr=debug` is your friend for this one, as the `ctx.generate_key` -/// function takes an ugly xml-ish string. -pub fn generate(params: &KeygenParams) -> Result { - try!(ensure_gpg_dir()); - - let k = try!(find_key(¶ms.keyname)); - if k.is_some() { - return Err(Error::InvalidKeyParameter(String::from("Key already exists"))); - } - - let mut ctx = try!(init_ctx()); - let s = params.to_gpg_params_string(); - debug!("{}", s); - // GnuPG does not support public and secret, they should be NULL. - // https://www.gnupg.org/documentation/manuals/gpgme/Generating-Keys.html#Generating-Keys - match ctx.generate_key(s, None, None) { - Ok(key_gen_result) => { - match key_gen_result.fingerprint() { - Some(fp) => return Ok(fp.to_string()), - // Not sure why this would happen, but here it is! - None => Ok("No fingerprint".to_string()), - } - } - Err(e) => Err(Error::from(e)), - } -} - -/// Return the **first** key that contains the `keyname` **first** in it's list of users -pub fn find_key(keyname: &str) -> Result> { - try!(ensure_gpg_dir()); - let mut ctx = try!(init_ctx()); - let mode = ops::KeyListMode::empty(); - ctx.set_key_list_mode(mode).unwrap(); - let mut keys = try!(ctx.keys()); - // irritatingly nested - for key in keys.by_ref().filter_map(result::Result::ok) { - match key.user_ids().enumerate().next() { - Some((_, user)) => { - if let Some(n) = user.name() { - if n == keyname { - return Ok(Some(key.clone())); - } - } - } - None => {} - } - } - Ok(None) -} - -/// query all keys in the gpg cache and return a vec -/// with a copy of each -pub fn list() -> Result> { - try!(ensure_gpg_dir()); - let mut ctx = try!(init_ctx()); - - // https://www.gnupg.org/documentation/manuals/gpgme/Key-Listing-Mode.html#Key-Listing-Mode - let mut mode = ops::KeyListMode::empty(); - // this is the default mode, but specify it anyways to be explicit - mode.insert(ops::KEY_LIST_MODE_LOCAL); - ctx.set_key_list_mode(mode).unwrap(); - - let mut allkeys = Vec::new(); - // get ALL keys - let mut keys = ctx.keys().unwrap(); - for key in keys.by_ref().filter_map(result::Result::ok) { - allkeys.push(key.clone()); - } - Ok(allkeys) -} - -/// write the output from a gpgme::Data object to a file -fn write_output(outfile: &str, output: gpgme::Data) -> Result<()> { - match output.into_string() { - Ok(o) => { - let mut f = try!(File::create(outfile)); - try!(f.write_all(o.as_bytes())); - Ok(()) - } - Err(Some(e)) => Err(Error::from(e)), - Err(None) => panic!("File output error"), - } -} diff --git a/components/core/src/lib.rs b/components/core/src/lib.rs index 064e357300..036408306e 100644 --- a/components/core/src/lib.rs +++ b/components/core/src/lib.rs @@ -6,7 +6,6 @@ // open source license such as the Apache 2.0 License. extern crate crypto as rust_crypto; -extern crate gpgme; #[macro_use] extern crate lazy_static; extern crate libarchive; @@ -22,7 +21,6 @@ pub use self::error::{Error, Result}; pub mod error; pub mod fs; -pub mod gpg; pub mod package; pub mod service; pub mod url; diff --git a/components/core/src/package/archive.rs b/components/core/src/package/archive.rs index 2794e5c96f..ba2bc0e398 100644 --- a/components/core/src/package/archive.rs +++ b/components/core/src/package/archive.rs @@ -6,20 +6,16 @@ // open source license such as the Apache 2.0 License. use std::collections::HashMap; -use std::fs::File; -use std::io::{Read, Seek, SeekFrom}; use std::path::PathBuf; use std::str::{self, FromStr}; -use rust_crypto::sha2::Sha256; -use rust_crypto::digest::Digest; use libarchive::writer; use libarchive::reader::{self, Reader}; use libarchive::archive::{Entry, ReadFilter, ReadFormat}; use regex::Regex; use error::{Error, Result}; -use gpg; +use crypto; use package::{PackageIdent, MetaFile}; lazy_static! { @@ -55,19 +51,13 @@ impl PackageArchive { } } - /// Calculate and return the checksum of the package archive in hexadecimal format. + /// Calculate and return the checksum of the package archive in base64 format. /// /// # Failures /// /// * If the archive cannot be read pub fn checksum(&self) -> Result { - let mut digest = Sha256::new(); - let mut file = try!(File::open(&self.path)); - let mut buffer = Vec::new(); - try!(file.read_to_end(&mut buffer)); - digest.input(&buffer); - let hash = digest.result_str(); - Ok(hash) + crypto::hash_file(&self.path) } pub fn cflags(&mut self) -> Result> { @@ -164,16 +154,13 @@ impl PackageArchive { } /// Given a package name and a path to a file as an `&str`, verify - /// the files gpg signature. + /// the files signature. /// /// # Failures /// - /// * Fails if it cannot verify the GPG signature for any reason + /// * Fails if it cannot verify the signature for any reason pub fn verify(&self) -> Result<()> { - match gpg::verify(self.path.to_str().unwrap()) { - Ok(_) => Ok(()), - Err(e) => Err(e), - } + crypto::artifact_verify(self.path.to_str().unwrap()) } /// Given a package name and a path to a file as an `&str`, unpack @@ -181,15 +168,14 @@ impl PackageArchive { /// /// # Failures /// - /// * If the package cannot be unpacked via gpg + /// * If the package cannot be unpacked pub fn unpack(&self) -> Result<()> { let file = self.path.to_str().unwrap().to_string(); - let mut out = try!(gpg::verify(&file)); - try!(out.seek(SeekFrom::Start(0))); + let tar_reader = try!(crypto::get_artifact_reader(&file)); let mut builder = reader::Builder::new(); try!(builder.support_format(ReadFormat::All)); try!(builder.support_filter(ReadFilter::All)); - let mut reader = try!(builder.open_stream(out)); + let mut reader = try!(builder.open_stream(tar_reader)); let writer = writer::Disk::new(); try!(writer.set_standard_lookup()); try!(writer.write(&mut reader, Some("/"))); @@ -228,12 +214,11 @@ impl PackageArchive { let mut metadata = Metadata::new(); let mut matched_count = 0u8; let f = self.path.to_str().unwrap().to_string(); - let mut out = try!(gpg::verify(&f)); - try!(out.seek(SeekFrom::Start(0))); + let tar_reader = try!(crypto::get_artifact_reader(&f)); let mut builder = reader::Builder::new(); try!(builder.support_format(ReadFormat::All)); try!(builder.support_filter(ReadFilter::All)); - let mut reader = try!(builder.open_stream(out)); + let mut reader = try!(builder.open_stream(tar_reader)); loop { let mut matched_type: Option = None; if let Some(entry) = reader.next_header() { @@ -271,5 +256,6 @@ impl PackageArchive { } self.metadata = Some(metadata); Ok(self.metadata.as_ref().unwrap().get(&file)) + } } diff --git a/components/depot/Cargo.lock b/components/depot/Cargo.lock index 5523ee92aa..4853ffa4c3 100644 --- a/components/depot/Cargo.lock +++ b/components/depot/Cargo.lock @@ -6,7 +6,6 @@ dependencies = [ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gpgme 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "habitat_core 0.4.0", "habitat_depot_core 0.4.0", "hyper 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -142,40 +141,10 @@ dependencies = [ "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "gpg-error" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libgpg-error-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gpgme" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "gpg-error 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "gpgme-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gpgme-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libgpg-error-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "habitat_core" version = "0.4.0" dependencies = [ - "gpgme 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "libarchive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "libsodium-sys 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -296,11 +265,6 @@ name = "libc" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "libgpg-error-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "libressl-pnacl-sys" version = "2.1.6" diff --git a/components/depot/Cargo.toml b/components/depot/Cargo.toml index b4beaa9700..552e68285c 100644 --- a/components/depot/Cargo.toml +++ b/components/depot/Cargo.toml @@ -11,7 +11,6 @@ doc = false bincode = "*" bitflags = "*" env_logger = "*" -gpgme = "*" hyper = "*" iron = "*" libc = "*" diff --git a/components/depot/plan/plan.sh b/components/depot/plan/plan.sh index 4ce436ced0..4ff373a0da 100644 --- a/components/depot/plan/plan.sh +++ b/components/depot/plan/plan.sh @@ -5,8 +5,7 @@ pkg_maintainer="The Habitat Maintainers " pkg_license=('apachev2') pkg_source=nosuchfile.tar.gz pkg_bin_dirs=(bin) -pkg_deps=(chef/glibc chef/openssl chef/gcc-libs chef/gpgme chef/libarchive - chef/libgpg-error chef/rngd chef/libsodium) +pkg_deps=(chef/glibc chef/openssl chef/gcc-libs chef/libarchive chef/libsodium) pkg_build_deps=(chef/coreutils chef/cacerts chef/rust chef/gcc chef/libsodium) pkg_service_run="bin/hab-depot start" pkg_gpg_key=3853DA6B @@ -16,8 +15,6 @@ do_build() { cargo clean env OPENSSL_LIB_DIR=$(pkg_path_for chef/openssl)/lib \ OPENSSL_INCLUDE_DIR=$(pkg_path_for chef/openssl)/include \ - GPGME_CONFIG=$(pkg_path_for chef/gpgme)/bin/gpgme-config \ - GPG_ERROR_CONFIG=$(pkg_path_for chef/libgpg-error)/bin/gpg-error-config \ LIBARCHIVE_LIB_DIR=$(pkg_path_for chef/libarchive)/lib \ LIBARCHIVE_INCLUDE_DIR=$(pkg_path_for chef/libarchive)/include \ SSL_CERT_FILE=$(pkg_path_for chef/cacerts)/ssl/cert.pem \ diff --git a/components/depot/tests/server.rs b/components/depot/tests/server.rs index d6c6e75ddc..51bcf9356b 100644 --- a/components/depot/tests/server.rs +++ b/components/depot/tests/server.rs @@ -117,7 +117,7 @@ use support::{command, docker, setup}; #[test] #[ignore] fn upload_a_package_and_then_install_it() { - setup::gpg_import(); + setup::origin_setup(); setup::key_install(); setup::simple_service(); let d = docker::depot("test/simple_service"); diff --git a/components/depot/tests/support/path.rs b/components/depot/tests/support/path.rs index 05b84e02ee..d830dda8dc 100644 --- a/components/depot/tests/support/path.rs +++ b/components/depot/tests/support/path.rs @@ -20,6 +20,10 @@ pub fn fixtures() -> PathBuf { root().join("fixtures") } +pub fn key_cache() -> PathBuf { + root().join("fixtures") +} + pub fn fixture_as_string(name: &str) -> String { let fixture_string = fixtures().join(name).to_string_lossy().into_owned(); fixture_string diff --git a/components/depot/tests/support/setup.rs b/components/depot/tests/support/setup.rs index 666a55ae28..68777e162a 100644 --- a/components/depot/tests/support/setup.rs +++ b/components/depot/tests/support/setup.rs @@ -6,30 +6,10 @@ // open source license such as the Apache 2.0 License. use std::sync::{Once, ONCE_INIT}; +use std::env; -pub fn gpg_import() { - static ONCE: Once = ONCE_INIT; - ONCE.call_once(|| { - let mut gpg = match super::command::studio_run("gpg", - &["--import", - &super::path::fixture_as_string("chef-private.gpg")]) { - Ok(cmd) => cmd, - Err(e) => panic!("{:?}", e), - }; - gpg.wait_with_output(); - if !gpg.status.unwrap().success() { - match gpg.stderr { - Some(stderr) => { - use regex::Regex; - let re = Regex::new("already in secret keyring").unwrap(); - if !re.is_match(&stderr) { - panic!("Failed to import gpg keys"); - } - } - None => panic!("Failed to import gpg keys") - } - } - }); +pub fn origin_setup() { + env::set_var("HABITAT_KEY_CACHE", super::path::key_cache()); } pub fn simple_service() { diff --git a/components/hab/Cargo.lock b/components/hab/Cargo.lock index a44b5cf287..dd8284da32 100644 --- a/components/hab/Cargo.lock +++ b/components/hab/Cargo.lock @@ -28,11 +28,6 @@ name = "ansi_term" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "bitflags" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitflags" version = "0.4.0" @@ -84,35 +79,6 @@ dependencies = [ "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "gpg-error" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libgpg-error-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gpgme" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "gpg-error 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "gpgme-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gpgme-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libgpg-error-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "habitat_common" version = "0.4.0" @@ -130,7 +96,6 @@ dependencies = [ name = "habitat_core" version = "0.4.0" dependencies = [ - "gpgme 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "libarchive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libsodium-sys 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -245,11 +210,6 @@ name = "libc" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "libgpg-error-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "libressl-pnacl-sys" version = "2.1.6" diff --git a/components/hab/plan.sh b/components/hab/plan.sh index 3d24cb0c6a..b9ce7f3c12 100644 --- a/components/hab/plan.sh +++ b/components/hab/plan.sh @@ -5,8 +5,7 @@ pkg_maintainer="The Habitat Maintainers " pkg_license=('apachev2') pkg_source=nosuchfile.tar.gz pkg_bin_dirs=(bin) -pkg_deps=(chef/glibc chef/openssl chef/gcc-libs chef/gpgme chef/libarchive - chef/libgpg-error chef/rngd chef/libsodium) +pkg_deps=(chef/glibc chef/openssl chef/gcc-libs chef/libarchive chef/libsodium) pkg_build_deps=(chef/coreutils chef/cacerts chef/rust chef/gcc chef/libsodium) pkg_gpg_key=3853DA6B @@ -15,8 +14,6 @@ do_build() { cargo clean env OPENSSL_LIB_DIR=$(pkg_path_for chef/openssl)/lib \ OPENSSL_INCLUDE_DIR=$(pkg_path_for chef/openssl)/include \ - GPGME_CONFIG=$(pkg_path_for chef/gpgme)/bin/gpgme-config \ - GPG_ERROR_CONFIG=$(pkg_path_for chef/libgpg-error)/bin/gpg-error-config \ LIBARCHIVE_LIB_DIR=$(pkg_path_for chef/libarchive)/lib \ LIBARCHIVE_INCLUDE_DIR=$(pkg_path_for chef/libarchive)/include \ SSL_CERT_FILE=$(pkg_path_for chef/cacerts)/ssl/cert.pem \ diff --git a/components/hab/src/command/artifact/crypto.rs b/components/hab/src/command/artifact/crypto.rs index 1dba4fbd12..e00012270c 100644 --- a/components/hab/src/command/artifact/crypto.rs +++ b/components/hab/src/command/artifact/crypto.rs @@ -14,7 +14,7 @@ pub fn generate_origin_key(origin_key: &str) -> Result<()> { } pub fn hash(infile: &str) -> Result<()> { - let h = try!(crypto::hash_file(infile)); + let h = try!(crypto::hash_file(&infile)); println!("{}", h); Ok(()) } @@ -44,6 +44,7 @@ pub fn sign(origin_key: &str, infile: &str, outfile: &str) -> Result<()> { pub fn verify(infile: &str) -> Result<()> { try!(crypto::artifact_verify(infile)); + println!("Habitat artifact is valid"); Ok(()) } diff --git a/components/plan-build/bin/hab-plan-build.sh b/components/plan-build/bin/hab-plan-build.sh index b6f1c29f0a..d4b6d86c36 100755 --- a/components/plan-build/bin/hab-plan-build.sh +++ b/components/plan-build/bin/hab-plan-build.sh @@ -27,14 +27,13 @@ # pkg_source=http://downloads.sourceforge.net/project/libpng/$pkg_name/${pkg_version}/${pkg_name}-${pkg_version}.tar.gz # pkg_filename=${pkg_name}-${pkg_version}.tar.gz # pkg_shasum=36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d -# pkg_gpg_key=3853DA6B # pkg_deps=(glibc) # pkg_lib_dirs=(lib) # pkg_include_dirs=(include) # ``` # # It has the name of the software, the version, where to download it, a -# checksum to verify the contents are what we expect, a GPG key to sign the +# checksum to verify the contents are what we expect, an origin key to sign the # resulting package with, a single dependency on glibc, and it has the # resulting libraries in `lib` and header files in `include`. # @@ -47,7 +46,7 @@ # 1. Run `./configure && make` # 1. Run `make install` # 1. Write out the data other packages need to depend on `zlib` -# 1. Create a GPG signed tarball of the results +# 1. Create a libsodium signed tarball of the results # # ## Plan Options # @@ -95,11 +94,6 @@ # pkg_shasum=36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d # ``` # -# ### pkg_gpg_key -# The GPG key to sign the package with. -# ``` -# pkg_gpg_key=3853DA6B -# ``` # # ### pkg_deps # An array of the package dependencies needed at runtime. @@ -211,7 +205,6 @@ # pkg_source=http://www.haproxy.org/download/1.5/src/${pkg_name}-${pkg_version}.tar.gz # pkg_filename=${pkg_name}-${pkg_version}.tar.gz # pkg_shasum=6648dd7d6b958d83dd7101eab5792178212a66c884bec0ebcd8abc39df83bb78 -# pkg_gpg_key=3853DA6B # pkg_bin_dirs=(bin) # pkg_deps=(glibc pcre openssl zlib) # pkg_service_run="bin/haproxy -f $pkg_svc_config_path/haproxy.conf" @@ -395,7 +388,6 @@ trap _on_exit 1 2 3 15 ERR # * `$_wget_cmd` (wget on system) # * `$_shasum_cmd` (either gsha256sum or sha256sum on system) # * `$_tar_cmd` (GNU version of tar) -# * `$_gpg_cmd` (GPG on system) # * `$_mktemp_cmd` (GNU version from coreutils) # # Note that all of the commands noted above are considered internal @@ -445,12 +437,6 @@ _find_system_commands() { fi debug "Setting _tar_cmd=$_tar_cmd" - if exists gpg; then - _gpg_cmd=$(command -v gpg) - else - exit_with "We require gpg to sign packages; aborting" 1 - fi - debug "Setting _gpg_cmd=$_gpg_cmd" } # **Internal** Return the path to the latest release of a package on stdout. @@ -1865,16 +1851,31 @@ EOT return 0 } -# **Internal** Create the package with `tar`/`gpg`, and sign it with -# `$pkg_gpg_key`. +# **Internal** Create the package with `tar`/`hab artifact sign` _generate_package() { - build_line "Generating package" + build_line "Generating artifact" mkdir -p $HAB_CACHE_ARTIFACT_PATH - $_tar_cmd -cf - "$pkg_prefix" | $_gpg_cmd \ - --set-filename x.tar \ - --local-user $pkg_gpg_key \ - --output $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.bldr\ - --sign + local artifact_base=$HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel} + echo "dest $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.xz" + echo "source ${pkg_prefix}" + # TODO: it would be nice to just stream to tar stuff to `hab artifact sign` + $_tar_cmd cJf $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.xz ${pkg_prefix} + + # TODO: HABITAT_ORIGIN MUST be set, do we assume a default? + # TODO: env var for the path to `hab`? + build_line "Signing artifact" + /src/components/hab/target/debug/hab artifact sign \ + $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.xz \ + $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.hab --origin ${HABITAT_ORIGIN} + + build_line "Verifying artifact" + ## TODO: pretty output + /src/components/hab/target/debug/hab artifact verify \ + $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.hab + + # TODO + rm $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.xz + return 0 } @@ -1945,10 +1946,6 @@ if [[ -z "${pkg_version}" ]]; then exit_with "Failed to build. 'pkg_version' must be set." 1 fi -# `$pkg_gpg_key` is a required metadata key -if [[ -z "${pkg_gpg_key}" ]]; then - exit_with "Failed to build. 'pkg_gpg_key' must be set." 1 -fi # Set `$pkg_filename` to the basename of `$pkg_source`, if it is not already # set by the `plan.sh`. @@ -1989,12 +1986,7 @@ _resolve_dependencies _set_path -# Ensure that the GPG secret key is loaded and ready for package signing. -if ! $_gpg_cmd --list-secret-keys | grep -q "/${pkg_gpg_key} " > /dev/null; then - warn "GPG key for pkg_gpg_key=$pkg_gpg_key is not loaded in secret key ring." - warn "Did you forget to import your signing key with 'gpg --import .gpg'?" - exit_with "Failed to build. GPG secret key must be loaded." 1 -fi +# TODO: ensure origin is set via env # Download the source mkdir -pv $HAB_CACHE_SRC_PATH @@ -2052,7 +2044,7 @@ do_end # Print the results build_line "Source Cache: $HAB_CACHE_SRC_PATH/$pkg_dirname" build_line "Installed Path: $pkg_prefix" -build_line "Artifact: $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.bldr" +build_line "Artifact: $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.hab" # Exit cleanly build_line diff --git a/components/sup/Cargo.lock b/components/sup/Cargo.lock index 9231860f43..03b3796895 100644 --- a/components/sup/Cargo.lock +++ b/components/sup/Cargo.lock @@ -5,7 +5,6 @@ dependencies = [ "ansi_term 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gpgme 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "habitat_common 0.4.0", "habitat_core 0.4.0", "habitat_depot_client 0.4.0", @@ -142,35 +141,6 @@ dependencies = [ "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "gpg-error" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libgpg-error-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gpgme" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "gpg-error 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "gpgme-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gpgme-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libgpg-error-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "habitat_common" version = "0.4.0" @@ -188,7 +158,6 @@ dependencies = [ name = "habitat_core" version = "0.4.0" dependencies = [ - "gpgme 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "libarchive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libsodium-sys 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -329,11 +298,6 @@ name = "libc" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "libgpg-error-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "libressl-pnacl-sys" version = "2.1.6" diff --git a/components/sup/Cargo.toml b/components/sup/Cargo.toml index 2908d9d672..e438af663b 100644 --- a/components/sup/Cargo.toml +++ b/components/sup/Cargo.toml @@ -19,7 +19,6 @@ rustc-serialize = "*" log = "*" env_logger = "*" ansi_term = "*" -gpgme = "*" hyper = "*" tempdir = "*" toml = "*" diff --git a/components/sup/plan.sh b/components/sup/plan.sh index a90c9b097a..d337b69d2c 100644 --- a/components/sup/plan.sh +++ b/components/sup/plan.sh @@ -5,8 +5,8 @@ pkg_maintainer="The Habitat Maintainers " pkg_license=('apachev2') pkg_source=nosuchfile.tar.gz pkg_bin_dirs=(bin) -pkg_deps=(chef/glibc chef/openssl chef/gcc-libs chef/gpgme chef/libarchive - chef/libgpg-error chef/rngd chef/busybox-static chef/libsodium) +pkg_deps=(chef/glibc chef/openssl chef/gcc-libs chef/libarchive + chef/busybox-static chef/libsodium) pkg_build_deps=(chef/coreutils chef/cacerts chef/rust chef/gcc chef/libsodium) pkg_gpg_key=3853DA6B @@ -15,8 +15,6 @@ do_build() { cargo clean env OPENSSL_LIB_DIR=$(pkg_path_for chef/openssl)/lib \ OPENSSL_INCLUDE_DIR=$(pkg_path_for chef/openssl)/include \ - GPGME_CONFIG=$(pkg_path_for chef/gpgme)/bin/gpgme-config \ - GPG_ERROR_CONFIG=$(pkg_path_for chef/libgpg-error)/bin/gpg-error-config \ LIBARCHIVE_LIB_DIR=$(pkg_path_for chef/libarchive)/lib \ LIBARCHIVE_INCLUDE_DIR=$(pkg_path_for chef/libarchive)/include \ SSL_CERT_FILE=$(pkg_path_for chef/cacerts)/ssl/cert.pem \ diff --git a/components/sup/src/command/key.rs b/components/sup/src/command/key.rs deleted file mode 100644 index 9216534cda..0000000000 --- a/components/sup/src/command/key.rs +++ /dev/null @@ -1,470 +0,0 @@ -// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers -// -// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc. -// and the party accessing this file ("Licensee") apply to Licensee's use of -// the Software until such time that the Software is made available under an -// open source license such as the Apache 2.0 License. - -use std::fs; -use std::path::Path; -use std::process::{Command, Stdio, Child}; - -use ansi_term::Colour::{Yellow, Red}; -use hcore::package::PackageIdent; -use hcore::fs::CACHE_KEY_PATH; -use hcore::gpg; -use depot_client; -use time::strptime; -use rpassword::read_password; -use regex::Regex; - -use config::Config; -use error::{Error, Result}; -use package::Package; - -static LOGKEY: &'static str = "KU"; // "key utils" -static USER_KEY_COMMENT: &'static str = "bldr user key"; -static SERVICE_KEY_COMMENT: &'static str = "bldr service key"; -// "bldr managed keys" all start with a prefix -static BLDR_KEY_PREFIX: &'static str = "bldr_"; -static BLDR_EMAIL_SUFFIX: &'static str = "@bldr"; - -/// Uploads a gpg key to a [depot](../depot). -/// -/// If the key starts with a `/`, we treat it as a path to a specific file; otherwise, it's a key -/// to grab from the cache in `CACHE_KEY_PATH`. Either way, we read the file and upload it to -/// the depot. -/// -/// # Failures -/// -/// * If the file fails to exist, or if we can't read it -/// * If the http upload fails -/// # Examples -/// -/// ```bash -/// $ bldr upload-key chef-public -u http://localhost:9633 -/// ``` -/// -/// Will upload the `chef-public` key from the local key cache to the depot url. -/// -/// ```bash -/// $ bldr upload-key --infile /tmp/chef-public -u http://localhost:9633 -/// ``` -/// -/// Will upload the key at `/tmp/chef-public.asc` to the depot url. -/// -pub fn upload(config: &Config) -> Result<()> { - let url = config.url().as_ref().unwrap(); - let path = Path::new(config.key()); - - match fs::metadata(path) { - Ok(_) => { - outputln!("Uploading {}", config.key()); - try!(depot_client::put_key(url, path)); - } - Err(_) => { - if path.components().count() == 1 { - let file = format!("{}/{}.asc", CACHE_KEY_PATH, config.key()); - let cached = Path::new(&file); - match fs::metadata(&cached) { - Ok(_) => { - outputln!("Uploading {}.asc", config.key()); - try!(depot_client::put_key(url, cached)); - } - Err(_) => { - return Err(sup_error!(Error::KeyNotFound(config.key().to_string()))); - } - } - } else { - return Err(sup_error!(Error::FileNotFound(config.key().to_string()))); - } - } - } - outputln!("Complete"); - Ok(()) -} - -/// Imports a gpg key from a [depot](../depot) or a local file. -/// If `config.infile() is not empty, we try to load from a file. -/// Otherwise, we load the key `config.key()` from `config.url()`, -/// drop it in `CACHE_KEY_PATH`, and then import it into GPG. -/// -/// # Failures -/// -/// * If the directory `CACHE_KEY_PATH` cannot be created -/// * If the we fail to download the key from the depot -/// * If the GPG import process fails -/// -/// # Examples -/// -/// ```bash -/// $ bldr import-key chef-public -u http://localhost:9633 -/// ``` -/// -/// Will download the `chef-public` gpg key from the specified depot. -/// -/// ```bash -/// $ bldr import-key --infile /tmp/chef-public.asc -/// ``` -/// -/// Will install the key found in `/tmp/chef-public.asc`. -/// -pub fn import(config: &Config) -> Result<()> { - match *config.infile() { - Some(ref infile) => { - try!(gpg::import(infile)); - } - None => { - try!(fs::create_dir_all(CACHE_KEY_PATH)); - // docopt requires -u to be set, so we should be safe to unwrap here - let url = config.url().as_ref().unwrap(); - let filename = try!(depot_client::fetch_key(&url, &config.key(), CACHE_KEY_PATH)); - try!(gpg::import(&filename)); - } - } - outputln!("Successfully imported key(s)"); - Ok(()) -} - -/// Exports a public user or service key to a local file. -/// When importing a service key, if the group is not specified -/// it defaults to `default`. -/// -/// # Examples -/// ```bash -/// $ bldr export-key --user foo --outfile /tmp/foo.pubkey -/// ``` -/// -/// ```bash -/// $ bldr export-key --service redis --outfile /tmp/redis.pubkey -/// ``` -/// -/// ```bash -/// $ bldr export-key --service redis --group dev --outfile /tmp/redis.pubkey -/// ``` -/// -pub fn export(config: &Config) -> Result<()> { - // it's either a service key or a user key, - // docopt will fail if you don't specify one or the other - let keyname = if config.service_key().is_some() { - gen_service_key_name(&config.service_key().as_ref().unwrap(), config.group()) - } else { - gen_user_key_name(&config.user_key().as_ref().unwrap()) - }; - let outfile = config.outfile().as_ref().unwrap(); - try!(gpg::export(&keyname, &outfile)); - outputln!("Successfully exported key {} to {}", - Yellow.bold().paint(keyname), - Yellow.bold().paint(outfile as &str)); - Ok(()) -} - -/// Encrypt and sign a file. -/// Valid user and service keys must be specified. -/// The user and service are both specified as recipients in the encrypted message. -/// The user key is used to sign the encrypted message. -/// If a password is not specified for the user key with the `--password` flag, -/// bldr will display an interactive prompt. -pub fn encrypt_and_sign(config: &Config) -> Result<()> { - // these values are required per docopt, so they really *shouldn't* be empty - let userkey = config.user_key().as_ref().unwrap(); - let servicekey = config.service_key().as_ref().unwrap(); - - let infile = config.infile().as_ref().unwrap(); - let outfile = config.outfile().as_ref().unwrap(); - - outputln!("Attempting to encrypt {}, sending output to {}", - Yellow.bold().paint(infile as &str), - Yellow.bold().paint(outfile as &str)); - - // prepend BLDR_KEY_PREFIX to the key name, these are the bldr keys - let full_userkey = gen_user_key_name(&userkey); - let full_servicekey = gen_service_key_name(&servicekey, config.group()); - let password = match config.password().clone() { - Some(p) => p, - None => { - println!("Please enter the key password for {}:", userkey); - let password = try!(read_password()); - debug!("The password is: '{}'", password); - password - } - }; - - debug!("User key: {}", full_userkey); - debug!("Service key: {}", full_servicekey); - debug!("Input file: {}", infile); - debug!("Output file: {}", outfile); - - try!(gpg::encrypt_and_sign(&full_userkey, - &password, - &full_servicekey, - &infile, - &outfile)); - - outputln!("Successfully wrote encrypted output to {}", - Yellow.bold().paint(outfile as &str)); - Ok(()) -} - -/// Decrypt a file -/// The private key of the service must reside in the current GPG cache. -/// The public key of the user must reside in the current GPG cache to -/// verify the signature. -pub fn decrypt_and_verify(config: &Config) -> Result<()> { - let infile = config.infile().as_ref().unwrap(); - let outfile = config.outfile().as_ref().unwrap(); - let msg = format!("Attempting to decrypt {}, sending output to {}", - infile as &str, - outfile as &str); - outputln!("{}", Yellow.bold().paint(msg)); - try!(gpg::decrypt_and_verify(&infile, &outfile)); - outputln!("Successfully wrote decrypted output to {}", - Yellow.bold().paint(outfile as &str)); - Ok(()) -} - -/// list ALL keys in gpg -pub fn list(_config: &Config) -> Result<()> { - let keys = try!(gpg::list()); - for key in &keys { - for (_, user) in key.user_ids().enumerate() { - // Pull out the uid so Cow is happy - let uid = user.uid().unwrap_or(""); - println!("{}", Yellow.bold().paint(uid)); - } - println!(" Key: {}", key.id().unwrap_or("---")); - println!(" Fingerprint: {}", key.fingerprint().unwrap_or("---")); - let primary_key = key.primary_key().unwrap(); - let expire = match primary_key.expires() { - None => "Never".to_string(), - Some(val) => { - let datetime = strptime(&val.to_string(), "%s").unwrap(); - format!("{}", datetime.rfc822()) - } - }; - println!(" Expires: {}", expire); - if key.is_revoked() { - println!("\t{}", Red.bold().paint("Revoked")); - } - if key.is_expired() { - println!("\t{}", Red.bold().paint("Expired")); - } - if key.is_disabled() { - println!("\t{}", Red.bold().paint("Disabled")); - } - if key.is_invalid() { - println!("\t{}", Red.bold().paint("Invalid")); - } - } - Ok(()) -} - -/// ensure parameters are correct before generating -/// gpg "xml-ish" parameter string -fn check_params(params: &gpg::KeygenParams) -> Result<()> { - // must be at least 5 characters - if params.keyname.len() < 5 { - return Err(sup_error!(Error::InvalidKeyParameter("key name must be at least 5 \ - characters in length" - .to_string()))); - } - - // must contain an @ sign between 1 or more characters - let re = Regex::new(r".+@.+").unwrap(); - if !re.is_match(¶ms.email) { - return Err(sup_error!(Error::InvalidKeyParameter("key email address must contain \ - an @ symbol" - .to_string()))); - } - return Ok(()); -} - -/// generate a service key name in the form of -/// `bldr_keyname.group`. If a service key is already in the -/// form BLDR_KEY_PREFIX.+, then just return it -fn gen_service_key_name(keyname: &str, group: &str) -> String { - let re = String::from(BLDR_KEY_PREFIX) + ".+"; - let regex = Regex::new(&re).unwrap(); - if regex.is_match(keyname) { - // it's already in normalized form - keyname.to_string() - } else { - format!("{}{}.{}", BLDR_KEY_PREFIX, keyname, group) - } -} - -/// generate a service key email address in the form of -/// `keyname.group@bldr` -fn gen_service_key_email(keyname: &str, group: &str) -> String { - format!("{}.{}{}", keyname, group, BLDR_EMAIL_SUFFIX) -} - -/// generate a user key name in the form of -/// `bldr_keyname`. If a user key is already in the -/// form BLDR_KEY_PREFIX.+, then just return it -fn gen_user_key_name(keyname: &str) -> String { - let re = String::from(BLDR_KEY_PREFIX) + ".+"; - let regex = Regex::new(&re).unwrap(); - if regex.is_match(keyname) { - // it's already in normalized form - keyname.to_string() - } else { - format!("{}{}", BLDR_KEY_PREFIX, keyname) - } -} - -/// Used to kill the rngd process in the event of an error -struct DroppableChildProcess { - child: Child, -} - -impl Drop for DroppableChildProcess { - fn drop(&mut self) { - debug!("Killing rngd"); - let _ = self.child.kill(); - debug!("Waiting for rngd to die"); - let _ = self.child.wait(); - () - } -} - -/// run rngd in the background to generate entropy while generating keys. -/// The process is killed when it goes out of scope via `DroppableChildProcess`. -fn run_rngd() -> Result { - debug!("Spawning rngd in the background"); - let res = try!(Package::load(&PackageIdent::new("chef", "rngd", None, None), None)); - let rngdpath = res.path().join("sbin/rngd"); - debug!("RNGD path = {}", rngdpath.display()); - let child = Command::new(rngdpath) - .arg("-f") - .arg("-r") - .arg("/dev/urandom") - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .spawn() - .unwrap_or_else(|e| panic!("failed to execute child: {}", e)); - let droppable = DroppableChildProcess { child: child }; - Ok(droppable) -} - -/// generate a user key in gpg -/// A user key requires a password and valid email address -/// If the user key already exists in gpg, it will not be created. -pub fn generate_user_key(config: &Config) -> Result<()> { - let _child = try!(run_rngd()); - let email = config.email().as_ref().unwrap(); - // clap requires user_key to be specified for generate - let user_key = config.user_key().as_ref().unwrap(); - let keyname = gen_user_key_name(user_key); - - let password = match config.password().clone() { - Some(p) => p, - None => { - println!("Please enter a password for {}:", user_key); - let p = try!(read_password()); - debug!("The password is: '{}'", p); - p - } - }; - - let fingerprint = { - let mut params = gpg::KeygenParams::new(&keyname, &email, USER_KEY_COMMENT); - params.passphrase = Some(&password); - params.expire_days = config.expire_days().unwrap_or(0); - try!(check_params(¶ms)); - try!(gpg::generate(¶ms)) - }; - - outputln!("Successfully generated user key {}", - Yellow.bold().paint(keyname)); - - outputln!("Fingerprint: {}", Yellow.bold().paint(fingerprint)); - Ok(()) -} - -/// generate a service key in gpg -/// A service key does NOT require a password -/// A service key has an email address automatically generated, in -/// the form: `service.group@bldr` -pub fn generate_service_key(config: &Config) -> Result<()> { - let _child = try!(run_rngd()); - let comment = SERVICE_KEY_COMMENT; - // clap requires service_key to be specified - let service_key = config.service_key().as_ref().unwrap(); - let kn = gen_service_key_name(service_key, config.group()); - let ke = gen_service_key_email(service_key, config.group()); - let fingerprint = { - let mut params = gpg::KeygenParams::new(&kn, &ke, comment); - params.passphrase = None; - params.expire_days = config.expire_days().unwrap_or(0); - try!(check_params(¶ms)); - try!(gpg::generate(¶ms)) - }; - - outputln!("Successfully generated service key {}", - Yellow.bold().paint(kn)); - outputln!("Fingerprint: {}", Yellow.bold().paint(fingerprint)); - Ok(()) -} - -#[test] -fn gen_key_check_params_test() { - fn fail_if_err(keyname: &str, email: &str) { - let params = gpg::KeygenParams::new(keyname, email, ""); - let results = check_params(¶ms); - match results { - Ok(_) => assert!(true), - Err(_) => assert!(false), - }; - } - - fn fail_if_ok(keyname: &str, email: &str) { - let params = gpg::KeygenParams::new(keyname, email, ""); - let results = check_params(¶ms); - match results { - Ok(_) => assert!(false), - Err(_) => assert!(true), - }; - } - - // validate key names - fail_if_ok("", "foo@bar"); - fail_if_ok("a", "foo@bar"); - fail_if_err("abcde", "foo@bar"); - - // validate email addresses - fail_if_ok("foobar", ""); - fail_if_ok("foobar", "a"); - fail_if_ok("foobar", "foo@"); - fail_if_err("foobar", "foo@bar"); -} - -#[test] -fn gen_service_key_email_test() { - assert_eq!("foobar.default@bldr", - gen_service_key_email("foobar", "default")); -} - -#[test] -fn gen_service_key_name_test() { - assert_eq!("bldr_foobar.default", - gen_service_key_name("foobar", "default")); -} - -#[test] -fn gen_service_key_name_test_normalized() { - assert_eq!("bldr_foobar.default", - gen_service_key_name("bldr_foobar.default", "default")); -} - -#[test] -fn gen_user_key_name_test() { - assert_eq!("bldr_foobar", gen_user_key_name("foobar")); - -} - -#[test] -fn gen_user_key_name_test_normalized() { - assert_eq!("bldr_foobar", gen_user_key_name("bldr_foobar")); - -} diff --git a/components/sup/src/command/mod.rs b/components/sup/src/command/mod.rs index 02b1b0597d..a5a53e3269 100644 --- a/components/sup/src/command/mod.rs +++ b/components/sup/src/command/mod.rs @@ -12,5 +12,4 @@ //! CLI. pub mod start; -pub mod key; pub mod configure; diff --git a/components/sup/src/config.rs b/components/sup/src/config.rs index fde4c0cab9..67f26a69f0 100644 --- a/components/sup/src/config.rs +++ b/components/sup/src/config.rs @@ -28,13 +28,6 @@ static LOGKEY: &'static str = "CFG"; pub enum Command { Config, Start, - ImportKey, - ExportKey, - GenerateUserKey, - GenerateServiceKey, - ListKeys, - Encrypt, - Decrypt, Shell, } @@ -64,13 +57,6 @@ impl FromStr for Command { fn from_str(s: &str) -> Result { match s { "config" => Ok(Command::Config), - "decrypt" => Ok(Command::Decrypt), - "encrypt" => Ok(Command::Encrypt), - "export-key" => Ok(Command::ExportKey), - "generate-service-key" => Ok(Command::GenerateServiceKey), - "generate-user-key" => Ok(Command::GenerateUserKey), - "import-key" => Ok(Command::ImportKey), - "list-keys" => Ok(Command::ListKeys), "sh" => Ok(Command::Shell), "start" => Ok(Command::Start), _ => Err(sup_error!(Error::CommandNotImplemented)), diff --git a/components/sup/src/error.rs b/components/sup/src/error.rs index 18b9e2ce47..f5fb1f1526 100644 --- a/components/sup/src/error.rs +++ b/components/sup/src/error.rs @@ -41,7 +41,6 @@ use std::str; use hcore::{self, package}; use common; use depot_client; -use gpgme; use uuid; use wonder::actor; use ansi_term::Colour::Red; @@ -94,7 +93,6 @@ pub enum Error { DbInvalidPath, DepotClient(depot_client::Error), FileNotFound(String), - GPGError(gpgme::Error), HabitatCommon(common::Error), HabitatCore(hcore::Error), HealthCheck(String), @@ -143,7 +141,6 @@ impl fmt::Display for SupError { Error::DbInvalidPath => format!("Invalid filepath to internal datastore"), Error::DepotClient(ref err) => format!("{}", err), Error::FileNotFound(ref e) => format!("File not found at: {}", e), - Error::GPGError(ref e) => format!("{}", e), Error::HealthCheck(ref e) => format!("Health Check failed: {}", e), Error::HookFailed(ref t, ref e, ref o) => { format!("Hook failed to run: {}, {}, {}", t, e, o) @@ -224,7 +221,6 @@ impl error::Error for SupError { Error::DbInvalidPath => "A bad filepath was provided for an internal datastore", Error::DepotClient(ref err) => err.description(), Error::FileNotFound(_) => "File not found", - Error::GPGError(_) => "gpgme error", Error::HealthCheck(_) => "Health Check returned an unknown status code", Error::HookFailed(_, _, _) => "Hook failed to run", Error::HTTP(_) => "Received an HTTP error", @@ -332,12 +328,6 @@ impl From for SupError { } } -impl From for SupError { - fn from(err: gpgme::Error) -> SupError { - sup_error!(Error::GPGError(err)) - } -} - impl From for SupError { fn from(err: actor::ActorError) -> Self { sup_error!(Error::ActorError(err)) diff --git a/components/sup/src/lib.rs b/components/sup/src/lib.rs index 39464f9df4..3284b78a80 100644 --- a/components/sup/src/lib.rs +++ b/components/sup/src/lib.rs @@ -45,7 +45,6 @@ extern crate mustache; extern crate rustc_serialize; extern crate toml; extern crate ansi_term; -extern crate gpgme; extern crate regex; extern crate libc; extern crate url; diff --git a/components/sup/src/main.rs b/components/sup/src/main.rs index 8374af0849..d32829cfad 100644 --- a/components/sup/src/main.rs +++ b/components/sup/src/main.rs @@ -24,7 +24,7 @@ use std::result; use std::str::FromStr; use ansi_term::Colour::Yellow; -use clap::{App, AppSettings, Arg, ArgGroup, ArgMatches, SubCommand}; +use clap::{App, AppSettings, Arg, ArgMatches, SubCommand}; use hcore::package::PackageIdent; use hcore::fs; @@ -166,18 +166,6 @@ fn main() { .takes_value(true) .help("The service group; shared config and topology [default: default].") }; - let arg_infile = || { - Arg::with_name("infile") - .long("infile") - .takes_value(true) - .help("Input filename") - }; - let arg_outfile = || { - Arg::with_name("outfile") - .long("outfile") - .takes_value(true) - .help("Output filename") - }; let arg_strategy = || { Arg::with_name("strategy") .long("strategy") @@ -220,92 +208,6 @@ fn main() { .long("gossip-permanent") .help("If this service is a permanent gossip peer")); let sub_sh = SubCommand::with_name("sh").about("Start an interactive shell"); - let sub_generate_user_key = SubCommand::with_name("generate-user-key") - .about("Generate a Habitat user key") - .arg(Arg::with_name("user") - .required(true) - .long("user") - .takes_value(true) - .help("Name of user key")) - .arg(Arg::with_name("password") - .required(false) - .long("password") - .takes_value(true) - .help("User key password")) - .arg(Arg::with_name("email") - .required(true) - .long("email") - .takes_value(true) - .help("User key email address")) - .arg(Arg::with_name("expire-days") - .long("expire-days") - .takes_value(true) - .value_name("expire-days") - .help("Number of days before a key expires")); - let sub_generate_service_key = SubCommand::with_name("generate-service-key") - .about("Generate a Habitat service key") - .arg(Arg::with_name("service") - .required(true) - .takes_value(true) - .help("Name of service key")) - .arg(arg_group()) - .arg(Arg::with_name("expire-days") - .long("expire-days") - .takes_value(true) - .value_name("expire-days") - .help("Number of days before a key expires")); - let sub_encrypt = SubCommand::with_name("encrypt") - .about("Encrypt and sign a message with a service as the recipient") - .arg(Arg::with_name("user") - .required(true) - .long("user") - .takes_value(true) - .help("Name of user key")) - .arg(Arg::with_name("service") - .required(true) - .long("service") - .takes_value(true) - .help("Name of service key")) - .arg(arg_infile().required(true)) - .arg(arg_outfile().required(true)) - .arg(Arg::with_name("password") - .required(false) - .long("password") - .takes_value(true) - .help("User key password")) - .arg(arg_group()); - let sub_decrypt = SubCommand::with_name("decrypt") - .about("Decrypt and verify a message") - .arg(arg_infile().required(true)) - .arg(arg_outfile().required(true)); - let sub_import_key = SubCommand::with_name("import-key") - .about("Import a public Habitat key") - .arg(arg_infile()) - .arg(Arg::with_name("key") - .long("key") - .takes_value(true) - .help("Public key filename") - .requires("url")) - .arg(arg_url()) - .group(ArgGroup::with_name("input-method") - .required(true) - .args(&["infile", "key"])); - let sub_export_key = SubCommand::with_name("export-key") - .about("Export a public Habitat key") - .arg(Arg::with_name("user") - .long("user") - .takes_value(true) - .help("Name of user key")) - .arg(Arg::with_name("service") - .long("service") - .takes_value(true) - .help("Name of service key")) - .group(ArgGroup::with_name("user-or-service-key") - .required(true) - .args(&["user", "service"])) - .arg(arg_outfile().required(true)) - .arg(arg_group()); - let sub_list_keys = SubCommand::with_name("list-keys").about("List user and service keys"); let sub_config = SubCommand::with_name("config") .about("Print the default.toml for a given package") .arg(Arg::with_name("package") @@ -326,13 +228,6 @@ fn main() { .help("Turn ANSI color off :(")) .subcommand(sub_start) .subcommand(sub_sh) - .subcommand(sub_generate_user_key) - .subcommand(sub_generate_service_key) - .subcommand(sub_encrypt) - .subcommand(sub_decrypt) - .subcommand(sub_import_key) - .subcommand(sub_export_key) - .subcommand(sub_list_keys) .subcommand(sub_config); let matches = args.get_matches(); @@ -349,13 +244,6 @@ fn main() { let result = match config.command() { Command::Shell => shell(&config), Command::Config => configure(&config), - Command::Decrypt => decrypt(&config), - Command::Encrypt => encrypt(&config), - Command::ExportKey => export_key(&config), - Command::GenerateServiceKey => generate_service_key(&config), - Command::GenerateUserKey => generate_user_key(&config), - Command::ImportKey => import_key(&config), - Command::ListKeys => list_keys(&config), Command::Start => start(&config), }; @@ -404,62 +292,3 @@ fn start(config: &Config) -> Result<()> { Ok(()) } -/// Import a key -fn import_key(config: &Config) -> Result<()> { - outputln!("Importing key {}", Yellow.bold().paint(config.key())); - try!(key::import(&config)); - outputln!("Finished importing key"); - Ok(()) -} - -/// Export a key -fn export_key(config: &Config) -> Result<()> { - outputln!("Exporting key {}", Yellow.bold().paint(config.key())); - try!(key::export(&config)); - outputln!("Finished exporting key"); - Ok(()) -} - -/// Generate a key for a user -fn generate_user_key(config: &Config) -> Result<()> { - outputln!("Generate user key for {}", - Yellow.bold().paint(config.key())); - try!(key::generate_user_key(&config)); - outputln!("Finished generating user key for {}", - Yellow.bold().paint(config.key())); - Ok(()) -} - -/// Generate a key for a service -fn generate_service_key(config: &Config) -> Result<()> { - outputln!("Generate service key for {}", - Yellow.bold().paint(config.key())); - try!(key::generate_service_key(&config)); - outputln!("Finished generating service key for {}", - Yellow.bold().paint(config.key())); - Ok(()) -} - -/// List managed gpg keys -fn list_keys(config: &Config) -> Result<()> { - outputln!("Listing keys"); - try!(key::list(&config)); - outputln!("Finished listing keys"); - Ok(()) -} - -/// Encrypt a file -fn encrypt(config: &Config) -> Result<()> { - outputln!("Encrypting"); - try!(key::encrypt_and_sign(&config)); - outputln!("Finished encrypting"); - Ok(()) -} - -/// Decrypt a file -fn decrypt(config: &Config) -> Result<()> { - outputln!("Decrypting"); - try!(key::decrypt_and_verify(&config)); - outputln!("Finished decrypting"); - Ok(()) -} diff --git a/components/sup/tests/bldr_build/mod.rs b/components/sup/tests/bldr_build/mod.rs index 681aac7779..0cbdf74f0c 100644 --- a/components/sup/tests/bldr_build/mod.rs +++ b/components/sup/tests/bldr_build/mod.rs @@ -13,7 +13,6 @@ use setup; #[test] fn builds_a_service() { - setup::gpg_import(); let mut simple_service = match util::command::plan_build(&util::path::fixture_as_string("bldr_build")) { Ok(cmd) => cmd, diff --git a/components/sup/tests/fixtures/chef-private.gpg b/components/sup/tests/fixtures/chef-private.gpg deleted file mode 100644 index 09837ac8af..0000000000 --- a/components/sup/tests/fixtures/chef-private.gpg +++ /dev/null @@ -1,105 +0,0 @@ ------BEGIN PGP PRIVATE KEY BLOCK----- -Version: GnuPG v1 - -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 -=PawG ------END PGP PRIVATE KEY BLOCK----- diff --git a/components/sup/tests/fixtures/chef-public.gpg b/components/sup/tests/fixtures/chef-public.gpg deleted file mode 100644 index 94889da351..0000000000 --- a/components/sup/tests/fixtures/chef-public.gpg +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1 - -mQINBFVTAAcBEADGgy8A1ZaZ02e9pQCYmi/IyKygrVx2DHs4l6rD55XGkjdbwN8U -m+R572jaYy+bX4wFp/9zJNqoewuqbRqTJRUpONJoHiAe3ieO20z5zicTWDMxQz3N -0excrEPbpl9f90lcGqS0ZDeMRWyZ0WHaUmM56drtGMRceyJSWdWzq4i8SLOHzz0v -74m/1WoO05ntjFuixSZoLEB6NmN+25vx1yOQIuCZGOEktri++5eOmz1U3T2tiCYr -46lXX435h1OuOyYBpFHJvMZb92EWYB1RM/267wVRnT54BVhBBhNPoe6cV9H0TraK -8UZyXlYPWGrWeJ81Dr+YnRrIZ2gRU44SiTmu3JmvJpSyuf6abO+dWNJOKfa62XaI -C82BVFVtO/ezPcRJDi1O4h7a8+3g/nfFLLqPgLVlqJ5h3PqLSrUj4cAkjaoQ7+oy -IxNSl2NC4H1zFReUlAwMMCrqJLGxlpE/BhiXPxpwDnbR8arwotlhdmgc7jeeHaEG -B918XlrkZmXyxCUC0naVyei8VUDmP85Ac6k3fnIUodYliaa02/QbULbtLZDcO2bp -AKend8VCU4utWHLlLPHXb/PzjRGLXqB4ComnAxghLzA2fpN4HU2YfZGCIA9PKeHq -G1GOb1Bg6IEnlFhHEN51XJyhkwV/pxNPzUEQsVo/C237+r7BwLi8YoLfpwARAQAB -tCBDaGVmIFNvZnR3YXJlIDxzZWN1cml0eUBjaGVmLmlvPokCOAQTAQIAIgUCVVMA -BwIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ+671tjhT2mtAlw/8Dizn -EohB/n77zGdJTcXwEWV4Kp7f8JeVd0RLkovKbvhAh/paP4XchxKCf4pjpoElmhkV -QAed0UdmzdlmP2WLkyjR22pJ9/CnL0i6J8OhfwWEHAai4xPhcCRtRHOl1NfKquj9 -/3DRfK4BiyKz3AQ57ijoNVeCEMGWOnGuwNtynT2dwyoz+jd5l/hueMya6uQPGQm+ -7LP/0/zBAi9eUprrdDVgBCD8nXbaGcm5W3Dvqp4pA29VLYyEkKXoAe1Zq3sOLEdP -d2VgbWx+vvaBJ15fjVcX1p5Y1UdLz2N6b18/HS+NNvxQo0dR6X+5hQZbxhhlhq7I -cqAMqj+MkOq+s0BhG5QD+egzMRMH/g/yLOYRO7CWu4rVc0m4t9dlCDNacdFp4HGC -dIWxJM1ux1QsKMRlZQvo9kR8Gl6jNhfGJaNGfqk+fP+3jZgE2RulBcUK46Pob5Ei -YSEqYL1bFt9GPDwL9dKQ+5Pmhop88d5I/xLort+VgwollHf9FyyUKadfWu9PhLV7 -PgZBWqp8nFhGssv5Vj8RCFzN9U4XXPr4U/UhXoukU0UblS3k7FAwy3zmLiVnb1E9 -PNRDlFeQajq5Lag+uI51sAemu6y/kY5AlxUxrePUT/fUF4SlnL0AqFOlHaFiB0r3 -+Z4N90x9Ckw2Mcx65cn1vCS3tU1/x+ma70Qm6se5Ag0EVVMABwEQALOhvhutJ/Q9 -lXktWmVdsmR2fQXBNZFjAwnOssFjBQa/WIasWNAoJ2J9Q++jKp9gqd9e36RsDHTX -4J9Abs1lW9vqogQZui3b+rWHnmBm90/FJuRUnlK5Wf3EkqJDKQfRLuC5T1uIhZh/ -M+upB9fqqTSJjVgktI6Zt1Tm5iSeJObiRzjHBtr3Pd+dQqBKwmXO7XsDbYCUCNLC -LkTH3/2jjzp8HdJiviVAhYWl62dNf4it9C5bKMrWGzWoSldQZlrKM8HkkeqJFkfi -CDq8/rQMCWWHFh3aRM3pawmyYnFrwlPzwvya5WcXKMXZqz8YfTvz3ilE/ElMR8/u -SoTvtHqZ1OKngkxgQzfcZmX7FeRsYKqScMWvWdOj48nAK8ixTwi5JBW4NMiqnokO -mh5ConTQ5vSjKTN6RwfdFq7xEobN6m5Qui67jGPOmv3DE6Muj4bFCsZfrs488dov -VFmgt5ZHW36k+L7e710o6jSHsL/TncmcnRuLWeY99gLmSb54YPuI8MIiYlzwUi36 -JxsyPrTh7bpPotNlh2403D1zkwevn4rWFLRt7j4KoBeSSCS1go6T6RoRsuXnlXcq -u5oXVy+Cja/zP1jZya5xwh359rAVxw3491+b2BnD/GTvtjPWSC27DjUsjj+rDTmr -CPGJ+Ak6VD8pLELd+XJgyGqEzzBynTEbABEBAAGJAh8EGAECAAkFAlVTAAcCGwwA -CgkQ+671tjhT2mvcaxAAkjpenhEopJ+a6d4yWaovMvnSK9a+roQoCBGkK79w4h+i -Ggiql/oKmWCle0GmdGEpM3GCflsdEHkac4pgda/GYotOZlcPcSD4LCG1jho7mkwb -DlORluvyQTlOVQefa/hwvCXszza0UO0ddg44q3l2z1nat9A4A7ipaHJIoesc0K3O -LX2wdifBxDP/HfzGeb50UZmBl4KQ66SzbgkIeHeamquAjk9XaWY6TFEJd5THMxIu -59bzUHogGsKJVySdGzT9Mr2AM5ufZXfxKGAhf70Rw/aCJaSV/W5XjGwSI2VjRzHW -fbSM6p0FmuIOubEOaJr0gZbFFQXn8a0UlHhonlIK0dYD84Qoh8dy/MIrPSJZaY/d -ZGa6SuFSMX4WKXLtjRAIMAOwume5zIoa+fKk8yIrpDOtQiPwjISccTsryED6b5fa -Oqdzp/9slD3VmcFXwmtRYnMumiwQUclCt9luDRdDXsdyXKOLq+xpwTTpsqC8U8V8 -wDLoLcNewFll/vUelFPVgOFAQhvWYraTVlk3s204tVkX/CinqdciKEnfpl7coIV5 -g8o77kTlJtNZsmzYYNG3Tm39cNKf/NWx18HsRTZlMTJaGU4uEsqz1/sqh+vj8JtV -M0IYc2VzulqDMdX/VGgs52R8wKbqChCDoGLrmTt/HkuDXgZv2whKxwxvfsSajPc= -=kz3I ------END PGP PUBLIC KEY BLOCK----- diff --git a/components/sup/tests/fixtures/habitat-20160408144426.pub b/components/sup/tests/fixtures/habitat-20160408144426.pub new file mode 100644 index 0000000000..b7c2834a71 --- /dev/null +++ b/components/sup/tests/fixtures/habitat-20160408144426.pub @@ -0,0 +1 @@ +EJlmtyLf9F3uwS1OaS/86m+txiJ60l2MUpFM5m4UXVk= \ No newline at end of file diff --git a/components/sup/tests/fixtures/habitat-20160408144426.sig.key b/components/sup/tests/fixtures/habitat-20160408144426.sig.key new file mode 100644 index 0000000000..c42f168f76 --- /dev/null +++ b/components/sup/tests/fixtures/habitat-20160408144426.sig.key @@ -0,0 +1 @@ +5G3ZGVO3V8hkjVr5nPU5MXtoM1X+iB4e8Y0Voc3cDuIQmWa3It/0Xe7BLU5pL/zqb63GInrSXYxSkUzmbhRdWQ== \ No newline at end of file diff --git a/components/sup/tests/functional.rs b/components/sup/tests/functional.rs index 67aaa017b9..ff45e30c2c 100644 --- a/components/sup/tests/functional.rs +++ b/components/sup/tests/functional.rs @@ -18,68 +18,22 @@ extern crate rustc_serialize; pub mod util; + mod setup { use std::sync::{Once, ONCE_INIT}; - use tempdir::TempDir; use std::process::Command; use std::collections::HashMap; use std::str::FromStr; + use std::env; + use tempdir::TempDir; use hcore::package::PackageIdent; use hcore::url; use common; use util; - pub fn gpg_import() { - static ONCE: Once = ONCE_INIT; - ONCE.call_once(|| { - let mut gpg = match util::command::studio_run("gpg", - &["--import", - &util::path::fixture_as_string("chef-private.gpg")]) { - Ok(cmd) => cmd, - Err(e) => panic!("{:?}", e), - }; - gpg.wait_with_output(); - if !gpg.status.unwrap().success() { - match gpg.stderr { - Some(stderr) => { - use regex::Regex; - let re = Regex::new("already in secret keyring").unwrap(); - if !re.is_match(&stderr) { - panic!("Failed to import gpg keys"); - } - } - None => panic!("Failed to import gpg keys") - } - } - }); - } - - pub fn gpg_import_with_gpg_cache(cache_dir: &str) { - static ONCE: Once = ONCE_INIT; - - let mut env: HashMap<&str, &str> = HashMap::new(); - env.insert("HAB_CACHE_GPG_PATH", cache_dir); - - ONCE.call_once(|| { - let mut gpg = - match util::command::run_with_env("gpg", - &["--import", - &util::path::fixture_as_string("chef-private.gpg")], - &env) { - Ok(cmd) => cmd, - Err(e) => panic!("{:?}", e), - }; - gpg.wait_with_output(); - }); - } - - pub fn install_rngd() { - static ONCE: Once = ONCE_INIT; - ONCE.call_once(|| { - let rpi = PackageIdent::from_str("chef/rngd").unwrap(); - common::command::package::install::from_url(&url::DEFAULT_DEPOT_URL, &rpi).unwrap(); - }); + pub fn origin_setup() { + env::set_var("HABITAT_KEY_CACHE", util::path::key_cache()); } pub fn simple_service() { @@ -142,17 +96,6 @@ mod setup { }); } - pub fn key_install() { - static ONCE: Once = ONCE_INIT; - ONCE.call_once(|| { - let mut cmd = match util::command::sup(&["key", - &util::path::fixture_as_string("chef-public.asc")]) { - Ok(cmd) => cmd, - Err(e) => panic!("{:?}", e), - }; - cmd.wait_with_output(); - }); - } } @@ -254,179 +197,6 @@ macro_rules! assert_file_exists_in_studio { } } -mod key_utils { - use util::command; - use uuid::Uuid; - - pub fn export_service_key(key: &str, outfile: &str, cache: &str, group: Option<&str>) { - let mut export = match group { - Some(g) => { - command::sup_with_test_gpg_cache(&["export-key", - "--service", - &key, - "--outfile", - &outfile, - "--group", - &g], - &cache) - .unwrap() - } - None => { - command::sup_with_test_gpg_cache(&["export-key", - "--service", - &key, - "--outfile", - &outfile], - &cache) - .unwrap() - } - - }; - export.wait_with_output(); - assert_cmd_exit_code!(export, [0]); - println!("{}", export.stdout()); - } - - pub fn export_user_key(key: &str, outfile: &str, cache: &str) { - let mut export = command::sup_with_test_gpg_cache(&["export-key", - "--user", - &key, - "--outfile", - &outfile], - &cache) - .unwrap(); - export.wait_with_output(); - assert_cmd_exit_code!(export, [0]); - println!("{}", export.stdout()); - } - - pub fn import(exported_user_key: &str, cache: &str) { - let mut import = command::sup_with_test_gpg_cache(&["import-key", - "--infile", - &exported_user_key], - &cache) - .unwrap(); - import.wait_with_output(); - assert_cmd_exit_code!(import, [0]); - println!("{}", import.stdout()); - } - - - pub fn encrypt(user: &str, - service: &str, - file_to_encrypt: &str, - encrypted_file: &str, - cache: &str, - group: Option<&str>) { - let mut encrypt = match group { - Some(g) => { - command::sup_with_test_gpg_cache(&["encrypt", - "--user", - &user, - "--service", - &service, - "--infile", - &file_to_encrypt, - "--outfile", - &encrypted_file, - "--password", - "password", - "--group", - g], - &cache) - .unwrap() - } - None => { - command::sup_with_test_gpg_cache(&["encrypt", - "--user", - &user, - "--service", - &service, - "--infile", - &file_to_encrypt, - "--outfile", - &encrypted_file, - "--password", - "password"], - &cache) - .unwrap() - } - - }; - encrypt.wait_with_output(); - println!("{}", encrypt.stdout()); - assert_cmd_exit_code!(encrypt, [0]); - assert_regex!(encrypt.stdout(), r".*Finished encrypting.*"); - } - - - pub fn decrypt(encrypted_file: &str, decrypted_file: &str, cache: &str, expected_status: i32) { - // try to decrypt a file that's not meant for me - let mut decrypt = command::sup_with_test_gpg_cache(&["decrypt", - "--infile", - &encrypted_file, - "--outfile", - &decrypted_file], - &cache) - .unwrap(); - decrypt.wait_with_output(); - println!("{}", decrypt.stdout()); - assert_cmd_exit_code!(decrypt, [expected_status]); - } - - pub fn list_keys(cache: &str, output_search: &str) { - let mut list_keys = command::sup_with_test_gpg_cache(&["list-keys"], &cache).unwrap(); - list_keys.wait_with_output(); - assert_regex!(list_keys.stdout(), output_search); - println!("{}", list_keys.stdout()); - } - - /// generate user and service keys w/ a given path - pub fn make_user_and_service(cache_dir: &str, group: Option<&str>) -> (String, String) { - let user_uuid = Uuid::new_v4().to_simple_string(); - let service_uuid = Uuid::new_v4().to_simple_string(); - - // generate a test user - let mut generate_user = command::sup_with_test_gpg_cache(&["generate-user-key", - "--user", - &user_uuid, - "--password", - "password", - "--email", - "email@chucktesta", - "--expire-days=10"], - cache_dir) - .unwrap(); - generate_user.wait_with_output(); - println!("{}", generate_user.stdout()); - assert_cmd_exit_code!(generate_user, [0]); - assert_regex!(generate_user.stdout(), r".*Fingerprint.*"); - - let mut generate_service = match group { - Some(g) => { - command::sup_with_test_gpg_cache(&["generate-service-key", - &service_uuid, - "--group", - &g], - cache_dir) - .unwrap() - } - None => { - command::sup_with_test_gpg_cache(&["generate-service-key", &service_uuid], - cache_dir) - .unwrap() - } - }; - generate_service.wait_with_output(); - assert_cmd_exit_code!(generate_service, [0]); - assert_regex!(generate_service.stdout(), r".*Fingerprint.*"); - (user_uuid, service_uuid) - } - - -} - - // Include the actual test modules here! pub mod bldr_build; pub mod sup_tests; diff --git a/components/sup/tests/sup_tests/gossip.rs b/components/sup/tests/sup_tests/gossip.rs index f8ef90be66..8136cbc763 100644 --- a/components/sup/tests/sup_tests/gossip.rs +++ b/components/sup/tests/sup_tests/gossip.rs @@ -11,7 +11,7 @@ use util::supervisor::Supervisor; // Start two supervisors, and make sure they see each other #[test] fn two_supervisors_link() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service_gossip(); let sup_a = Supervisor::new(); @@ -24,7 +24,7 @@ fn two_supervisors_link() { // Start two supervisors, stop one, make sure they see the failure #[test] fn two_supervisors_detect_failure() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service_gossip(); let sup_a = Supervisor::new(); @@ -46,7 +46,7 @@ fn two_supervisors_detect_failure() { // see the other two members, even though they were not provided initially. #[test] fn members_are_gossiped() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service_gossip(); let sup_a = Supervisor::new(); @@ -65,7 +65,7 @@ fn members_are_gossiped() { // as anything but alive, confirming they are routing their gossip through b. #[test] fn routes_around_failure() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service_gossip(); let sup_a = Supervisor::new(); @@ -89,7 +89,7 @@ fn routes_around_failure() { // its incarnation and shares its Alive rumor. A and C then see B as alive again. #[test] fn incarnation_updates_on_suspicion() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service_gossip(); let sup_a = Supervisor::new(); @@ -125,7 +125,7 @@ fn incarnation_updates_on_suspicion() { // their incarnation and are then marked alive. #[test] fn ressurection_of_permanent_members() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service_gossip(); let sup_a = Supervisor::new_with_permanent(); @@ -159,7 +159,7 @@ fn ressurection_of_permanent_members() { // that never lands - and you wind up isolated. #[test] fn isolated_members_find_a_way_to_rejoin() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service_gossip(); let sup_a = Supervisor::new(); diff --git a/components/sup/tests/sup_tests/key.rs b/components/sup/tests/sup_tests/key.rs index bc71c22503..2deeaa2c5f 100644 --- a/components/sup/tests/sup_tests/key.rs +++ b/components/sup/tests/sup_tests/key.rs @@ -13,17 +13,20 @@ use std::env; /// kt_ = "key test" -/// run all gpg tests in their own cache so they +/// run all crypto tests in their own cache so they /// don't leave test certs behind etc +/* fn gen_test_gpg_cache() -> String { format!("/tmp/{}", Uuid::new_v4().to_simple_string()) } +*/ #[ignore] #[test] // TODO fn kt_upload_a_key_and_install_it() { - setup::install_rngd(); - setup::gpg_import(); + /* + * DP TODO: GPG -> NaCl + setup::origin_setup(); setup::simple_service(); let d = docker::depot("test/simple_service"); let ipaddress = d.ipaddress(); @@ -43,421 +46,14 @@ fn kt_upload_a_key_and_install_it() { .unwrap(); install.wait_with_output(); assert_cmd_exit_code!(install, [0]); + */ } -fn gpg_test_setup() -> String { - setup::install_rngd(); - let gpg_cache = gen_test_gpg_cache(); - setup::gpg_import_with_gpg_cache(&gpg_cache); - gpg_cache -} - -#[test] -fn kt_generate_service_key() { - // also tests list-keys - let gpg_cache = gpg_test_setup(); - - let test_uuid = Uuid::new_v4().to_simple_string(); - let mut generate = command::sup_with_test_gpg_cache(&["generate-service-key", &test_uuid], - &gpg_cache) - .unwrap(); - - generate.wait_with_output(); - assert_cmd_exit_code!(generate, [0]); - assert_regex!(generate.stdout(), r".*Fingerprint.*"); - - // check to see if the key is in the output - let mut listkeys = command::sup_with_test_gpg_cache(&["list-keys"], &gpg_cache).unwrap(); - listkeys.wait_with_output(); - - let re_string = format!(".*{}.*", test_uuid); - assert_cmd_exit_code!(listkeys, [0]); - assert_regex!(listkeys.stdout(), &re_string); -} - - -#[test] -fn kt_generate_service_key_with_bldr_prefix() { - // also tests list-keys - let gpg_cache = gpg_test_setup(); - - let test_uuid = Uuid::new_v4().to_simple_string(); - let test_uuid_with_prefix = "bldr_".to_string() + &test_uuid; - - let mut generate = command::sup_with_test_gpg_cache(&["generate-service-key", &test_uuid], - &gpg_cache) - .unwrap(); - - generate.wait_with_output(); - assert_cmd_exit_code!(generate, [0]); - - { - let re = format!(".*{}.*", test_uuid_with_prefix); - println!("Looking for \n{}\n", re); - assert_regex!(generate.stdout(), &re); - } - - { - let re = format!(".*Successfully generated service key.*"); - println!("Looking for \n{}\n", re); - assert_regex!(generate.stdout(), &re); - } - - - - // check to see if the key is in the output - let mut listkeys = command::sup_with_test_gpg_cache(&["list-keys"], &gpg_cache).unwrap(); - listkeys.wait_with_output(); - - let re_string = format!(".*{}.*", test_uuid); - assert_cmd_exit_code!(listkeys, [0]); - assert_regex!(listkeys.stdout(), &re_string); -} - - - -#[test] -fn kt_generate_service_key_with_group() { - // pass in --group as "foobar123" - // also tests list-keys - let gpg_cache = gpg_test_setup(); - - let test_uuid = Uuid::new_v4().to_simple_string(); - let mut generate = command::sup_with_test_gpg_cache(&["generate-service-key", - &test_uuid, - "--group=foobar123"], - &gpg_cache) - .unwrap(); - - generate.wait_with_output(); - assert_cmd_exit_code!(generate, [0]); - assert_regex!(generate.stdout(), r".*Fingerprint.*"); - - // check to see if the key is in the output - let mut listkeys = command::sup_with_test_gpg_cache(&["list-keys"], &gpg_cache).unwrap(); - listkeys.wait_with_output(); - let re_string = format!(".*{}\\.foobar123.*", test_uuid); - assert_cmd_exit_code!(listkeys, [0]); - assert_regex!(listkeys.stdout(), &re_string); -} - - -#[test] -fn kt_generate_service_key_with_expiration() { - // also tests list-keys - let gpg_cache = gpg_test_setup(); - let test_uuid = Uuid::new_v4().to_simple_string(); - let mut generate = command::sup_with_test_gpg_cache(&["generate-service-key", - &test_uuid, - "--expire-days=10"], - &gpg_cache) - .unwrap(); - - generate.wait_with_output(); - assert_cmd_exit_code!(generate, [0]); - assert_regex!(generate.stdout(), r".*Fingerprint.*"); - - // check to see if the key is in the output - let mut listkeys = command::sup_with_test_gpg_cache(&["list-keys"], &gpg_cache).unwrap(); - listkeys.wait_with_output(); - - let re_string = format!(".*{}.*", test_uuid); - assert_cmd_exit_code!(listkeys, [0]); - assert_regex!(listkeys.stdout(), &re_string); -} - -#[test] -fn kt_generate_service_key_with_expiration_and_group() { - // also tests list-keys - let gpg_cache = gpg_test_setup(); - let test_uuid = Uuid::new_v4().to_simple_string(); - let mut generate = command::sup_with_test_gpg_cache(&["generate-service-key", - &test_uuid, - "--expire-days=10", - "--group=foobar123"], - &gpg_cache) - .unwrap(); - - generate.wait_with_output(); - assert_cmd_exit_code!(generate, [0]); - assert_regex!(generate.stdout(), r".*Fingerprint.*"); - - // check to see if the key is in the output - let mut listkeys = command::sup_with_test_gpg_cache(&["list-keys"], &gpg_cache).unwrap(); - listkeys.wait_with_output(); - - let re_string = format!(".*{}\\.foobar123.*", test_uuid); - assert_cmd_exit_code!(listkeys, [0]); - assert_regex!(listkeys.stdout(), &re_string); -} - - - -#[test] -fn kt_generate_user_key() { - // also tests list-keys - let gpg_cache = gpg_test_setup(); - let test_uuid = Uuid::new_v4().to_simple_string(); - let mut generate = command::sup_with_test_gpg_cache(&["generate-user-key", - "--user", - &test_uuid, - "--password", - "password", - "--email", - "email@bldrtest"], - &gpg_cache) - .unwrap(); - - generate.wait_with_output(); - assert_cmd_exit_code!(generate, [0]); - assert_regex!(generate.stdout(), r".*Fingerprint.*"); - - // check to see if the key is in the output - let mut listkeys = command::sup_with_test_gpg_cache(&["list-keys"], &gpg_cache).unwrap(); - listkeys.wait_with_output(); - - let re_string = format!(".*{}.*", test_uuid); - assert_cmd_exit_code!(listkeys, [0]); - assert_regex!(listkeys.stdout(), &re_string); -} - -#[test] -fn kt_generate_user_key_with_expiration() { - // also tests list-keys - let gpg_cache = gpg_test_setup(); - let test_uuid = Uuid::new_v4().to_simple_string(); - let mut generate = command::sup_with_test_gpg_cache(&["generate-user-key", - "--user", - &test_uuid, - "--password", - "password", - "--email", - "email@bldrtest", - "--expire-days=10"], - &gpg_cache) - .unwrap(); - - generate.wait_with_output(); - assert_cmd_exit_code!(generate, [0]); - assert_regex!(generate.stdout(), r".*Fingerprint.*"); - - // check to see if the key is in the output - let mut listkeys = command::sup_with_test_gpg_cache(&["list-keys"], &gpg_cache).unwrap(); - listkeys.wait_with_output(); - - let re_string = format!(".*{}.*", test_uuid); - assert_cmd_exit_code!(listkeys, [0]); - assert_regex!(listkeys.stdout(), &re_string); -} - -#[test] -fn kt_generate_user_key_with_bldr_prefix() { - // also tests list-keys - let gpg_cache = gpg_test_setup(); - let test_uuid = Uuid::new_v4().to_simple_string(); - let test_uuid_with_prefix = "bldr_".to_string() + &test_uuid; - let mut generate = command::sup_with_test_gpg_cache(&["generate-user-key", - "--user", - &test_uuid_with_prefix, - "--password", - "password", - "--email", - "email@bldrtest", - "--expire-days=10"], - &gpg_cache) - .unwrap(); - - generate.wait_with_output(); - assert_cmd_exit_code!(generate, [0]); - { - let re = format!(".*{}.*", test_uuid_with_prefix); - println!("Looking for \n{}\n", re); - assert_regex!(generate.stdout(), &re); - } - - { - let re = format!(".*Successfully generated user key.*"); - println!("Looking for \n{}\n", re); - assert_regex!(generate.stdout(), &re); - } - - - // check to see if the key is in the output - let mut listkeys = command::sup_with_test_gpg_cache(&["list-keys"], &gpg_cache).unwrap(); - listkeys.wait_with_output(); - - let re_string = format!(".*{}.*", test_uuid); - assert_cmd_exit_code!(listkeys, [0]); - assert_regex!(listkeys.stdout(), &re_string); -} - - +/* +>>>>>>> wip fn mk_tmp_filename() -> String { format!("/tmp/{}", Uuid::new_v4().to_simple_string()) } +*/ - - -#[test] -fn kt_find_key() { - use hcore::gpg; - setup::install_rngd(); - - let cache_dir = gen_test_gpg_cache(); - { - // generate a test user - let mut generate_user = command::sup_with_test_gpg_cache(&["generate-user-key", - "--user", - "a", - "--password", - "password", - "--email", - "email@bldrtest", - "--expire-days=10"], - &cache_dir) - .unwrap(); - generate_user.wait_with_output(); - println!("{}", generate_user.stdout()); - assert_cmd_exit_code!(generate_user, [0]); - assert_regex!(generate_user.stdout(), r".*Fingerprint.*"); - } - - { - // generate a test user - let mut generate_user = command::sup_with_test_gpg_cache(&["generate-user-key", - "--user", - "aa", - "--password", - "password", - "--email", - "email@bldrtest", - "--expire-days=10"], - &cache_dir) - .unwrap(); - generate_user.wait_with_output(); - println!("{}", generate_user.stdout()); - assert_cmd_exit_code!(generate_user, [0]); - assert_regex!(generate_user.stdout(), r".*Fingerprint.*"); - } - - env::set_var("HAB_CACHE_GPG_PATH", cache_dir); - match gpg::find_key("bldr_a") { - Ok(result) => { - let r = result.unwrap(); - assert_eq!(1, r.user_ids().count()); - let (_, user) = r.user_ids().enumerate().next().unwrap(); - let name = user.name().unwrap(); - assert_eq!("bldr_a", name); - } - Err(e) => panic!("FAIL {:?}", e), - }; - - - match gpg::find_key("bldr_aa") { - Ok(result) => { - let r = result.unwrap(); - assert_eq!(1, r.user_ids().count()); - let (_, user) = r.user_ids().enumerate().next().unwrap(); - let name = user.name().unwrap(); - assert_eq!("bldr_aa", name); - } - Err(e) => panic!("FAIL {:?}", e), - }; - - match gpg::find_key("aaa") { - Ok(Some(_)) => assert!(false), - Ok(None) => assert!(true), - Err(_) => assert!(false), - }; - env::remove_var("HAB_CACHE_GPG_PATH"); -} - -#[test] -fn kt_end_to_end() { - // test all encryption functions with the default group - test_gpg(None); -} - -#[test] -fn kt_end_to_end_with_group() { - // test all encryption functions with a group - test_gpg(Some("testgroup")); -} - -fn test_gpg(group: Option<&str>) { - use std::io::prelude::*; - use std::fs::File; - use key_utils::*; - setup::install_rngd(); - let file_to_encrypt = mk_tmp_filename(); - let encrypted_file = mk_tmp_filename(); - let decrypted_file = mk_tmp_filename(); - - let exported_user_key = mk_tmp_filename(); - let exported_service_key = mk_tmp_filename(); - - println!("Plaintext file to encrypt: {}", file_to_encrypt); - println!("Encrypted output: {}", encrypted_file); - println!("Decrypted output: {}", decrypted_file); - println!("Exported user key: {}", exported_user_key); - println!("Exported service key: {}", exported_service_key); - - let mut f = File::create(file_to_encrypt.clone()).unwrap(); - let _res = f.write_all(b"Top secret data!\nTop secret data!!\n"); - - let gpg_cache_a = gen_test_gpg_cache(); - let gpg_cache_b = gen_test_gpg_cache(); - println!("GPG CACHE A = {}", gpg_cache_a); - println!("GPG CACHE B = {}", gpg_cache_b); - - // make a user and a service in the default group - let (ua, sa) = make_user_and_service(&gpg_cache_a, group); - let (_ub, sb) = make_user_and_service(&gpg_cache_b, group); - - // encrypt something that only GPG Cache A can decrypt - encrypt(&ua, - &sa, - &file_to_encrypt, - &encrypted_file, - &gpg_cache_a, - group); - - // we can decrypt a message that we own all keys for - decrypt(&encrypted_file, &decrypted_file, &gpg_cache_a, 0); - - - // Can gpg_cache_b read the message, even though it's not - // the recipient? This should fail (return code 1), we - // encrypted as user ua, but we need sa's private key to - // decrypt (or ua's public key to verify) - decrypt(&encrypted_file, &decrypted_file, &gpg_cache_b, 1); - - // export the service key from the B cache - export_service_key(&sb, &exported_service_key, &gpg_cache_b, group); - - // export the user key from the A cache - export_user_key(&ua, &exported_user_key, &gpg_cache_a); - - import(&exported_user_key, &gpg_cache_b); - let search_for_user = format!(".*{}.*", ua); - // do a list-keys and search for the user that was imported - list_keys(&gpg_cache_b, &search_for_user); - - import(&exported_service_key, &gpg_cache_a); - let search_for_service = format!(".*{}.*", sb); - // do a list-leys and search for the service that was imported - list_keys(&gpg_cache_a, &search_for_service); - - // encrypt a new message, this time using service B's public key - // which we have imported - encrypt(&ua, - &sb, - &file_to_encrypt, - &encrypted_file, - &gpg_cache_a, - group); - - // returns 0 :-) - decrypt(&encrypted_file, &decrypted_file, &gpg_cache_b, 0); -} diff --git a/components/sup/tests/sup_tests/start.rs b/components/sup/tests/sup_tests/start.rs index 0b61e4fce7..4a1213c0c2 100644 --- a/components/sup/tests/sup_tests/start.rs +++ b/components/sup/tests/sup_tests/start.rs @@ -13,7 +13,7 @@ use std::time::Duration; #[test] fn standalone_no_options() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service(); let d = docker::run("test/simple_service"); @@ -26,7 +26,7 @@ fn standalone_no_options() { #[ignore] #[test] fn standalone_no_options_without_config() { - setup::gpg_import(); + setup::origin_setup(); setup::fixture_service("simple_service_without_config"); let d = docker::run("test/simple_service_without_config"); @@ -42,7 +42,7 @@ fn standalone_no_options_without_config() { #[ignore] #[test] fn standalone_with_environment_config() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service(); let d = docker::run_with_env("test/simple_service", @@ -56,7 +56,7 @@ fn standalone_with_environment_config() { #[ignore] #[test] fn standalone_with_discovery_config() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service(); util::discovery::clear("config"); @@ -69,7 +69,7 @@ fn standalone_with_discovery_config() { #[ignore] #[test] fn standalone_with_discovery_config_updates() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service(); util::discovery::clear("config"); @@ -85,7 +85,7 @@ fn standalone_with_discovery_config_updates() { #[ignore] #[test] fn leader_with_discovery() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service(); util::discovery::clear("config"); diff --git a/components/sup/tests/sup_tests/topology/leader.rs b/components/sup/tests/sup_tests/topology/leader.rs index 6c8d6e6e33..a8dbdb8208 100644 --- a/components/sup/tests/sup_tests/topology/leader.rs +++ b/components/sup/tests/sup_tests/topology/leader.rs @@ -12,7 +12,7 @@ use util::supervisor::Supervisor; // quorum reached. #[test] fn minimum_quorum() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service_gossip(); let sup_a = Supervisor::new_with_topology("leader"); @@ -36,7 +36,7 @@ fn minimum_quorum() { // Start three supervisors. See that they elect one, and only one, leader. #[test] fn elects_a_leader() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service_gossip(); let sup_a = Supervisor::new_with_topology("leader"); @@ -67,7 +67,7 @@ fn elects_a_leader() { #[test] #[ignore] fn elects_on_failure() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service_gossip(); let mut sup_a = Supervisor::new_with_topology("leader"); @@ -123,7 +123,7 @@ fn elects_on_failure() { #[test] #[ignore] fn leader_without_quorum_stops_service_remainder_elects_new_leader() { - setup::gpg_import(); + setup::origin_setup(); setup::simple_service_gossip(); let sup_a = Supervisor::new_with_permanent_topology("leader"); diff --git a/components/sup/tests/util/command.rs b/components/sup/tests/util/command.rs index c1f5bc6769..64e0a7ab1a 100644 --- a/components/sup/tests/util/command.rs +++ b/components/sup/tests/util/command.rs @@ -193,7 +193,7 @@ pub fn spawn(mut command: Command) -> CmdResult { } pub fn studio_run(cmd: &str, args: &[&str]) -> CmdResult { - let real_cmd = "hab-studio"; + let real_cmd = "/src/components/studio/bin/hab-studio.sh"; let mut real_args = vec!["-r", "/opt/studios/functional-tests", "run", cmd]; real_args.extend_from_slice(args); let mut command = command(real_cmd, &real_args[..]); @@ -253,8 +253,8 @@ pub fn sup_with_env(args: &[&str], env: &HashMap<&str, &str>) -> CmdResult /// some days, you just want to specify a directory instead of a hash. /// This function is for you! -pub fn sup_with_test_gpg_cache(args: &[&str], cache_dir: &str) -> CmdResult { +pub fn sup_with_test_key_cache(args: &[&str], cache_dir: &str) -> CmdResult { let mut env: HashMap<&str, &str> = HashMap::new(); - env.insert("HAB_CACHE_GPG_PATH", cache_dir); + env.insert("HAB_CACHE_KEY_PATH", cache_dir); sup_with_env(args, &env) } diff --git a/components/sup/tests/util/path.rs b/components/sup/tests/util/path.rs index 30b64a5a7e..40c80f6500 100644 --- a/components/sup/tests/util/path.rs +++ b/components/sup/tests/util/path.rs @@ -20,6 +20,12 @@ pub fn fixtures() -> PathBuf { root().join("fixtures") } +pub fn key_cache() -> PathBuf { + // same as the fixtures dir, for now + root().join("fixtures") +} + + pub fn fixture(name: &str) -> PathBuf { fixtures().join(name) } From 95f47a76eaaffaf9bba75d6626bf914e93b099ff Mon Sep 17 00:00:00 2001 From: Dave Parfitt Date: Tue, 12 Apr 2016 11:25:59 -0400 Subject: [PATCH 2/4] remove gpg ref --- components/bpm/plan.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/components/bpm/plan.sh b/components/bpm/plan.sh index d60e0ae0ef..cb0ea5cb61 100644 --- a/components/bpm/plan.sh +++ b/components/bpm/plan.sh @@ -35,9 +35,6 @@ do_install() { install -v -D $(pkg_path_for coreutils-static)/bin/coreutils \ $pkg_prefix/libexec/coreutils - install -v -D $(pkg_path_for gnupg-static)/bin/gpg \ - $pkg_prefix/libexec/gpg - install -v -D $(pkg_path_for jq-static)/bin/jq \ $pkg_prefix/libexec/jq From 5cd3ed85c87b23eb014efe7f1d93f4875cc1eb7a Mon Sep 17 00:00:00 2001 From: Dave Parfitt Date: Tue, 12 Apr 2016 15:38:42 -0400 Subject: [PATCH 3/4] install verifies package --- components/common/Cargo.lock | 62 +++++++------------ .../common/src/command/package/install.rs | 1 + .../simple_service_without_config/plan.sh | 2 +- 3 files changed, 24 insertions(+), 41 deletions(-) diff --git a/components/common/Cargo.lock b/components/common/Cargo.lock index 76c675d605..1627791d9c 100644 --- a/components/common/Cargo.lock +++ b/components/common/Cargo.lock @@ -19,11 +19,6 @@ dependencies = [ "memchr 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bitflags" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitflags" version = "0.4.0" @@ -53,46 +48,19 @@ dependencies = [ "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "gpg-error" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libgpg-error-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gpgme" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "gpg-error 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "gpgme-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gpgme-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libgpg-error-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "habitat_core" version = "0.4.0" dependencies = [ - "gpgme 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "libarchive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libsodium-sys 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.62 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "sodiumoxide 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -198,11 +166,6 @@ name = "libc" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "libgpg-error-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "libressl-pnacl-sys" version = "2.1.6" @@ -211,6 +174,15 @@ dependencies = [ "pnacl-build-helper 1.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "libsodium-sys" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lmdb-sys" version = "0.5.0" @@ -363,6 +335,16 @@ name = "semver" version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "sodiumoxide" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libsodium-sys 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "solicit" version = "0.4.4" diff --git a/components/common/src/command/package/install.rs b/components/common/src/command/package/install.rs index 34bd1e49b2..fb46dd32a6 100644 --- a/components/common/src/command/package/install.rs +++ b/components/common/src/command/package/install.rs @@ -98,6 +98,7 @@ fn install_from_depot>(url: &str, ident.as_ref(), CACHE_ARTIFACT_PATH)); let ident = try!(archive.ident()); + try!(archive.verify()); try!(archive.unpack()); println!("Installed {}", ident); } diff --git a/components/sup/tests/fixtures/simple_service_without_config/plan.sh b/components/sup/tests/fixtures/simple_service_without_config/plan.sh index cb71b8c8bb..ffdcf81168 100644 --- a/components/sup/tests/fixtures/simple_service_without_config/plan.sh +++ b/components/sup/tests/fixtures/simple_service_without_config/plan.sh @@ -4,7 +4,7 @@ pkg_version=0.0.1 pkg_license=('Apache2') pkg_maintainer="The Habitat Maintainers " pkg_source=nosuchfile.tar.gz -pkg_deps=(chef/gpgme chef/libassuan chef/libgpg-error) +pkg_deps=() pkg_bin_dirs=(bin) pkg_service_run="bin/simple_service_without_config" pkg_gpg_key=3853DA6B From 8a2cf5246911c109ae8918f2dc3190b1c7a15016 Mon Sep 17 00:00:00 2001 From: Dave Parfitt Date: Tue, 12 Apr 2016 17:08:59 -0400 Subject: [PATCH 4/4] .hab -> .bldr for the time being --- components/plan-build/bin/hab-plan-build.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/plan-build/bin/hab-plan-build.sh b/components/plan-build/bin/hab-plan-build.sh index d4b6d86c36..d85beec2c4 100755 --- a/components/plan-build/bin/hab-plan-build.sh +++ b/components/plan-build/bin/hab-plan-build.sh @@ -1866,12 +1866,12 @@ _generate_package() { build_line "Signing artifact" /src/components/hab/target/debug/hab artifact sign \ $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.xz \ - $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.hab --origin ${HABITAT_ORIGIN} + $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.bldr --origin ${HABITAT_ORIGIN} build_line "Verifying artifact" ## TODO: pretty output /src/components/hab/target/debug/hab artifact verify \ - $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.hab + $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.bldr # TODO rm $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.xz @@ -2044,7 +2044,7 @@ do_end # Print the results build_line "Source Cache: $HAB_CACHE_SRC_PATH/$pkg_dirname" build_line "Installed Path: $pkg_prefix" -build_line "Artifact: $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.hab" +build_line "Artifact: $HAB_CACHE_ARTIFACT_PATH/${pkg_origin}-${pkg_name}-${pkg_version}-${pkg_rel}.bldr" # Exit cleanly build_line