Securing the development frontend
One of the nice features of symfony is the ability to use different "loaders" for symfony that activate certain aspects of symfony. The main use of this is the development frontend, which greatly eases development by adding a little panel inside the output of HTML pages with debug information. However symfony requires these frontends to all reside inside the main web directory which obviously poses security issues. As a result these alternate frontends should not be put on production machines in the default location.
There are a number of solutions to solve this security risk, while still being able to leverage these frontends during development and even on the production machines. The below list was compiled from a thread on the developers list. Each approach has its own strengths and weaknesses, so the suggestions are not made in any particular order.
Suggestion 1: Symlink on demand
Move the development frontends into a separate directory and symlink them into the web directory as needed. When using this approach on production machines, you should at the very list use a non-standard name in the symlink. However, this is obviously "security through obscurity" (so not very secure). In case any automatic rsyncing solutions are used, additional precautions should be taken to prevent automatic propagation of these files to other servers.
Suggestion 2: Set variables in vhost
By using a virtual host ("vhost"), you can set the application, environment and debugging mode. The frontend code would need to be modified as follows:
<?php define('SF_ROOT_DIR', realpath(dirname(__FILE__).'/..')); define('SF_APP', isset($_SERVER['SF_APP'])?$_SERVER['SF_APP'] : 'frontend'); define('SF_ENVIRONMENT', isset($_SERVER['SF_ENVIRONMENT'])?$_SERVER['SF_ENVIRONMENT'] : 'prod'); define('SF_DEBUG', isset($_SERVER['SF_DEBUG'])?(bool)$_SERVER['SF_DEBUG'] : false);
A sample vhost for Apache could look like this:
<VirtualHost *:80>
ServerName domain.com
ServerAlias www.domain.com
ErrorLog logs/domain_com-error.log
CustomLog logs/domain_com-access.log common
DocumentRoot /var/www/vhosts/domain.com/web
<Directory /var/www/vhosts/domain.com/web>
Order allow,deny
Allow from all
Options +FollowSymLinks +ExecCGI
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]
</Directory>
Alias /sf /var/www/vhosts/domain.com/lib/vendor/symfony/data/web/sf
<Directory /var/www/vhosts/domain.com/lib/vendor/symfony/data/web/sf>
Order allow,deny
Allow from all
</Directory>
SetEnv SF_APP frontend
SetEnv SF_ENVIRONMENT dev
SetEnv SF_DEBUG 1
</VirtualHost>
Note the three SetEnv lines and the corresponding $_SERVER[] expressions.
Suggestion 3: Limit access using SSL certificates
You can can limit access to specific URLs in the vhost, so frontend_dev.php could only be accessible to users presenting a client SSL certificate. You can find information on how to set this up over here.
Suggestion 4: Adapt url/asset helper url generation
You can make it possible to place the development frontends into a different directory, which can then be secured/exposed as required. Unfortunately, in Symfony 1.0.x this approach requires a fair number of hacks. Symfony 1.1 will make it easier to change behavior in the url and asset helpers.
1) Add a constant in the given front controllers that enables the host rewriting:
<?php define('SF_REWRITE_ASSET_HOST', true);
2) Add a filter that rewrites the location (for most applications there will be a need to initialize the session, making sure that non authenticated users are directed at the right page, that the language/country cookie is set properly etc., which seems like a goof location for this code):
<?php class initSessionFilter extends sfFilter { /** * Execute filter * * @param FilterChain $filterChain The symfony filter chain */ public function execute($filterChain) { if ($this->isFirstCall()) { $context = $this->getContext(); $request = $context->getRequest(); $user = $context->getUser(); $action = $context->getActionStack()->getLastEntry()->getActionInstance(); if (defined('SF_REWRITE_ASSET_HOST') && SF_REWRITE_ASSET_HOST) { $asset_host = sfConfig::get('app_config_rewrite_asset_host'); if (substr($asset_host, 0, 4) === 'http') { $request->setRelativeUrlRoot($asset_host); } elseif (preg_match('/s(\/.+\/)(.*)/', $asset_host, $matches)) { $request->setRelativeUrlRoot(preg_replace($matches[1], $matches[2], $request->getRelativeUrlRoot())); } else { $request->setRelativeUrlRoot($request->getRelativeUrlRoot().$asset_host); } } .. } } }
3) Add 'app_config_rewrite_asset_host' to your app.yml file
all:
config:
# rewrite_asset_host: 'http://foo.bar'
# rewrite_asset_host: 's/admin\./'
rewrite_asset_host: '/../web'
Remember that you can have different configuration settings per environment and per server (following the above guidelines). However, there is a problem with this solution if the no_script_tag feature is disabled, because in that case the url helpers will use the $request->getRelativeUrlRoot() to construct the url. In that case you also need to do some further hacking:
4) First you need to store the original relative url root in a constant before modifying the value in your filter. Then you need to open up and store lib/symfony/controller/sfWebController.class.php in your application lib directory and modify the genUrl() method. Look for the call to getRelativeUrlRoot() and change the section of the code as follows:
<?php $url = ''; if (!sfConfig::get('sf_no_script_name')) { $url = $this->getContext()->getRequest()->getScriptName(); } else if ($sf_relative_url_root = $this->getContext()->getRequest()->getRelativeUrlRoot()) { $url = (defined('RELATIVE_ROOT_URL')) ? RELATIVE_ROOT_URL : $sf_relative_url_root; }

