Skip to content

Symfony Config Component does not recognize environment variables #28599

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

Closed
alex-bacart opened this issue Sep 25, 2018 · 14 comments
Closed

Symfony Config Component does not recognize environment variables #28599

alex-bacart opened this issue Sep 25, 2018 · 14 comments

Comments

@alex-bacart
Copy link
Contributor

Symfony version(s) affected: 4.1

Description
Following the documentation on a fresh installed Symfony 4.1.
https://symfony.com/doc/current/configuration/external_parameters.html#environment-variable-processors

Copying and pasting these configuration in config/packages/framework.yaml
image

Getting an exception:

In BaseNode.php line 529:
Invalid type for path "framework.trusted_hosts.0". Expected one of "bool", "int", "float", "string", but got "array".

My environment does not contain a TRUSTED_PROXIES variable.
It looks like a bug with a JSON environment variables passed to configuration. If it's by design than it's a documentation bug.

Maybe related to #28137 and #23888

@javiereguiluz
Copy link
Member

To be honest, I expect this example to work. The other issues gave some explanations about this expected behaviour ... but I'm not convinced 😕

@ro0NL
Copy link
Contributor

ro0NL commented Sep 27, 2018

By design :)

trusted_hosts is a protyped scalar array, which is incompatible with env vars (we dont know it's an array of scalars, as such we dont allow it). Env values can be anything, and we get minimal info from the prefix.

To support this, we need that info. So with a notation like %env(string[]:json:ENV)% it could be possible, as suggested here: #28137 (comment)

@javiereguiluz
Copy link
Member

Yes, but it's the "by design" thing which I don't understand.

Right now it works like this:

  • I require an array here...
  • ...but you are using an env var...
  • ...which could be perfectly an array...
  • ... but what if it's not an array?
  • So, in case someone doesn't pass an array here, I'm going to throw an exception always, even if you pass an array.

I'd like to work it like this:

  • This expects an array...
  • ...but if you pass an env var, that's OK too
  • If the env var doesn't contain an array, the app won't work.
  • But that's your responsibility as a developer. You made a conscious decision to use env vars, so you must know how to deal with env vars.

Does it make sense ... or would it be a worse behaviour?

@ro0NL
Copy link
Contributor

ro0NL commented Sep 27, 2018

Right now it works like this:

  • it requires scalar[]
  • we pass array
  • it crashes as such :)

We can allow it sure, but it defeats config validation. You can already allow it by using variable node.

For core i'd to look at @nicolas-grekas suggestion (#28137 (comment)) to basically allow the array (change core to variable node) and validate the elements to be scalar during runtime.

That's a per case change anyway, from config pov i'm still happy with the current design. But as mentioned, the more type info we can extract from the env prefix, the better we can make the integration with config validation.

@ro0NL
Copy link
Contributor

ro0NL commented Sep 27, 2018

Also. to make this valid for now, the same logic applies as #28137 (comment)

trusted_hosts:
  - '%(env:TRUSTED_HOST_1)%'
  - ...

@javiereguiluz
Copy link
Member

javiereguiluz commented Sep 27, 2018

I'm afraid I don't follow you. What's the difference between scalar[] and array? Isn't ['10.0.0.1', '10.0.0.2'] an array of scalar strings? (So it's both an array and a scalar[])

@ro0NL
Copy link
Contributor

ro0NL commented Sep 27, 2018

any scalar[] is an array

but not any array is scalar[], per se. It could be int[], object[] etc. as well.

@javiereguiluz
Copy link
Member

That's where we disagree. If Symfony doesn't know for sure if something is right or wrong, it should abstain.

@ro0NL
Copy link
Contributor

ro0NL commented Sep 27, 2018

Then it should abstain from validating during compile time. At least it should not allow for false positives.

If the node is configured to requires type A, but gets type B it should crash. Period. scalar[] and array in that sense are different types to me.

So if want to use an arbitrary array from JSON in config, then config should also allow for a variable (protyped) array.

@stof
Copy link
Member

stof commented Sep 27, 2018

As soon as the Config component performs some normalization of the input (which is the case here to accept passing a string rather than an array when you need a single value), this does not play well with env placeholders, as the normalization logic runs on the placeholder itself, not on the value (as it is not known).

That's where we disagree. If Symfony doesn't know for sure if something is right or wrong, it should abstain.

The assumption for bundles is that once a semantic config is validated using the Config component, they can use it safely to configure their code. If you suggest Symfony to accept values, then this assumption gets broken. Symfony cannot abstain. Either it accepts the value when processing the config, or it rejects it.

Side note: We already deprecated the config for trusted_proxies in the FrameworkBundle config in 3.3, asking to mutate the Request global state from the front controller rather than during bundle boot. We should have done the same for trusted_hosts and http_method_override. The request can be used before booting the kernel (for instance when using AppCache. In such case, relying on the FrameworkBundle config is broken.

@dtfafard
Copy link

dtfafard commented Nov 9, 2018

By design :)

trusted_hosts is a protyped scalar array, which is incompatible with env vars (we dont know it's an array of scalars, as such we dont allow it). Env values can be anything, and we get minimal info from the prefix.

To support this, we need that info. So with a notation like %env(string[]:json:ENV)% it could be possible, as suggested here: #28137 (comment)

Hi guys,

Please help me understand how can "by design" go from allowing the use of arrays in configs to not allowing the use of arrays using environment variable. The solution proposed is to add an environment variable for each array and then add a new array item in the config as such :
# config/mybundle.yaml
mybundleconfig:
- parameter1: '%env(ENV_VAR_1)%'
- parameter2: '%env(ENV_VAR_2)%'

I believe this solution is not scalable and removes the option of dynamism. What if I want 2 emails on my dev environment, but I want 3 on my production environment. Of vice versa.

I would like a replacement that will allow the use of a scalable structure such as the following :
#config/mybundle.yaml
mybundleconfig:
parameter: ['a', 'b', 'c']

What is the solution proposed?

@dtfafard
Copy link

dtfafard commented Nov 22, 2018

Hi guys,

I've managed to make the code work manually overwriting :

// In Symfony\Component\Config\Definition\ArrayNode
    /**
     * {@inheritdoc}
     */
    protected function allowPlaceholders(): bool
    {
        return false;
    }

// to 


    /**
     * {@inheritdoc}
     */
    protected function allowPlaceholders(): bool
    {
        return true;
    }

// and
//In Symfony\Bundle\FrameworkBundle\DependencyInjection\Configuration
->beforeNormalization()->ifString()->then(function ($v) { return array($v); })->end()
                    ->prototype('scalar')->end()

// to 

->beforeNormalization()->ifString()->then(function ($v) { return $v; })->end()
                    ->prototype('scalar')->end()

No errors were thrown. The goal would be to find a way to overwrite them without directly editing the Vendors.

@ro0NL
Copy link
Contributor

ro0NL commented Nov 22, 2018

See #29270 for a different approach :)

@fabpot
Copy link
Member

fabpot commented Aug 6, 2019

Closing in favor of #29270

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants