oriolrius.cat

Des del 2000 compartiendo sobre…

Tag: front-controller

symfony: protegint els entorns de desenvolupament, integració i producció

Reading time: 7 – 12 minutes

A l’article symfony: entorns de desenvolupament, integració i producció es pot entendre el perquè de treballar amb aquests tres espais de noms (environment) així doncs el que es preten explicar és:

  • Impedir accés a les aplicacions en entorns de ‘dev’ i ‘int’ des de llocs no controlats. O sigui, que una IP d’internet no pugui executar myapp_dev.php o myapp_int.php però encanvi una IP de la xarxa del desenvolupador si que pugui.
  • Impedir accés a aplicacions de backend des de l’entorn de producció. Si hem desenvolupat alguna aplicació per tal de fer el manteniment de l’aplicació principal, una part d’administració o backend aquesta no sigui accessible des d’IPs no controlades.
  • Separar el fitxer de configuració config/cofnig.php per cada un dels entorns. Així podem definir constants o d’altres tasques de forma particular per cada un dels entorns.

Per tal d’aconseguir aquests objectius he creat el fitxer config/config.lib.php:

<?php
/**
 * Comproba si la IP amb la que s'accedeix a l'aplicació permet connectar en aquest environment
 *
 * @param string $env nom de l'environment
 * @param array $ips ips des de les que podem accedir a l'environment
 * @param string $clientip ip del client que vol accedir al recurs
 */
function envCorrecte ($env,$ips,$clientip)
	{
	if (SF_ENVIRONMENT==$env)
	{
		$acces=0;
			foreach($ips as $ip)
		{
			$ipclient=substr($clientip,0,strlen($ip));
				if ($ipclient==$ip)
			{
				$acces=1;
				}
		}
		if ($acces==0)
			{
			echo "You are not in '".$env."' environment! (".$ipclient."<>".$ip.")";
				exit;
		}
	}
}
/**
 * Comproba si l'aplicació amb la que s'accedeix al projecte és publica o no
 *
 * @param array $apps llista d'aplicacions no públiques
 * @param array $ips llista d'IP amb les que es pot accedir a les apps no públiques
 * @param string $clientip ip del client que vol accedir al recurs
 */
function appCorrecte ($apps,$ips,$clientip)
	{
	// solucionem problema de la clau '0'
    	$apps_aux[0]='';
		$apps = $apps_aux + $apps;
	//
	if (array_search(SF_APP,$apps)!=false)
		{
		$acces=0;
		foreach($ips as $ip)
			{
			$ADR=$HTTP_SERVER_VARS['REMOTE_ADDR'];
			$ipclient=substr($clientip,0,strlen($ip));
				if ($ipclient==$ip)
			{
				$acces=1;
				}
		}
		if ($acces==0)
		{
				echo "Keep away! ".SF_APP." is not a public application!";
			exit;
		}
		}
}
?>

Llavors des del fitxer config/config.php cal que cridem aquesta petita llibreria de funcions que he creat. La resta és més que lògica, aquí en teniu un exemple:

<?php
include("config.lib.php");
/**
 * Controlem accés als 'environments' de 'env' i 'int'
 */
$ip_dev=array("10.138.0.","192.168.");
$ip_int=array("10.138.0.","192.168.");
envCorrecte('env',$ip_env,$HTTP_SERVER_VARS['REMOTE_ADDR']);
envCorrecte('int',$ip_int,$HTTP_SERVER_VARS['REMOTE_ADDR']);
/**
 * Controlem accés a les 'apps' d'ús privat
 */
$ip_apps=array("10.138.0.","192.168.","w.x.y.z");
$apps=array('myapp_1','myapp_2','myapp_n');
appCorrecte($apps,$ip_apps,$HTTP_SERVER_VARS['REMOTE_ADDR']);
/**
 * Carreguem el fitxer de configuració propi de l'"environment".
 */
include("config.".SF_ENVIRONMENT.".php");
/**
 * Part comú en els 3 entorns
 */
?>

Com podeu veure el codi és molt senzill i la potència i el dinamisme, excepcionals.

Aquest codi també l’he publicat com un snippet a Access control to environment and applications and custom global config file for an environment.

symfony: entorns de desenvolupament, integració i producció

Reading time: 3 – 4 minutes

Al desenvolupar un projecte de software m’agrada treballar en 3 entorns. Mentre s’esta desenvolupant el projecte esta bé tenir un espai de variables (o entorn de noms) a l’aplicació que correspongui als ajustaments del servidor de desenvolupament (normalment una màquina pròpia), per exemple, els path, urls, dades de la bbdd, etc. tot això ha d’estar el màxim separat possible del codi per tal de poder crear les configuracions pels entorns d’integració i producció.

L’entorn d’integració és una màquina en l’entorn de desenvolupament del client, amb les característiques el més semblants possibles a l’entorn de producció. O sigui, les dades de configuració de l’espai de noms han d’apuntar a serveis si pot ser de la mateixa versió que l’entorn de producció. Així podem provar l’aplicació i millores de l’aplicació abans de passar-la a producció. Finalment hem de tenir l’entorn de noms per producció amb les dades de treball.

Per tal de suportar tot això symfony suporta en moltíssims fitxers de configuració la possibilitat de definir l’environment, en el cas que plantejo, ‘dev’, ‘int’ i ‘prod’. En el front controller de cada aplicació podem definir aquest entorn de noms així després s’accedirà a la part dels fitxers de configuració que pertoca.

Per exemple, si mirem el fixer config/databases.yml on symfony defineix els sistemes de BBDD que usa la nostre aplicació en cada un dels environments podriem tenir algo així:

dev:
  nombbdd:
    class:           sfPropelDatabase
    param:
      phptype:       mysql
      hostspec:      localhost
      database:      nombbdd
      username:      userbbdd
      password:      passbbdd
int:
  nombbdd:
    class:          sfPropelDatabase
    param:
      phptype:      oracle
      username:     nombbdd
      password:     nombbdd
      hostspec:     hostint
      database:     NULL
prod:
  nombbdd:
    class:          sfPropelDatabase
    param:
      phptype:      oracle
      username:     nombbdd
      password:     nombbdd
      hostspec:     hostprod
      database:     NULL

Al cridar el front controller és quan symfony diu amb quin environment treballarem, per exemple, per una aplicació anomenada myapp podriem tenir aquests tres front controllers un per cada entorn:

Entorn de desenvolupament web/myapp_dev.php:

<?php
define('SF_ROOT_DIR',    realpath(dirname(__FILE__).'/..'));
define('SF_APP',         'myapp');
define('SF_ENVIRONMENT', 'dev');
define('SF_DEBUG',       true);
#
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
#
sfContext::getInstance()->getController()->dispatch();
?>

Entorn de integració web/myapp_int.php:

<?php
define('SF_ROOT_DIR',    realpath(dirname(__FILE__).'/..'));
define('SF_APP',         'myapp');
define('SF_ENVIRONMENT', 'int');
define('SF_DEBUG',       true);
#
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
#
sfContext::getInstance()->getController()->dispatch();
?>

Entorn de producció web/myapp.php:

<?php
define('SF_ROOT_DIR',    realpath(dirname(__FILE__).'/..'));
define('SF_APP',         'myapp');
define('SF_ENVIRONMENT', 'prod');
define('SF_DEBUG',       false);
#
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
#
sfContext::getInstance()->getController()->dispatch();
?>

Com es pot veure, tan desenvolupament com integració ens mostraran informació de debug i producció amagarà els missatges d’error i reportarà sempre l’error “internal server error”. A més podem veure que tots tres entorns criden el mateix fitxer de configuració global config/config.php.

Si voleu més informació sobre aquest tema us recomano els següents enllaços de la documentació de symfony: