Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Securely Run Cron Jobs with Zend Framework

I've seen plenty of posts about cron and ZF but most of the solutions leave the job to be run available to triggering by the public.

What if you want to set up an action that can ONLY be run by cron? Not by some anonymous user and not by someone that has to log in?

The solution I am using involved putting a file outside of my web root, having it bootstrap enough of the ZF to use what I need (like, I don't need the view) and then hit that from cron. My questions are, is this a "best practice" way to do this? What if you needed to make the code accessible over the web but still need to prevent random users from finding and running it?

For illustration, here is what I am doing (that works) for a cron job run from the php command line, and on the same server, something like this:

* 10 * * * php /Apps/ZF/cronjobs/crontest.php

Webroot is: /Apps/ZF/someproject/

crontest.php:

<?php
ini_set('include_path', ini_get('include_path') . ':/Apps/ZF/someproject/library');

define('APPLICATION_PATH','/Apps/ZF/someproject/application');
define('APPLICATION_ENVIRONMENT','test');

//Include the loader (for loading ZF resources)
require_once 'Zend/Loader.php';

//Include the model (to access the Sites model in this case)
require_once(APPLICATION_PATH . '/models/Planets.php');

Zend_Loader::registerAutoload();

$configuration = new Zend_Config_Ini(
    APPLICATION_PATH . '/config/config.ini',
    APPLICATION_ENVIRONMENT
);

// DB adapter
$dbAdapter = Zend_Db::factory($configuration->database);

// DB table setup
Zend_Db_Table_Abstract::setDefaultAdapter($dbAdapter);

// Whatever code we want to run... 
$test = new Model_Planets();

$test->fetchEntries();

Zend_Debug::dump($test);
?>

So, as I said, this works so I'm not looking for someone to write me a solution... just curious about doing this "better". Also, what if I needed this to be accessible via the web but still want to keep it only runnable by cron? What about making it more flexible (because here I am hard coding a few paths that I suspect could be made more dynamic)?

I assume I could make a list of permitted servers, then test that with $_SERVER['REMOTE_ADDR']?

What do you all think? Suggestions? I work alone so I have no colleague to ask for help on this... SO is my colleague, in a way.

like image 956
Lothar Avatar asked Feb 28 '11 19:02

Lothar


3 Answers

One way is to set an environmental variable.

So in your crontab

SCRIPT_RUN_ENV=cron
* * * * * foo.php // Whatever your line is

Then, in the application, just check that:

if (get_env('SCRIPT_RUN_ENV') != 'cron') {
    echo "Program cannot be run manually\n";
    exit(1);
}

Now, anyone can set their environmental variable to that value and successfully run the cron, but it should stop the trivial running (or accidental)...

But also note that anyone who can edit the environmental variable on the server can already execute it, so there's no real way to secure it from that angle (none that are automated at least)... It's also worth noting that you cannot inject an environmental variable through HTTP.

like image 75
ircmaxell Avatar answered Sep 19 '22 08:09

ircmaxell


Well, the value of PHPSAPI should differ when it's run via cron and web-server.

like image 35
Shahriyar Imanov Avatar answered Sep 21 '22 08:09

Shahriyar Imanov


The best way to secure your php cron job is putting the php file in a non-public_html folder.

For example:

Your page is in /home/myuser/public_html/test.php

Move it to /home/myuser/test.php

and put in the cron job :

php -q /home/myuser/test.php

Now, no user can enter your page from browser and only the cron job can use it.

like image 28
Ahmed Soliman Avatar answered Sep 23 '22 08:09

Ahmed Soliman