-
Notifications
You must be signed in to change notification settings - Fork 824
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NEW replace _ss_environment.php with .env and environment vars #6337
Conversation
521cad4
to
ee72f02
Compare
Brilliant change. I'd suggest creating an |
Could we not support both getenv() and defined() vars using a core environment helper?
This allows certain vars to be fixed (and thus protected from modification). there are security concerns related to allowing core vars to be modified. |
@assertchris good idea - I guess I'll just copy laravel ;) - though there is more a favour towards putting these methods into utility classes. @tractorcow whilst I don't really think there's a significant issue in allowing our pseudo environment vars to be modified I think your suggestion is sound in regards to providing BC support. One issue there is to address is how we now handle |
I think it would be better to resolve |
f6a9cb1
to
85f9a62
Compare
I would prefer to see |
I agree - there's currently the ability to set default baseurl and we could easily move this to an env var itself. |
My view is that if you declare security-sensitive vars such as SS_TRUST_* values, attempts to re-declare them via getenv() could potentially be an error condition (i.e. only if defined in multiple places AND differ). Other values could be safely overridden, however, e.g for testing purposes. :) I'm very security paranoid though... so I am perhaps arguing for unnecessary strictness in this case. |
Maybe just have SS_DEFAULT_BASE_URL instead as a substitute? Does that better suit the new architecture? We have BASE_URL but that's a core constant not an environment-level option. |
tests/bootstrap/environment.php
Outdated
@@ -2,33 +2,37 @@ | |||
|
|||
// Bootstrap _ss_environment.php |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Bootstrap environment.php ?
if(defined('SS_PROTECTED_ASSETS_PATH')) { | ||
return SS_PROTECTED_ASSETS_PATH; | ||
if(getenv('SS_PROTECTED_ASSETS_PATH')) { | ||
return getenv('SS_PROTECTED_ASSETS_PATH'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it more efficient to avoid calling getenv
twice and instead do something like below?
if($protetedAssetsPath=getenv('SS_PROTECTED_ASSETS_PATH')) {
return $protectedAssetsPath;
}
If so then there are a number of other places one reduce the calls to getenv
:)
src/Control/Director.php
Outdated
@@ -585,7 +585,7 @@ public static function is_https() { | |||
// See https://support.microsoft.com/en-us/kb/307347 | |||
$headerOverride = false; | |||
if (TRUSTED_PROXY) { | |||
$headers = (defined('SS_TRUSTED_PROXY_PROTOCOL_HEADER')) ? array(SS_TRUSTED_PROXY_PROTOCOL_HEADER) : null; | |||
$headers = (getenv('SS_TRUSTED_PROXY_PROTOCOL_HEADER')) ? array(getenv('SS_TRUSTED_PROXY_PROTOCOL_HEADER')) : null; | |||
if (!$headers) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra call to getenv
?
src/Control/HTTPRequest.php
Outdated
@@ -708,7 +708,7 @@ public function allParsed() { | |||
public function getIP() { | |||
$headerOverrideIP = null; | |||
if(TRUSTED_PROXY) { | |||
$headers = (defined('SS_TRUSTED_PROXY_IP_HEADER')) ? array(SS_TRUSTED_PROXY_IP_HEADER) : null; | |||
$headers = (getenv('SS_TRUSTED_PROXY_IP_HEADER')) ? array(getenv('SS_TRUSTED_PROXY_IP_HEADER')) : null; | |||
if(!$headers) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra call to getenv
?
src/Core/Constants.php
Outdated
if(defined('SS_TRUSTED_PROXY_IPS') && SS_TRUSTED_PROXY_IPS !== 'none') { | ||
if(SS_TRUSTED_PROXY_IPS === '*') { | ||
if(getenv('SS_TRUSTED_PROXY_IPS') !== 'none') { | ||
if(getenv('SS_TRUSTED_PROXY_IPS') === '*') { | ||
$trusted = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra call to getenv ?
src/Core/Constants.php
Outdated
if (defined('SS_ALLOWED_HOSTS') && php_sapi_name() !== "cli") { | ||
$all_allowed_hosts = explode(',', SS_ALLOWED_HOSTS); | ||
if (getenv('SS_ALLOWED_HOSTS') && php_sapi_name() !== "cli") { | ||
$all_allowed_hosts = explode(',', getenv('SS_ALLOWED_HOSTS')); | ||
if (!isset($_SERVER['HTTP_HOST']) || !in_array($_SERVER['HTTP_HOST'], $all_allowed_hosts)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra call to getenv ?
@@ -167,7 +167,7 @@ protected function currentAbsoluteURL() { | |||
// See https://support.microsoft.com/en-us/kb/307347 | |||
$headerOverride = false; | |||
if(TRUSTED_PROXY) { | |||
$headers = (defined('SS_TRUSTED_PROXY_PROTOCOL_HEADER')) ? array(SS_TRUSTED_PROXY_PROTOCOL_HEADER) : null; | |||
$headers = (getenv('SS_TRUSTED_PROXY_PROTOCOL_HEADER')) ? array(getenv('SS_TRUSTED_PROXY_PROTOCOL_HEADER')) : null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra call to getenv ?
src/Dev/Deprecation.php
Outdated
if(defined('SS_DEPRECATION_ENABLED')) { | ||
return SS_DEPRECATION_ENABLED; | ||
if(getenv('SS_DEPRECATION_ENABLED')) { | ||
return getenv('SS_DEPRECATION_ENABLED'); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra call to getenv ?
src/Dev/Install/config-form.html
Outdated
if($usingEnv && isset($fieldSpec['envVar']) && defined($fieldSpec['envVar'])) { | ||
$value = constant($fieldSpec['envVar']); | ||
if($usingEnv && isset($fieldSpec['envVar']) && getenv($fieldSpec['envVar'])) { | ||
$value = getenv($fieldSpec['envVar']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra call to getenv ?
src/Dev/Install/install.php5
Outdated
if( defined('SS_DATABASE_CLASS') ){ | ||
$type = $_REQUEST['db']['type'] = SS_DATABASE_CLASS; | ||
if( getenv('SS_DATABASE_CLASS') ){ | ||
$type = $_REQUEST['db']['type'] = getenv('SS_DATABASE_CLASS'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra call to getenv ?
src/Dev/Install/install.php5
Outdated
if( defined('SS_DATABASE_CLASS') ){ | ||
$type = $_REQUEST['db']['type'] = SS_DATABASE_CLASS; | ||
if( getenv('SS_DATABASE_CLASS') ){ | ||
$type = $_REQUEST['db']['type'] = getenv('SS_DATABASE_CLASS'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra call to getenv
?
src/conf/ConfigureFromEnv.php
Outdated
} else if(defined('SS_DATABASE_CHOOSE_NAME') && SS_DATABASE_CHOOSE_NAME) { | ||
$loopCount = (int)SS_DATABASE_CHOOSE_NAME; | ||
if(getenv('SS_DATABASE_NAME')) { | ||
$database = getenv('SS_DATABASE_NAME'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra call to getenv
?
src/conf/ConfigureFromEnv.php
Outdated
if(getenv('SS_DATABASE_NAME')) { | ||
$database = getenv('SS_DATABASE_NAME'); | ||
} else if(getenv('SS_DATABASE_CHOOSE_NAME')) { | ||
$loopCount = (int)getenv('SS_DATABASE_CHOOSE_NAME'); | ||
$databaseDir = BASE_PATH; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra call to getenv
?
src/conf/ConfigureFromEnv.php
Outdated
if(defined('SS_DATABASE_PORT')) { | ||
$databaseConfig['port'] = SS_DATABASE_PORT; | ||
if(getenv('SS_DATABASE_PORT')) { | ||
$databaseConfig['port'] = getenv('SS_DATABASE_PORT'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra call to getenv
?
src/conf/ConfigureFromEnv.php
Outdated
if (defined('SS_DATABASE_TIMEZONE')) { | ||
$databaseConfig['timezone'] = SS_DATABASE_TIMEZONE; | ||
if (getenv('SS_DATABASE_TIMEZONE')) { | ||
$databaseConfig['timezone'] = getenv('SS_DATABASE_TIMEZONE'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra call to getenv
?
src/conf/ConfigureFromEnv.php
Outdated
if(defined('SS_DATABASE_SCHEMA')) | ||
$databaseConfig["schema"] = SS_DATABASE_SCHEMA; | ||
if(getenv('SS_DATABASE_SCHEMA')) | ||
$databaseConfig["schema"] = getenv('SS_DATABASE_SCHEMA'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra call to getenv
?
20de2fa
to
7edf25a
Compare
I've added docs under environment management that show the new format. I've added to the changelog to link to this.
Added security issues section to environment management docs
I'm not sure where to put this, it doesn't really make sense to put it in environment management docs ("Don't do this thing you can't do any more coz it's bad but if you have to do it this way").
Added to change log |
In the |
docs/en/04_Changelogs/4.0.0.md
Outdated
* Removed support for _ss_environment.php in favour of .env and first class environment variables | ||
* Environment variables now can be set in `.env` file placed in webroot or one level above | ||
* Environment variables will be read from the environment as well | ||
* `$_FILE_TO_URL_MAPPING` has been removed and replaced with using `Director.aleternate_host` or `SS_HOST` env var |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spelling ("aleternate")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's wrong with my aleternate spelling :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more points. However, I'd be open to merging as-is and raising an alpha5 ticket for the subsequent changes if we want to just get the thing over the line.
|
||
## Managing environment variables with `.env` files | ||
|
||
By default the `.env` must be placed in your webroot. If this file exists, it will be automatically loaded by the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Let's start saying "project root" rather than webroot. If, one blessed day, we allow a flexible webroot location, then these docs won't need updating.
- We should note in these docs that the
.env
Eg: "By default, the .env
file must be placed either in your project root folder (i.e. next to your composer.json), or in its parent folder"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
| `SS_ALLOWED_HOSTS` | A comma deliminated list of hostnames the site is allowed to respond to | | ||
| `SS_MANIFESTCACHE` | The manifest cache to use (defaults to file based caching) | | ||
| `SS_IGNORE_DOT_ENV` | If set the .env file will be ignored. This is good for live to mitigate any performance implications of loading the .env file | | ||
| `SS_HOST` | The hostname to use when it isn't determinable by other means (eg: for CLI commands) | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't appear to let us force the generation of https://
URLs from CLI scripts. Perhaps we want to allow SS_HOST
to be a URL fragment as well as a hostname?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be a future PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've also lost the ability to indicate that a SilverStripe site is running in a non-root URL.
Was there a reason that we didn't make this setting SS_BASE_URL
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm - good point
|
||
// Basic CLI hostname | ||
# Basic CLI hostname | ||
global $_FILE_TO_URL_MAPPING; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is out of date.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
BASE_PATH, | ||
dirname(BASE_PATH), | ||
) as $path) { | ||
try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a blocker, but I feel that an if(file_exists())
check would be better than throwing and swallowing an exception.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exception is a bit of overhead, we can fix in separate ticket.
7edf25a
to
0a9ec3f
Compare
0a9ec3f
to
8c8231c
Compare
OK - I've addressed all the feedback apart from the URL issues |
I'm happy for us to merge as-is and pick up SS_HOST vs SS_BASE_URL as a separate ticket. |
:') Can't believe it - whoop |
I've opened the follow-up issue |
Awesome to see this merged! Buuuuut: It broke all travis builds apart from framework, since that's the only one that no longer relies on travis-support: silverstripe/silverstripe-travis-support#41. And funnily enough, we're using conditional logic in the _ss_env there ;) @dhensby, do you have time to look at this? |
I'll look at it today. |
The current version of phpdotenv is robust and thread-safe. The following example will work in a multithreaded environment. This avoids using the adapter that would have called <?php
use Dotenv\Environment\Adapter\EnvConstAdapter;
use Dotenv\Environment\Adapter\ServerConstAdapter;
use Dotenv\Environment\DotenvFactory;
use Dotenv\Dotenv;
$factory = new DotenvFactory([new EnvConstAdapter(), new ServerConstAdapter()]);
Dotenv::create($path, null, $factory)->load(); |
Thanks for the update @GrahamCampbell! @silverstripe/core-team do we want to do an RFC to re-implement the latest version of phpdotenv for SS5? |
New issue / thread please :) |
I second Dan. Going through dozen of messages from 2 years ago is not conductive to a useful discussion. |
See #8764. :) |
This PR replaces our idiosyncratic
_ss_environment.php
convention with support for first class environment variables with a.env
poly-fill for easy testing/development.I've also removed the dependency on the
Host
header ($_SERVER['HTTP_HOST']
) from the bootstrap so we no longer require$_FILE_TO_URL_MAPPING
global for CLI execution. Devs can now setSS_HOST
environment variable orDirector.alternate_host
config var.Docs and tests have been updated