Different security.yml files for different environments - php

I could not manage to find a way to include different security.yml files that would be included depending on Symfony2`s environment. For example I wanted to have an in-memory user provider for my acceptance tests, cause I don't really need to test my entities and stuff here, I only want to make an acceptance test for my views.
But, as it turned out, it's not an easy thing to do. I removed security.yml from includes in my config.yml, renamed it to security_prod.yml and created a security_test.yml which has the in_memory user provider. Then I've included security_prod.yml and security_test.yml in my production and testing configs respectively.
Yet it does not seem to work at all:
$ SYMFONY_ENV=test app/console cache:clear
[Symfony\Component\Config\Definition\Exception\InvalidConfigurationException]
You are not allowed to define new elements for path "security.providers". Please define all elements for this path in one config file.
$ SYMFONY_ENV=prod app/console cache:clear
[Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException]
Configuration path "security.access_control" cannot be overwritten. You have to define all options for this path, and any of its sub-paths in one
configuration section.
It appeared to me like the security.yml filename was hardcoded (which would be way too weird for Symfony), and it wasn't.
So the question is: how do I get multiple security.ymls with Symfony? And what could be causing this behaviour?

Instruction for those, who is looking for it (and do not red comments):
Create different config files for different environments: config_test.yml, config_dev.yml, config_prod.yml
Create different security files: security_test.yml, security_dev.yml, security_prod.yml
Import security_test.yml in config_test.yml and so on for other environments. Example for config_test.yml:
imports:
- { resource: security_test.yml }
Make sure you included security_*.yml only once (basically author did this mistake)

Related

I have to replicate all config file for each environment

I try to add some config in config/* directory.
I'll use a very simple example, to illustrate the problem, but keep in mind that this problem occur for every .yaml config files for any services. I am not able to make inheritance between config files.
So in services.yaml I have this code :
#config/services.yaml
parameters:
app.debug: 0
smtp.user: ''
app.locale: '%kernel.default_locale%'
app.product.number_per_page: 20
container.dumper.inline_factories: true
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
bind:
$locale: '%kernel.default_locale%'
$product_per_page: '%app.product.number_per_page%'
And then i try to access $product_per_page into my controller :
#src/Controller/myController.php
public function listProduct(int $product_per_page){
dump($product_per_page);
die();
}
When I execute this code, it give me the following errror :
Could not resolve argument $product_per_page of
"App\Controller\ProductController::listproduct()", maybe you forgot to
register the controller as a service or missed tagging it with the
"controller.service_arguments"?
So I have to copy this config files (config/services.yaml), and then paste it into config/services_dev.yaml, services_prod.yaml, services_test.yaml
And then it is working, but this is not suitable at all...
Because I have to do that for every config files... So i copy and paste in every environnement each time I update ANY configuration.
Of course, I have try to cache:clear and composer update, but nothing do.
I was expecting Symfony read the file as explain here but it is not working for me.
I have try to create another Symfony project, and now it is working in this one. But I want to understand what is wrong ? Is there a thing I have done which have result into a bug that cannot being correct even ater updating Symfony, even after having update composer, even after having clear the cache.
I can't believe there's nothing to do but to create a new Symfony project in which you copy the files from the old one.

Custom configuration file for Symfony project

My goal is to add to a new Symfony 4.4 project an extra config file to define some behavior of the system. It could be anything, like, pancakes.yaml:
pancakes:
enablePancakes: false
I wish to know how can I load that config file. find a way to read its parameters and values to change some custom behavior the system might have but honestly I think I'm not smart enough to understand what the documentation says.
For now it could be anything, like printing the configuration file values, for now I only need to know how to load it.
you can update the following file :
# config/service.yaml
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
parameters:
locale: 'en'
chat_update_interval: 10000
and use service decoration in your new application to override your parameters.

Symfony 4, .env files and production

.env files are very handy with docker, kubernetes, etc
But what if I have simple nginx server without any orchestration and a pack of cron workers and a pack of daemons(systemd/supervisord/etc)?
I can write these env variables to nginx server section, but I have to set up hundreds of env variables to each cron worker or daemon.
I found a quick solution: using symfony/dotenv component in production.
But it seems to me dirty. Who can suggest better solution?
First of all, not all variables need to be specified using environment variables. Keep variables that do not differ per system in a separate yaml file.
When you have just one environment per server you can specify the environment variables globally in /etc/environment. (Might be different depending on your Linux flavour)
Personally I find that using DotEnv poses more difficulties than solutions when you run multiple environments on the same server. Specifying the variables in a global configuration like /etc/environment doesn't work in that case.
Specifying the environment variables in nginx isn't a solution either since, as you mentioned, they won't be picked up by cron, supervisor, the console, etc. For me, this was the reason to completely remove DotEnv and work with the good old parameters.yaml file again. Nothing will stop you from doing that.
Another solution however is to keep using DotEnv in your development environment and to include a separate parameters.yaml in production. You can then define the environment variables as follows:
parameters:
env(APP_ENV): prod
env(APP_SECRET): 3d05afda019ed4e3faaf936e3ce393ba
...
A way to include this file is to put the following in your services.yaml file:
imports:
- { resource: parameters.yaml, ignore_errors: true }
This way, the import will be ignored when no parameters.yaml file exists. Another solution is to add a line to configureContainer() in your Kernel class:
$loader->load($confDir.'/parameters'.self::CONFIG_EXTS, 'glob');
if you want to centralize your environment variables for cli and fpm you can define them once in your system. And then reference them all in your php-fpm.conf:
....
[www]
env[APP_VAR1] = $APP_VAR1
env[APP_VAR2] = $APP_VAR2
...
In that way you can avoid using DotEnv in production which is encouraged by best practices.
Hope this helps.

Change default configuration file of Symfony2 project

Context
I have a simple Symfony2 project (only command line commands). This project includes an app/config.yml file, containing information used for dependency injection creation.
For example, app/config.yml contains:
github:
token: abcdefgh
And src/Foo/Resources/config/github.yml (services files) contains:
services:
github.client:
class: Github\Client
calls:
- ['authenticate', [%github.token%, null, 'http_token']]
The file app/config.yml is loaded by Application::__construct() function.
When I run app/console mycommand, it uses the defined token.
Needs
I need to be able to run my commands using different configurations.
For now, I replace manually the app/config.yml file, but it's crappy.
To do this, I thought about 2 possible solutions:
Be able to specify another app/config.yml file when I run app/console mycommand --f=app/config2.yml.
Have another configuration file for specific command usage, and use it with app/console mycommand --f=myconfig.yml. The thing is the dependency injection can not work or be updated after the application is run.
I don't know how to do one of this solution (or a third one, no matters). If it's a common behavior, can you point me some documentation or example to do something like this?
It is totally possible by using different environements, check out the doc :
http://symfony.com/doc/current/cookbook/configuration/environments.html
Typically you will specify the environement using --env=myenv.

Access to the base_path of a particular Asset directory from a controller

I want to access the base_path (base_url registered) of a specific Asset component directory from a controller in order to store my reports to a specific path preconfigured in config.yml.
I started changing my configuration, after upgrading to Symfony 2.7, like the following:
app/config/config.yml
framework:
assets:
version: 'v5'
version_format: '%%s?version=%%s'
base_path: ~
base_urls: ['http://cdn.example.com', 'https://secure.example.com']
packages:
reports:
base_path: bundles/mybundle
So, when I request a specific route, with the correct request parameters my controller generate the HTML from a particular Twig template and, at the end, it will be converted to PDF using KnpSnappyBundle.
At last, my purpose is to build a list of generated PDF reports accessible from a public assets directory.
$kernel->locateResource()
However, I can access the complete path using a workaround like the following:
$this->container->get('kernel')->locateResource('#MyBundle/Resources/public/reports')
Using parameters.yml
I have also asked for some hints and it seems legit to use the parameters.yml in order to manage the Asset component configuration. So, from the controller, they would be accessed using $this->getParameter() and, at the same time, as a configuration value for Asset.
The simplest way to deal with that is to define it as a parameter in parameters.yml, as you suggested yourself.
It's really easy to get it and it totally makes sense.
Update
I wanted to provide a bit more reasoning for my answer, so I will cite http://symfony.com/doc/current/best_practices/configuration.html as a reference.
Reading there, it seems that you should put into "parameters.yml" all infrastructure parameters which do not really change your application behaviours. I think this applies to your case as well: your application does not change its behaviour according to assets paths, it only needs to know where they are.
So, again, I'd say that putting them in parameters.yml not only provides you an easy solution but also it's a "good practice".

Categories