How to restrict php directives using php_admin_value and php_admin_flag

Let’s say you are dealing with a shared Apache server running PHP as an Apache module, you have several websites running, and you don’t want to let some php directives being changed. You allow the modifications of the directives such as  display_errors but you don’t want memory_limit to be changed by any of the users (let’s say 128M) also, you don’t want to say that your server runs PHP (i.e expose_php off).

It’s possible to change the values of the php.ini directives in three differents ways:

  • apache configuration (i.e virtualhost(s), apache2.conf, etc …)
  • .htaccess (if AllowOverride Options or AllowOverride All)
  • ini_set function

There are two ways to force the values of the php directives and make them unchangeable from .htaccess or with ini_set function.

php_admin_value <setting> <value>

This one forces a directive to a certain value (non boolean), for example:

php_admin_value memory_limit 128M

We force memory_limit to 128M.

php_admin_flag <setting> <on|off>

This one does the same but for a boolean value, for example:

php_admin_flag expose_php off

There the directive expose_php will be unset.

To do this for ALL the websites on your server, you can edit your /etc/apache2/apache2.conf (may change if you have httpd) and put this content at the end:

Include php_restrictions

Create the file  /etc/apache2/php_restrictions, and add this content:

php_admin_value memory_limit 200M
php_admin_flag expose_php off

You can add as many rules as you wish, then reload your webserver like that (may change if you have httpd):

/etc/init.d/apache2 reload

To do this for only ONE specific website (i.e virtualhost), just set the rules inside the virtualhost like that:

NameVirtualHost www.test.com:80
<VirtualHost www.test.com:80>
    ServerName test.com
    ServerAlias www.test.com 
    DocumentRoot /var/www/test
    # now the rules
    php_admin_value memory_limit 128M
    php_admin_flag expose_php off
</VirtualHost>

This will apply only to the www.test.com website.

Then you need to reload the webserver too.

Voilà, you have restricted some directives and some others are still changeable.

Though, some directives cannot be changed inside apache2.conf or virtualhost(s), you may check the documentation .

How to deal with several ssh keys easily

Hello, this post will be about how to use several ssh keys in a “simple” way.

I had the problem of having several ssh keys to connect to different servers and also to use git with a different key.
I know I’m not quite clear with this, so let’s take an example.

You have two keys, one to connect to a server and an other one to use git (github, bitbucket, whatever …).

You want to clone a project using git :

git clone git@git.florianleleu.com:/myAwesomeProject

And you would do this to connect to the server s1.farm.florianleleu.com :

ssh florian@s1.farm.florianleleu.com -p 2222

Your keys are in ~/.ssh/, though which one will be used for the server and which one for git? Stuck.

I hope it’s more clear now. 😀

Here’s one way to solve this problem.
You have to create this file ~/.ssh/config
Give it some “good” rights (i.e chmod 600 ~/.ssh/config)

Here is an example of what you can write in this file, the explanations will follow :

Host git git.florianleleu.com
    HostName git.florianleleu.com
    User git
    IdentityFile ~/.ssh/git/id_rsa

Host *.farm.florianleleu.com
    User florian
    Port 2222
    IdentityFile ~/.ssh/farm/id_rsa

Options shown :

  • Host => alias or the pattern(s) you want to match, some regex are allowed
  • Hostname => the real host you want to connect to
  • User => the user with which you will be connected on the remote server
  • Port => the port of the remote server (default 22)
  • IdentityFile => the path to your private key

And now how to use it :

git clone git:/myAwesomeProject

In this command: git clone git:/myAwesomeProject, what’s in bold will be replaced by git@git.florianleleu.com because it is matched by the first Host (i.e alias), and obviously, it will do what was wanted at first, which is to take the key ~/.ssh/git/id_rsa. Note that you can also write it git clone git@git.florianleleu.com:/myAwesomeProject, but the alias is quite handy.

ssh s1.farm.florianleleu.com

In this command: ssh s1.farm.florianleleu.com, it’s matched by the second Host, and will be replaced by florian@s1.farm.florianleleu.com -p 2222 and use the file ~/.ssh/farm/id_rsa.

Obviously, not everything is said, there are other options ! RTFM 🙂

man ssh_config

CakePHP’s tips

Hello, this post will be few tips about CakePHP, about random things such as set a favicon, use the cache, use no database, …

I’ll make it evolve from time to time, feel free to give tips too in the comments 😉

  • How to set a favicon in your layout?

Well that’s pretty easy, open your layout which should be in app/View/Layouts/xxx.ctp and add this line in the head markup :

<head>
    <?php
        echo $this->Html->meta('icon', $this->Html->url('/favicon.png'));
    ?>
    ...
<head>

Of course here, the favicon is called favicon.png and is at the root of the webroot folder.

  • How to use the cache? (short explanation)
  • How to use CakePHP without database?

You have to create a new datasource file in app/Model/Datasource, call it for example Nosource.php, and fill it with this

<?php
    class NoSource extends DataSource {
        function isConnected() {
            return true;
    }
}

Then in your database.php file in app/Config just configure the default database this way

<?php
    public $default = array(
        'datasource' => 'NoSource'
    );

This would do the trick.

  • How to use a model without a table?

Just add the $useTable = false; line into your model.

<?php
App::uses('AppModel', 'Model');

class NoTableModel extends AppModel {
    public $name = 'NoTableModel';
    public $useTable = false;
}

  • How to have coloration in Eclipse for .ctp files?

In Eclipse just go to Preference > General > Content Types > Php, and then add *.ctp, you were blind, now you see.

  • How to deal quickly with erros in your application? (dirty but quick way)

Put this function in your appController, this example will catch all errors and redirect to the root of your website. It’s a pretty bad example, but it’s up to you to do whatever you want in the function (set a message, do actions, …). I used this for a small local application, it didn’t need to show errors.

<?php
    public function appError($error)
    {
        $this->redirect('/');
    }
  • How to get only your model data and not its associated data?

The recursive attribute allows you to set how deep you go when you get (with the methods find, read, etc … ) the data your model. For example, let’s say you have a model Post, if you want to grab only the data of the post and not the tags, the categories, etc … do as follows

<?php
    $myPost = $this->Post->find('first', array('recursive' => -1));

Set to -1 it only grabs the data of the model. You can also set it in your appModel directly (it’s wiser) and change its value whenever you need just like I showed before with the find method. More explanations about it there.

  • How to make your own validation rule?

Probably you came to the need of some homemade validation rules. It’s kinda easy to do. Let’s say you have a Post model, so it’s in App/Model/Post.php, in there just write down the following code.

<?php
    public function notEqualTo($field, $forbidden) 
    {
	if($field['title'] === $forbidden))
	{
		return false;
	}

	return true;
    }

This method is really quite easy and just forbids to use a value. So we just created a new validation rule, called notEqualtTo. Its first parameter is the value of the field on which you’ll put the validation rule, the second is a parameter we set here for a forbidden value, it can be whatever you need/want. Stick in your Post model, and in the $validate, just add this.

<?php
    public $validate = array(	
	'title' => array(
		'rule1' => array(
			'rule' => array("notEqualTo", "my awesome title"),
			'message' => 'This title is forbidden.'		
		),
                .....
	),
    );

So here we just said that we want the rule notEqualTo applied on our title field, as a second parameter we gave the string “my awesome title”, which means that when you’ll try to validate, if your title is “my awesome title”, the validation will fail. It’s now up to you to do more itneresting validation rules.
P.S : you can also define your validation rules in the AppModel, it means that you could use them in all your models.

  • How to get rid of CakePHP’s default routes?

Other easy thing, open the app/Config/routes.php file and comment or erase this line (should be at the bottom of the file)

<?php
// 	require CAKE . 'Config' . DS . 'routes.php';

Don’t forget to define your routes else this won’t work well.

  • How to debug?

Two interesting methods :

    – Debugger::log($this->request->data); which saves into a file in /app/tmp/logs/debug.txt

    – debug($this->request->data); which displays its result directly (it’s an “upgraded” var_dump)

The documentation is quite good, so have a look at it there.

  • How to override validation message?

Let’s say you have a custom validation rule on a field in your $validate. But your validation function can return different kind of errors according to what went wrong?  The important word was return. To do so you just have to return the error message from your validation function if it failed and true if it went well. Example !

// your validation rules
public $validate = array(
    'name' => array(
	'rule1' => array(
         	'rule' => array('myIsValid'),
	        'message' => 'My useless message.'
	),
);

// the homemade validation
public function myIsValid($field)
{
    $return = true;

    if($field['name'] != 'bla')
    {
        $return = 'wooops ! it should be equal to bla !';
    }
    else if(other stupid condition)
    {
        ...
    }

    return $return;
}

The point here was to show that you can return a string has the error message, it will be in the validationErrors. Enjoy !