0

I'm working on an app written in CakePHp 2.3.8 on a Ubuntu 12.04 server running apache2. I'd like to create a cron job to handle a situation that occurs on the first day of every month. Each month users are given a set amount of specific tasks they can use, if they go over this limit they're charged based on the number of tasks they go over by. I'd like to create a cron job to accomplish this, but my concern is someone accessing the URL of the CakePHP action for this specific task which could then initiate financial transactions.

I read through this writeup from Google about cron jobs, but I'm not quite sure I understand what they're saying about securing URL's.

A cron handler is just a normal handler defined in app.yaml. You can prevent users 
from accessing URLs used by scheduled tasks by restricting access to administrator 
accounts. Scheduled tasks can access admin-only URLs. You can restrict a URL by
adding login: admin to the handler configuration in app.yaml.

If the URL being accessed is powered by my CakePHP app, how is cron able to determine whether or not an administrator is accessing it? Or am I supposed to write a stand-alone PHP (or whatever language) file to handle these cron jobs, and inside that file it can "talk" to cron to determine if an admin is accessing it?

Say I do use CakePHP to power it. Would it be safe (or rather necessary) to use a long string in the URL so that basically no one would guess it, and have it match that string in the code?

So something like www.mysite.com/url/to/task/jdbpojzm2929qJjfwX82j3zze9iwj919jsfjmmwmwi

And then my code for that job

function cron_called_function($code){
    if($code == "jdbpojzm2929qJjfwX82j3zze9iwj919jsfjmmwmwi"){
        //do task
    }
}
Stuart Langley
  • 7,044
  • 1
  • 20
  • 20
user1443519
  • 591
  • 1
  • 12
  • 26

3 Answers3

1

Non-public member functions cannot be accessed via the url. Cake convention says prefix the method with an underscore.

private function _cron_called_function() {   // or protected
    // do task
}

Or perhaps look at creating a shell and setting up a cron in cake

Community
  • 1
  • 1
Ross
  • 18,117
  • 7
  • 44
  • 64
0

Never use URLs to do these kind of tasks, it is simply plain wrong, insecure and can cause your script to die or the server to become not responding any more.

Lets say you have 10000 users and a script runtime of 30 sec, it is very likely that the script times out before it finished and you end up with just a part of your users being processed at this time. The other scenario with a high or infinite amount of script runtime can lock your server. Depending on the script or DB actions it might cause the server to have a high load and users who use the site while the script is running will encounter a horrible slow to non responding site.

Also you can't really run a loop on a single URL, well you could redirect from one to another that does the limit and offset thing to simulate a loop over the 100000 users. If you don't loop over the records but fetch all 100000 at the same time it's likely your script dies because of running out of memory.

You should create a shell that processes the users in a loop and always just processes batches of for example 10, 50 or 100 users.

When executing your shell I recommend to use it with the "nice" command together to limit the amount of CPU time the shell is allowed to use to prevent the shell from taking 100% CPU usage to keep your site responding.

You can't "talk" to a cron either, a cron is nothing more than a timed executing of something. You can't really specify an user either except you implemented a shell in a way that allows you to pass a specific user as argument for example "cake transactions --user admin". If you mean to execute the shell with a specific system user see How to specify in crontab by what user to run script?.

Look at creating a shell and setting up a cron in cake.

Community
  • 1
  • 1
floriank
  • 25,546
  • 9
  • 42
  • 66
  • what I meant by "talk to cron" is how can I access private functions if it doesn't know where the request originated from? I suppose that means this must be done through a shell, correct? – user1443519 Dec 23 '13 at 21:45
  • I think that my answer pretty clearly explains that this kind of tasks should be done through a shell. *Not* through an URL exposed to the public - even if there is a password. You're supposed to put your code mostly in models, models can be shared easy between controllers and shells. Write a cake shell that does whatever task you want to do and set the cron up to run that shell X times a day for example. See the two links at the bottom of my answer. See also http://www.cyberciti.biz/faq/how-do-i-add-jobs-to-cron-under-linux-or-unix-oses/ - or are you using App Engine? – floriank Dec 23 '13 at 22:17
-2

There are a bunch of ways to prevent anyone buy your own server from accessing a url. None are perfect, but some are better than others.

If possible, point the cron to a page that is simply not visible on the web. This could be a page that is located above the public_html heirarchy. From within the server, this page will be accessible, but will not be accessible via url. This is the best option, IMO.

Another option is to restrict the page to the ip address of the server and to other values in the request such as a post or querystring variable.

And, of course, you have already figured out that you can include a long secret or token in the url that would long enough to make it difficult or unlikely to guess.

You could also ping a page that, in turn, uses CURL to log in as an administrator and runs the page - this is, in some ways, the option that most reflects how you interact with the site. You could create a admin called "cron" and then there would be a log of "cron"'s activities just like any other admin. http://php.net/manual/en/book.curl.php

ssaltman
  • 3,623
  • 1
  • 18
  • 21