December 11th, 2019

Google App Engine Cron Service and Django Rest Framework permissions

If you use Google App Engine, you can run tasks using Cron Service. It's simple. You can create an API endpoint and cron service can make a GET request at a specified time.

To schedule a task, you need to create cron.yaml file, example:

cron:
- description: "Update images"
url: /tasks/update-images
schedule: every day 4:00

It's essential to secure the /tasks/update-images endpoint. It should be accessible only from the cron service. According to the documentation, you can verify the HTTP header or/and IP address.

Let's use the HTTP header. All requests from Cron Service contains X-Appengine-Cron: true header. If someone tries to send a request with this header to the API, App Engine will remove it.

The X- headers are stripped by App Engine when they originate from external sources so that you can trust this header.

Using this information, you can create custom DRF permission.

from rest_framework import permissions
class IsCron(permissions.BasePermission):
def has_permission(self, request, view):
if request.META.get("HTTP_X_APPENGINE_CRON"):
return True
return False

Use permission_classes decorator to set the IsCron permission.

from rest_framework.decorators import api_view, permission_classes
from core.permissions.cron import IsCron
@api_view(["GET"])
@permission_classes([IsCron])
def update_images(request):
# ...

Now we are sure that the API endpoint can only be used by the cron service.

Do you want to support me?

© 2019 Przemysław Kołodziejczyk