diff --git a/components/core/src/env.rs b/components/core/src/env.rs index 0adcc964a9..41829ac50f 100644 --- a/components/core/src/env.rs +++ b/components/core/src/env.rs @@ -77,59 +77,3 @@ pub fn var_os>(key: K) -> std::option::Option { None => None, } } - -/// Fetches the environment variable `SUDO_USER` from the current process, but only if the value is -/// not `"root"`. -/// -/// This function is special-purpose for a Habitat-centric interpretation of this value. If the -/// root user is running a command with `sudo`, then the environment will contain a -/// `SUDO_USER=root` value. However, Habitat considers root's home for caches, etc. to be under -/// the `/hab` directory (as opposed to root's `$HOME`). -/// -/// # Examples -/// -/// With no environment variable present: -/// -/// ``` -/// use std; -/// use habitat_core; -/// -/// std::env::remove_var("SUDO_USER"); -/// match habitat_core::env::sudo_user() { -/// Some(val) => panic!("The environment variable is set but should be unset!"), -/// None => println!("No SUDO_USER set in the environment"), -/// } -/// ``` -/// -/// With a non-root user set: -/// -/// ``` -/// use std; -/// use habitat_core; -/// -/// std::env::set_var("SUDO_USER", "bob"); -/// match habitat_core::env::sudo_user() { -/// Some(val) => assert_eq!(val, "bob"), -/// None => panic!("The environment variable is set and should be bob"), -/// } -/// ``` -/// -/// With the root user set: -/// -/// ``` -/// use std; -/// use habitat_core; -/// -/// std::env::set_var("SUDO_USER", "root"); -/// match habitat_core::env::sudo_user() { -/// Some(val) => panic!("The environment variable is set to root and should return with None!"), -/// None => println!("No non-root SUDO_USER set in the environment"), -/// } -/// ``` -/// -pub fn sudo_user() -> std::option::Option { - match self::var("SUDO_USER") { - Ok(val) => if val != "root" { Some(val) } else { None }, - Err(_) => None, - } -} diff --git a/components/hab/src/command/studio.rs b/components/hab/src/command/studio.rs index 49b58b213b..92e8045f37 100644 --- a/components/hab/src/command/studio.rs +++ b/components/hab/src/command/studio.rs @@ -13,127 +13,56 @@ // limitations under the License. use std::env; -use std::fs; +use std::fs as stdfs; use std::ffi::OsString; -use std::path::Path; +use std::path::PathBuf; use common::ui::UI; use hcore::crypto::CACHE_KEY_PATH_ENV_VAR; use hcore::env as henv; -use hcore::fs::{CACHE_ARTIFACT_PATH, CACHE_KEY_PATH}; -use hcore::os::{filesystem, users}; +use hcore::fs; use config; use error::Result; const ARTIFACT_PATH_ENVVAR: &'static str = "ARTIFACT_PATH"; +const ORIGIN_ENVVAR: &'static str = "HAB_ORIGIN"; const STUDIO_CMD: &'static str = "hab-studio"; const STUDIO_CMD_ENVVAR: &'static str = "HAB_STUDIO_BINARY"; const STUDIO_PACKAGE_IDENT: &'static str = "core/hab-studio"; pub fn start(ui: &mut UI, args: Vec) -> Result<()> { - inner::rerun_with_sudo_if_needed(ui)?; - - // If the `$HAB_ORIGIN` environment variable is not present, then see if a default is set in - // the CLI config. If so, set it as the `$HAB_ORIGIN` environment variable for the `hab-studio` - // or `docker` execv call. - if henv::var("HAB_ORIGIN").is_err() { - let config = config::load_with_sudo_user()?; + if henv::var(ORIGIN_ENVVAR).is_err() { + let config = config::load()?; if let Some(default_origin) = config.origin { debug!("Setting default origin {} via CLI config", &default_origin); env::set_var("HAB_ORIGIN", default_origin); } } - // Check if we are running under a `sudo` invocation. If so, determine the non-root user that - // issued the command in order to set some Studio-related environment variables. This is done - // so that the `hab-studio` command will find the correct key cache, artifact cache, etc. and - // so that the correct directores will be volume mounted when used with Docker. - if let Some(sudo_user) = henv::sudo_user() { - if let Some(home) = users::get_home_for_user(&sudo_user) { - // If the `$HAB_CACHE_KEY_PATH` environment variable is not present, set it to the - // non-root user's key cache - if henv::var(CACHE_KEY_PATH_ENV_VAR).is_err() { - let cache_key_path = home.join(format!(".{}", CACHE_KEY_PATH)); - debug!( - "Setting cache_key_path for SUDO_USER={} to: {}", - &sudo_user, - cache_key_path.display() - ); - env::set_var(CACHE_KEY_PATH_ENV_VAR, cache_key_path); - } - // If the `$ARTIFACT_PATH` environment variable is not present, set it to the non-root - // user's key cache - if henv::var(ARTIFACT_PATH_ENVVAR).is_err() { - let cache_artifact_path = home.join(format!(".{}", CACHE_ARTIFACT_PATH)); - try!(create_cache_artifact_path( - &cache_artifact_path, - Some(&sudo_user), - )); - debug!( - "Setting cache_artifact_path for SUDO_USER={} to: {}", - &sudo_user, - cache_artifact_path.display() - ); - env::set_var(ARTIFACT_PATH_ENVVAR, cache_artifact_path); - } - // Prevent any inner `hab` invocations from triggering similar logic: we will be - // operating in the context `hab-studio` which is running with root like privileges. - env::remove_var("SUDO_USER"); - } - } else { - if let Some(home) = users::get_home_for_current_user() { - if henv::var(ARTIFACT_PATH_ENVVAR).is_err() { - let cache_artifact_path = home.join(format!(".{}", CACHE_ARTIFACT_PATH)); - try!(create_cache_artifact_path(&cache_artifact_path, None)); - debug!( - "Setting cache_artifact_path at: {}", - cache_artifact_path.display() - ); - env::set_var(ARTIFACT_PATH_ENVVAR, cache_artifact_path); - } + if henv::var(CACHE_KEY_PATH_ENV_VAR).is_err() { + let path = fs::cache_key_path(None::<&str>); + debug!("Setting {}={}", CACHE_KEY_PATH_ENV_VAR, path.display()); + env::set_var(CACHE_KEY_PATH_ENV_VAR, &path); + }; + + let artifact_path = match henv::var(ARTIFACT_PATH_ENVVAR) { + Ok(p) => PathBuf::from(p), + Err(_) => { + let path = fs::cache_artifact_path(None::<&str>); + debug!("Setting {}={}", ARTIFACT_PATH_ENVVAR, path.display()); + env::set_var(ARTIFACT_PATH_ENVVAR, &path); + path } + }; + if !artifact_path.is_dir() { + debug!("Creating artifact_path at: {}", artifact_path.display()); + stdfs::create_dir_all(&artifact_path)?; } inner::start(ui, args) } -fn create_cache_artifact_path(path: &Path, sudo_user: Option<&str>) -> Result<()> { - if path.is_dir() { - Ok(()) - } else { - match sudo_user { - Some(sudo_user) => { - debug!( - "Creating cache_artifact_path for SUDO_USER={} at: {}", - &sudo_user, - path.display() - ) - } - None => debug!("Creating cache_artifact_path at: {}", path.display()), - }; - try!(fs::create_dir_all(&path)); - if let Some(sudo_user) = sudo_user { - if let (Some(uid), Some(gid)) = - ( - users::get_uid_by_name(sudo_user), - users::get_primary_gid_for_user(sudo_user), - ) - { - debug!( - "Setting permissions of {} for SUDO_USER={} to: {}:{}", - path.display(), - &sudo_user, - uid, - gid - ); - try!(filesystem::chown(path.to_string_lossy().as_ref(), uid, gid)); - } - } - Ok(()) - } -} - #[cfg(target_os = "linux")] mod inner { use std::env; @@ -155,6 +84,8 @@ mod inner { const SUDO_CMD: &'static str = "sudo"; pub fn start(ui: &mut UI, args: Vec) -> Result<()> { + rerun_with_sudo_if_needed(ui)?; + let command = match henv::var(super::STUDIO_CMD_ENVVAR) { Ok(command) => PathBuf::from(command), Err(_) => { @@ -180,7 +111,7 @@ mod inner { } } - pub fn rerun_with_sudo_if_needed(ui: &mut UI) -> Result<()> { + fn rerun_with_sudo_if_needed(ui: &mut UI) -> Result<()> { // If I have root permissions, early return, we are done. if am_i_root() { return Ok(()); @@ -314,11 +245,6 @@ mod inner { run_container(docker_cmd, args, volumes.iter(), env_vars.iter()) } - pub fn rerun_with_sudo_if_needed(_ui: &mut UI) -> Result<()> { - // No sudo calls necessary here--we are calling `docker` commands instead - Ok(()) - } - fn find_docker_cmd() -> Result { let docker_cmd = henv::var(DOCKER_CMD_ENVVAR).unwrap_or(DOCKER_CMD.to_string()); diff --git a/components/hab/src/config.rs b/components/hab/src/config.rs index 1dd4f807a2..65f7df99b5 100644 --- a/components/hab/src/config.rs +++ b/components/hab/src/config.rs @@ -18,9 +18,7 @@ use std::io::Write; use std::path::PathBuf; use hcore::config::ConfigFile; -use hcore::env as henv; use hcore::fs::{am_i_root, FS_ROOT_PATH}; -use hcore::os::users; use toml; use error::{Error, Result}; @@ -47,15 +45,18 @@ impl Default for Config { } pub fn load() -> Result { - common_load(false) -} - -pub fn load_with_sudo_user() -> Result { - common_load(true) + let cli_config_path = cli_config_path(); + if cli_config_path.exists() { + debug!("Loading CLI config from {}", cli_config_path.display()); + Ok(Config::from_file(&cli_config_path)?) + } else { + debug!("No CLI config found, loading defaults"); + Ok(Config::default()) + } } pub fn save(config: &Config) -> Result<()> { - let config_path = cli_config_path(false); + let config_path = cli_config_path(); let parent_path = match config_path.parent() { Some(p) => p, None => { @@ -72,34 +73,11 @@ pub fn save(config: &Config) -> Result<()> { Ok(()) } -fn common_load(use_sudo_user: bool) -> Result { - let cli_config_path = cli_config_path(use_sudo_user); - if cli_config_path.exists() { - debug!("Loading CLI config from {}", cli_config_path.display()); - Ok(Config::from_file(&cli_config_path)?) - } else { - debug!("No CLI config found, loading defaults"); - Ok(Config::default()) - } -} - -fn cli_config_path(use_sudo_user: bool) -> PathBuf { - match am_i_root() { - true => { - if use_sudo_user { - if let Some(sudo_user) = henv::sudo_user() { - if let Some(home) = users::get_home_for_user(&sudo_user) { - return home.join(format!(".{}", CLI_CONFIG_PATH)); - } - } - } - } - false => { - if let Some(home) = env::home_dir() { - return home.join(format!(".{}", CLI_CONFIG_PATH)); - } +fn cli_config_path() -> PathBuf { + if !am_i_root() { + if let Some(home) = env::home_dir() { + return home.join(format!(".{}", CLI_CONFIG_PATH)); } } - PathBuf::from(&*FS_ROOT_PATH).join(CLI_CONFIG_PATH) } diff --git a/components/studio/bin/hab-studio.sh b/components/studio/bin/hab-studio.sh index c086fabf03..a828038fc8 100755 --- a/components/studio/bin/hab-studio.sh +++ b/components/studio/bin/hab-studio.sh @@ -448,6 +448,7 @@ new_studio() { local studio_artifact_path studio_artifact_path="${HAB_STUDIO_ROOT}${HAB_CACHE_ARTIFACT_PATH}" if ! $bb mount | $bb grep -q "on $studio_artifact_path type"; then + $bb mkdir -p $v $ARTIFACT_PATH $bb mkdir -p $v $studio_artifact_path $bb mount $v --bind $ARTIFACT_PATH $studio_artifact_path fi