Environment specific configuration in zend


In software development life cycle, we generally need different type of environments for different purpose like – “development”, “testing”, “production” etc.

And all these environments has some environment specific configuration. like in development server “display error” will be on and payment mode will be “testmode” But in production server “display error” will be off and payment mode will be “livemode” In production server error logging will be on but in testing server it may not be on. Database connection will be different for each environment. etc etc…

Problem:

Its been a big headache to server management team to modify configuration files each time code update to any server.
Here we have created multiple configuration files for each server and automatically loaded environment wise configuration file using “zend-framework”.

Solution:

Here we will consider 3 environment- “Production”, “QA” and “Development” in order to explain the process.
So we will create 4 ini files:
common_config.ini: to keep common configuration (which don’t change with environments)
app_prod.ini: “Production” server specific configuration
app_QA.ini: “QA” server specific configuration
app_dev.ini: “Development” server specific configuration

common_config.ini:

[Production]
phpSettings.error_log = [path to file] "/application.log"

includePaths.application = APP_PATH
includePaths.library = APP_LIB

bootstrap.path = [path to file] "/Bootstrap.php"
bootstrap.class = "Project_Bootstrap"

autoloadernamespaces.0 = "Project"

resources.frontController.moduleControllerDirectoryName = "controllers"
resources.frontController.moduleDirectory = [path to file] "/modules"

resources.frontController.defaultControllerName = "index"
resources.frontController.defaultAction = "index"
resources.frontController.defaultModule = "account"
[QA : Production]
[Development : Production]

Look at last 2 lines- it is saying QA and Development server both will extend configuration from Production.

app_prod.ini:

[Production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
phpSettings.log_errors = 1

;payment related credentials
payment.mode = "liveMode"
;db configuration
resources.db.adapter = "Pdo_Mysql"
resources.db.params.host = "localhost"
resources.db.params.username = "user1"
resources.db.params.password = "pass1"
resources.db.params.dbname = "db_prod"

app_QA.ini:

[QA]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
phpSettings.log_errors = 1

;payment related credentials
payment.mode = "testMode"
;db configuration
resources.db.adapter = "Pdo_Mysql"
resources.db.params.host = "localhost"
resources.db.params.username = "user2"
resources.db.params.password = "pass2"
resources.db.params.dbname = "db_qa"

app_dev.ini:

Similar to QA. you now know what will be in this configuration file. 🙂

So we made ready all configuration files. Now need to load proper configuration for environments.
index.php file will contain something like this:

 

defined('COMMON_CONFIG_INI_PATH') || define('COMMON_CONFIG_INI_PATH',
        [path to file] . '/Config/common_config.ini');

// set APP_INI_PATH according to environment
switch (APP_ENV) {
    case 'Production' :
        defined('APP_INI_PATH') || define('APP_INI_PATH',
            [path to file] . '/Config/app_prod.ini');
        break;
    case 'QA' :
        defined('APP_INI_PATH') || define('APP_INI_PATH',
            [path to file] . '/Config/app_QA.ini');
        break;
    case 'Development' :
        defined('APP_INI_PATH') || define('APP_INI_PATH',
            [path to file] . '/Config/app_dev.ini');
}

defined('APP_LOG_PATH') || define('APP_LOG_PATH',
        realpath(dirname(__FILE__) . '/../logs'));

//Bootstrap the application
require_once('Zend/Application.php');
//load zend_app with config file and run
$application = new Zend_Application(APP_ENV,
        array(
            'config' => array(
                        COMMON_CONFIG_INI_PATH,
                        APP_INI_PATH
                       )
             )
    );
$application->bootstrap()->run();

So here we we have set 2 constant for configuration files according to environment: COMMON_CONFIG_INI_PATH and APP_INI_PATH
and loaded these 2 configuration while bootstrapping.

You are done. Nothing more. Simple, isn’t it? 🙂

Advertisements

CONSTRUCTOR and DesTruCtoR in php


As a developer “Constructor” is very common to us and we use it very frequently. But do we know what is destructor and when to use it?

Yes the names describe their meanings themselves. Constructor and destructor are 2 methods of a class which are called at the time of object construction and destruction respectively.

Constructor:

How to create:

Generally the way of creating a constructor is creating a method, name of which is same as class name.

For Example:

class foo {
    function foo()
    {
        // PHP 4 style constructor
    }
}

Whereas PHP5 introduce a new magic method “__construct()” to declare a constructor.

The benefit of this method is if sometime we need to change the name of class, we don’t need to change the name of constructor.

For Example:

class newFoo {
    function __construct()
    {
        // PHP 5+ style constructor
    }
}

PHP5 first searches for magic method style constructor. If not present, it searches for a method, same name with class name. So, both style works.

Why to use:

Constructors are useful for initializing an object’s properties, or for performing startup procedures. For example, need to connect to database or set some specific set of configuration or fetch some remote file and cache it for quick usage.

Destructor:

How to create:

PHP 5 introduces a destructor concept similar to OOP concept. Magic method “__destruct()” is used to declare a destructor.

For Example:

class foo {
    function __construct()
    {
        echo ‘Constructor called’. PHP_EOL;
    }
    function __destruct()
    {
        echo ‘Destructor called’;
    }
}
new foo();

This code will display:

Constructor called
Destructor called

REMEMBER that destructor will not be called till the last reference of the object is gone, and this may not take place when you want or expect it.

For Example:

$obj1 = new foo();
$obj2 = $obj1;
unset($obj1);

This one will not call destructor as even if $obj1 is getting unset, another reference is still present.

Why to use:

Its mainly useful for performing cleanup procedures, such as disconnect remote connection, remove temporary files etc.

Hope this will help to effectively use constructor and destructor. 🙂

 

References:
http://php.net/manual/en/language.oop5.decon.php
http://www-numi.fnal.gov

Common Session Attacks (Session Fixation and Session Hijacking)


We developers use session protected functionality to restrict unwanted access, to provide security.  Do we know there are 2 very popular session attacks?

In the first type of attack, attacker can hijack any user’s session and use that same session to grab illegal privilege. This is called “session hijacking”.

In the second type of attack, attacker tricks to use her own specified session to victim which in turn disclose victims valuable details. In this way attacker fixes victim’s session, hence called “session fixation”.

In the both ways the main target is to use the same session which victim is using.

Procedure of Attack:

Except the initial step both type are same.

Session Fixation: This process starts before victim logs in. First atacker logs into the system and receive a valid session identifier (say sessionid = abcd). now attacker sets the victim’s session even bofore victim logs in.

Fixation

Following are 2 basic way to trick user-

http://anywebsite.com/<script>document.cookie=”sessionid=abcd”;</script>
http://anywebsite.com/<meta http-equiv=Set-Cookie content=”sessionid=abcd”>

Now if victim clicks on this type of link their session set to “abcd”. Now when victim logs in, same session id gets associated to his session.

Session Hijacking: In this process attacker try to grab a session which victim is using.

Following are few basic way to attack-

using cross site scripting –

<SCRIPT>alert(document.cookie);</SCRIPT>

Man-in-the-middle attack
Man-in-the-browser attack

Now the attacker impersonate as victim as she is using same session as victims session, and do whatever she wants.

Prevention:

Session Fixation:

-> Since Session Fixation starts before login, we can create a new session whenever an user logs in, hence preventing using of an existing session.
-> Use session_regenerate_id();

Session Hijacking:

Session hijacking cannot be directly prevented, however we can put steps in to make it very difficult and harder to use. Remember how difficult we can make it, attacker will leave and look for a softer target

-> Use a strong session hash identifier: session.hash_function in php.ini. If PHP < 5.3, set it to “session.hash_function = 1” for SHA1.
If PHP >= 5.3, set it to session.

hash_function = sha256

or

session.hash_function = sha512

-> “session.hash_bits_per_character = 5” in php.ini. When the attacker tries to guess the session identifier the ID will be shorter, but uses more characters.
-> Change the default session name from PHPSESSID to something else.
-> Save $_SERVER[‘HTTP_USER_AGENT’] in session and check in every request for user agent.

Defend attackers 🙂

References:
http://shiflett.org/articles/session-hijacking
https://www.owasp.org/index.php/Session_fixation
http://stackoverflow.com/questions/5081025/php-session-fixation-hijacking

Parallel Download Link


Parallel vs Serial – fighting continues.

Note that for smaller files it doesn’t matter much. But in case of bigger files it really does.

Case 1: 4113-thumb
Lets say we have download links for songs. So the user may want to download one by one, as in this way single file download is faster and user can start listening while other are getting download.

Case 2:
Now suppose our download links provide zipped reports. And those reports will be analyzed later. Another example can be your site provide online courses. When a user going through online tutorial he may download all the resources and assignments. In these cases user may want to download all the files parallel.

Generally we use this type of code to implement download functionality.

header('Content-Type: audio/mpeg3');
header('Content-disposition: attachment; filename=' . $filename);
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($path));
ob_clean();
flush();
readfile($path);

Now if you access more than one download link, you may find that when first download is on the process others are not started. After completion of first download second one gets started and so on..

To make all download parallel use this simple trick –

session_write_close();

at the top of the method.

What it does?

According to PHP’s session handling, using the default session handler, when a PHP script opens a session it locks it. Subsequent scripts that need to access, it have to wait until the first script is finished with it and unlocks it (which happens automatically at shutdown, or by session_write_close() ). So here session_write_close() simply unlocks the session.

Hope this will help 🙂

Efficient Bulk insert into database with foreign key relation


We will try to find here a better way of inserting data into database table from some csv or xls lists.

Lets say we have a list of users in a csv and need to import it in database table name “user” using php.

user table has following column

'id' (PrimaryKey, AutoIncrement), 'name', 'age'

So simply we can do a batch insert like

INSERT INTO `user` (name,age) VALUES ('John','20'),('Donald', '25') ...

Now lets say we have another table called “user_contact” to store contact detail of user.

user_contact table has following column

'id' (PrimaryKey, AutoIncrement), 'user_id' (foreign key of id of user table), 'address', 'phone'

And we have csv with column

'name', 'age', 'address', 'phone'

Now we are thinking how to import this data in a efficient way.

First Approach: images

1) create a new list1 using ‘name’ and ‘age’
2) Insert 1 by 1 value in ‘user’ table, get id and create a new list2 using ‘user_id’, ‘address’, ‘phone’
3) Batch insert in user_contact table using list2.

Problem in First Approach:
In case of user table if there are 1000 rows, it will insert 1000 times (very bad).

Second Approach:

1) Lock the user table.
2) Get the current autoincrement value (lets say 5).
3) Create a new list1 using ‘name’ and ‘age’ and do a batch insert.
4) Release lock.
5) Now we know our user_id will start from 5 and go on sequentially. So create a new list2 using

'user_id', 'address', 'phone'

6) Batch insert in user_contact table using list2.

Good and Bad:
Batch insert is faster according to http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html (Good) 🙂
Table will be locked for a longer time and other inserts will be waiting to complete this. (BAD) 😦

Better Approach:

1) Lock the user table.
2) Get the current autoincrement value (lets say 5).
3) Increase the auto-increment value according to our need. For 1000 row insert we need to make the new auto increment value to (5+1000) = 1005
4) Release lock.
5) Create a new list1 using ‘id’, ‘name’ and ‘age’ and do a batch insert.
6) Create a new list2 using ‘user_id’, ‘address’, ‘phone’
7) Batch insert in user_contact table using list2.

Table will be locked for very less time, i.e., read current autoincrement value and set to new one.

SOME NOTES:

Transaction or lock sometime gives a better performance while doing inserts. Because the index buffer is flushed to disk only once. http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html

We have looked into the approach here, not the code. To get and set auto-increment using php could be –

$query = mysql_query("SHOW TABLE STATUS LIKE 'aitest'");
$row = mysql_fetch_array($query);
$next_id = $row['Auto_increment'];
$no_of_records = 10;
$sql = "ALTER TABLE aitest AUTO_INCREMENT = ".$next_id+ $no_of_records.";";
$query = mysql_query($sql);

Use “LOAD DATA INFILE” to get a massive performance gain.

Help database server – help yourself 🙂

New “unix Bash security hole”, deadlier than “Heartbleed”


images2A big unix bash hole (“Shellshock”) uncovered on 24thSep 2014, which can be used to take control of your unix based system.

Bash is the very powerful software to control unix based systems via command line. And if this powerful weapon reaches to an unwanted person, everything can be sacrificed.

The Department of Homeland Security’s United States Computer Emergency Readiness Team, or US-CERT, issued an alert saying the vulnerability affected Unix-based operating systems including Linux and Apple Inc’s Mac OS X.

Is your system vulnerable ?

As per an excellent write-up by RedHat, to check if your system is vulnerable, type below commands in bash.

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

If you see an output like

vulnerable
this is a test

You need a patch to fix it.

It is relatively easy to use this hole.

Tod Beardsley, an engineering manager at cybersecurity firm Rapid7, warned the bug was rated a “10” for severity, meaning it has maximum impact, and rated “low” for complexity of exploitation, meaning it is relatively easy for hackers to launch attacks.

Fix it!

US-CERT advised computer users to obtain operating systems updates from software makers. It said that Linux providers including Red Hat Inc (RHT.N) had already prepared them, but it did not mention an update for OS X. Apple representatives could not be reached.

To update it a similar type of command can be run

yum update bash

After a patch, if you run above command, you will find a output similar to

env x='() { :;}; echo vulnerable'  bash -c "echo this is a test"
bash: warning: x: ignoring function definition attempt
bash: error importing function definition for `x'
this is a test

For MAC users:
http://security.stackexchange.com/questions/68202/how-to-patch-bash-on-osx-in-wake-of-shellshock
Unlike Heartbleed, Shellshock doesn’t appear to have any easy solutions for average users right now. In most cases, it will be up to system administrators and software companies to issue patches.

Know more:

https://securityblog.redhat.com/2014/09/24/bash-specially-crafted-environment-variables-code-injection-attack/

http://www.reuters.com/article/2014/09/24/us-cybersecurity-bash-idUSKCN0HJ2FQ20140924