From d013f95751b2dd2d9776c8650a44001a7d5d0cff Mon Sep 17 00:00:00 2001 From: Catalin Cristescu Date: Wed, 14 Jun 2017 10:37:38 -0400 Subject: [PATCH 1/6] In a multi user environment where multiple projects are located on the same instance(s) if two or more users are deploying a project on the same environment, the generated hosts files are overwritten or worse, the deploy will fail due to file permissions Make the persistent storage folder configurable or use the system tmp as default if not possible --- src/Host/Storage.php | 68 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/src/Host/Storage.php b/src/Host/Storage.php index b3d9f1895..a1da74b70 100644 --- a/src/Host/Storage.php +++ b/src/Host/Storage.php @@ -14,6 +14,72 @@ class Storage { + /** + * In a multi user environment where multiple projects are located on the same instance(s) + * if two or more users are deploying a project on the same environment, the generated hosts files + * are overwritten or worse, the deploy will fail due to file permissions + * + * Make the persistent storage folder configurable or use the system tmp + * as default if not possible + * + * @return string + * @throws Exception + */ + private static function _getPersistentStorageLocation() { + $config = \Deployer\Deployer::get()->config; + + // default persistent storage in case we can't use the configured value + // or we can't create the default location + // use the system temporary folder and the current pid to make the path unique + $tmp = sys_get_temp_dir() . '/' . uuid(posix_getpid()); + + // get the location for the deployer configuration + $deployerConfig = $config->has('deployer_config') ? $config->get('deployer_config') : null; + + if ( !is_null($deployerConfig) ) { + // check if the folder exists and it's writable + if ( !(is_dir($deployerConfig) && is_writable($deployerConfig)) ) { + throw new Exception("Deployer folder `$deployerConfig` doesn't exists or doesn't writable."); + } + } else { + // not configured, generate deployer folder name + + // use the home dir of the current user + // and the repository name + $userInfo = posix_getpwuid(posix_getuid()); + + // if for some reason we couldn't find a valid home folder + // or if it's not writable, use the default location + if ( !isset($userInfo['dir']) || !(is_dir($userInfo['dir']) && is_writable($userInfo['dir'])) ) { + return $tmp; + } + + // we have a folder name + $deployerConfig = $userInfo['dir'] . '/.deployer'; + + //if it doesn't exists, create it + if ( !file_exists($deployerConfig) ) { + mkdir($deployerConfig, 0777, true); + } + + //it exists, check if it's a folder and if it's writable + if ( !(is_dir($deployerConfig) && is_writable($deployerConfig)) ) { + return $tmp; + } + } + + // we will store the persistent data per repository + $configRepository = $config->has('repository') ? $config->get('repository') : null; + if (empty($configRepository)) { + return $tmp; + } + + // we now have the repository name + $repository = str_replace('/', '_', substr($configRepository, (strrpos($configRepository, ':') + 1))); + + return $deployerConfig . '/' . $repository; + } + /** * @param Host[] $hosts */ @@ -27,7 +93,7 @@ public static function persist(array $hosts) $values[$key] = $host->get($key); } - $file = sys_get_temp_dir() . '/' . $host->getHostname() . '.dep'; + $file = self::_getPersistentStorageLocation() . '/' . $host->getHostname() . '.dep'; $values['host_config_storage'] = $file; $persistentCollection = new PersistentCollection($file, $values); From ad11d01e5f966cdc0afe13461600a6d6400c5131 Mon Sep 17 00:00:00 2001 From: Catalin Cristescu Date: Wed, 14 Jun 2017 10:55:09 -0400 Subject: [PATCH 2/6] Use uniqid together with the PID to generate a temporary folder name when the persistent storage it's located in the system tmp --- src/Host/Storage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Host/Storage.php b/src/Host/Storage.php index a1da74b70..8c34c789e 100644 --- a/src/Host/Storage.php +++ b/src/Host/Storage.php @@ -31,7 +31,7 @@ private static function _getPersistentStorageLocation() { // default persistent storage in case we can't use the configured value // or we can't create the default location // use the system temporary folder and the current pid to make the path unique - $tmp = sys_get_temp_dir() . '/' . uuid(posix_getpid()); + $tmp = sys_get_temp_dir() . '/' . uniqid(posix_getpid()); // get the location for the deployer configuration $deployerConfig = $config->has('deployer_config') ? $config->get('deployer_config') : null; From b0e373ddbebf48640e1533f6d9cdb6c7dfc75bae Mon Sep 17 00:00:00 2001 From: Catalin Cristescu Date: Thu, 15 Jun 2017 10:05:27 -0400 Subject: [PATCH 3/6] Use uniqid together with the PID to generate a temporary folder name when the persistent storage it's located in the system tmp. Dropped the uniqueid. --- src/Host/Storage.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Host/Storage.php b/src/Host/Storage.php index 8c34c789e..02b219d47 100644 --- a/src/Host/Storage.php +++ b/src/Host/Storage.php @@ -16,8 +16,9 @@ class Storage { /** * In a multi user environment where multiple projects are located on the same instance(s) - * if two or more users are deploying a project on the same environment, the generated hosts files - * are overwritten or worse, the deploy will fail due to file permissions + * if two or more users are deploying at the same time on the same environment, + * the generated hosts files are overwritten or worse, the deploy will fail + * due to file permissions * * Make the persistent storage folder configurable or use the system tmp * as default if not possible @@ -28,11 +29,11 @@ class Storage private static function _getPersistentStorageLocation() { $config = \Deployer\Deployer::get()->config; - // default persistent storage in case we can't use the configured value + // use the system temporary folder and the current pid as default + // persistent storage in case we can't use the configured value // or we can't create the default location - // use the system temporary folder and the current pid to make the path unique - $tmp = sys_get_temp_dir() . '/' . uniqid(posix_getpid()); - + $tmp = sys_get_temp_dir() . '/' . posix_getpid(); + // get the location for the deployer configuration $deployerConfig = $config->has('deployer_config') ? $config->get('deployer_config') : null; @@ -76,7 +77,7 @@ private static function _getPersistentStorageLocation() { // we now have the repository name $repository = str_replace('/', '_', substr($configRepository, (strrpos($configRepository, ':') + 1))); - + return $deployerConfig . '/' . $repository; } From f4235f6542383b59adfbafc09cf14fbff59404e1 Mon Sep 17 00:00:00 2001 From: Catalin Cristescu Date: Mon, 19 Jun 2017 11:35:18 -0400 Subject: [PATCH 4/6] Using getenv to find the home folder on non posix compatible systems. Removed the option to used a configuration variable to set the persistent storage location. --- src/Host/Storage.php | 144 +++++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 68 deletions(-) diff --git a/src/Host/Storage.php b/src/Host/Storage.php index 02b219d47..70c9ad761 100644 --- a/src/Host/Storage.php +++ b/src/Host/Storage.php @@ -14,73 +14,6 @@ class Storage { - /** - * In a multi user environment where multiple projects are located on the same instance(s) - * if two or more users are deploying at the same time on the same environment, - * the generated hosts files are overwritten or worse, the deploy will fail - * due to file permissions - * - * Make the persistent storage folder configurable or use the system tmp - * as default if not possible - * - * @return string - * @throws Exception - */ - private static function _getPersistentStorageLocation() { - $config = \Deployer\Deployer::get()->config; - - // use the system temporary folder and the current pid as default - // persistent storage in case we can't use the configured value - // or we can't create the default location - $tmp = sys_get_temp_dir() . '/' . posix_getpid(); - - // get the location for the deployer configuration - $deployerConfig = $config->has('deployer_config') ? $config->get('deployer_config') : null; - - if ( !is_null($deployerConfig) ) { - // check if the folder exists and it's writable - if ( !(is_dir($deployerConfig) && is_writable($deployerConfig)) ) { - throw new Exception("Deployer folder `$deployerConfig` doesn't exists or doesn't writable."); - } - } else { - // not configured, generate deployer folder name - - // use the home dir of the current user - // and the repository name - $userInfo = posix_getpwuid(posix_getuid()); - - // if for some reason we couldn't find a valid home folder - // or if it's not writable, use the default location - if ( !isset($userInfo['dir']) || !(is_dir($userInfo['dir']) && is_writable($userInfo['dir'])) ) { - return $tmp; - } - - // we have a folder name - $deployerConfig = $userInfo['dir'] . '/.deployer'; - - //if it doesn't exists, create it - if ( !file_exists($deployerConfig) ) { - mkdir($deployerConfig, 0777, true); - } - - //it exists, check if it's a folder and if it's writable - if ( !(is_dir($deployerConfig) && is_writable($deployerConfig)) ) { - return $tmp; - } - } - - // we will store the persistent data per repository - $configRepository = $config->has('repository') ? $config->get('repository') : null; - if (empty($configRepository)) { - return $tmp; - } - - // we now have the repository name - $repository = str_replace('/', '_', substr($configRepository, (strrpos($configRepository, ':') + 1))); - - return $deployerConfig . '/' . $repository; - } - /** * @param Host[] $hosts */ @@ -94,7 +27,7 @@ public static function persist(array $hosts) $values[$key] = $host->get($key); } - $file = self::_getPersistentStorageLocation() . '/' . $host->getHostname() . '.dep'; + $file = self::getPersistentStorageLocation() . '/' . $host->getHostname() . '.dep'; $values['host_config_storage'] = $file; $persistentCollection = new PersistentCollection($file, $values); @@ -150,4 +83,79 @@ public static function setup(Host $host, string $file) $persistentCollection->load(); $host->getConfig()->setCollection($persistentCollection); } + + /** + * In a multi user environment where multiple projects are located on the same instance(s) + * if two or more users are deploying at the same time on the same environment, + * the generated hosts files are overwritten or worse, the deploy will fail + * due to file permissions + * + * Make the persistent storage folder configurable or use the system tmp + * as default if not possible + * + * @return string + * @throws Exception + */ + private static function getPersistentStorageLocation() { + $config = \Deployer\Deployer::get()->config; + + // use the system temporary folder and the current pid as default + // persistent storage in case we can't use the configured value + // or we can't create the default location + $tmp = sys_get_temp_dir() . '/' . posix_getpid(); + + // use the home dir of the current user + // and the repository name + + //posix compatible + if (function_exists('posix_getpwuid')) { + $userInfo = posix_getpwuid(posix_getuid()); + + // if for some reason we couldn't find a valid home folder + // or if it's not writable, use the default location + if ( !isset($userInfo['dir']) || !(is_dir($userInfo['dir']) && is_writable($userInfo['dir'])) ) { + return $tmp; + } + + // we have a folder name + $homeDir = $userInfo['dir']; + } else { + if (getenv('HOME')) { + // MacOS and other *nix + $homeDir = getenv('HOME'); + } else if (getenv('HOMEDRIVE') && getenv('HOMEPATH')) { + // Windows 8+ + $homeDir = getenv('HOMEDRIVE') . getenv('HOMEPATH'); + } + } + + if (empty($homeDir)) { + // unable to get the home dir + return $tmp; + } else { + // we have a folder name + $persistentStorage = $homeDir . '/.deployer'; + } + + //if it doesn't exists, create it + if ( !file_exists($persistentStorage) ) { + mkdir($persistentStorage, 0777, true); + } + + //it exists, check if it's a folder and if it's writable + if ( !(is_dir($persistentStorage) && is_writable($persistentStorage)) ) { + return $tmp; + } + + // we will store the persistent data per repository + $configRepository = $config->has('repository') ? $config->get('repository') : null; + if (empty($configRepository)) { + return $tmp; + } + + // we now have the repository name + $repository = str_replace('/', '_', substr($configRepository, (strrpos($configRepository, ':') + 1))); + + return $persistentStorage . '/' . $repository; + } } From ced4a16418e58f3151691b2b2ce3cc7b21d4640b Mon Sep 17 00:00:00 2001 From: Catalin Cristescu Date: Mon, 19 Jun 2017 12:19:55 -0400 Subject: [PATCH 5/6] Using getmypid on non posix compatible systems to get the PID of the running process. --- src/Host/Storage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Host/Storage.php b/src/Host/Storage.php index 70c9ad761..332f31f62 100644 --- a/src/Host/Storage.php +++ b/src/Host/Storage.php @@ -102,7 +102,7 @@ private static function getPersistentStorageLocation() { // use the system temporary folder and the current pid as default // persistent storage in case we can't use the configured value // or we can't create the default location - $tmp = sys_get_temp_dir() . '/' . posix_getpid(); + $tmp = sys_get_temp_dir() . '/' . (function_exists('posix_getpid') ? posix_getpid() : getmypid()); // use the home dir of the current user // and the repository name From 4b0bdf2b0c091d4d80a233a96be6d121790a3a5b Mon Sep 17 00:00:00 2001 From: Catalin Cristescu Date: Fri, 23 Jun 2017 08:11:30 -0400 Subject: [PATCH 6/6] Using random file names in system tmp instead per user storage. --- src/Host/Storage.php | 77 +------------------------------------------- 1 file changed, 1 insertion(+), 76 deletions(-) diff --git a/src/Host/Storage.php b/src/Host/Storage.php index 332f31f62..85a6c0473 100644 --- a/src/Host/Storage.php +++ b/src/Host/Storage.php @@ -27,7 +27,7 @@ public static function persist(array $hosts) $values[$key] = $host->get($key); } - $file = self::getPersistentStorageLocation() . '/' . $host->getHostname() . '.dep'; + $file = sys_get_temp_dir() . '/' . uniqid('deployer-') . '-' . $host->getHostname() . '.dep'; $values['host_config_storage'] = $file; $persistentCollection = new PersistentCollection($file, $values); @@ -83,79 +83,4 @@ public static function setup(Host $host, string $file) $persistentCollection->load(); $host->getConfig()->setCollection($persistentCollection); } - - /** - * In a multi user environment where multiple projects are located on the same instance(s) - * if two or more users are deploying at the same time on the same environment, - * the generated hosts files are overwritten or worse, the deploy will fail - * due to file permissions - * - * Make the persistent storage folder configurable or use the system tmp - * as default if not possible - * - * @return string - * @throws Exception - */ - private static function getPersistentStorageLocation() { - $config = \Deployer\Deployer::get()->config; - - // use the system temporary folder and the current pid as default - // persistent storage in case we can't use the configured value - // or we can't create the default location - $tmp = sys_get_temp_dir() . '/' . (function_exists('posix_getpid') ? posix_getpid() : getmypid()); - - // use the home dir of the current user - // and the repository name - - //posix compatible - if (function_exists('posix_getpwuid')) { - $userInfo = posix_getpwuid(posix_getuid()); - - // if for some reason we couldn't find a valid home folder - // or if it's not writable, use the default location - if ( !isset($userInfo['dir']) || !(is_dir($userInfo['dir']) && is_writable($userInfo['dir'])) ) { - return $tmp; - } - - // we have a folder name - $homeDir = $userInfo['dir']; - } else { - if (getenv('HOME')) { - // MacOS and other *nix - $homeDir = getenv('HOME'); - } else if (getenv('HOMEDRIVE') && getenv('HOMEPATH')) { - // Windows 8+ - $homeDir = getenv('HOMEDRIVE') . getenv('HOMEPATH'); - } - } - - if (empty($homeDir)) { - // unable to get the home dir - return $tmp; - } else { - // we have a folder name - $persistentStorage = $homeDir . '/.deployer'; - } - - //if it doesn't exists, create it - if ( !file_exists($persistentStorage) ) { - mkdir($persistentStorage, 0777, true); - } - - //it exists, check if it's a folder and if it's writable - if ( !(is_dir($persistentStorage) && is_writable($persistentStorage)) ) { - return $tmp; - } - - // we will store the persistent data per repository - $configRepository = $config->has('repository') ? $config->get('repository') : null; - if (empty($configRepository)) { - return $tmp; - } - - // we now have the repository name - $repository = str_replace('/', '_', substr($configRepository, (strrpos($configRepository, ':') + 1))); - - return $persistentStorage . '/' . $repository; - } }