Breakfast at lake near Tampere Finland

Securing HTTP trigger in Google Cloud Functions

In this how-to article, I’m going to show how you can secure your Google Cloud Platform (GCP) Functions HTTP trigger, it has not been that straightforward to secure HTTP trigger in Cloud Functions in the past HTTP triggers in GCP were publicly available. While this might be useful in a lot of scenarios, it’s also quite possible you don’t want ‘strangers’ hitting your public endpoints all the time.

If you read on, I will show how to remove an unauthorized Cloud Function HTTP Trigger, and how you can create a service account to be used with your application to trigger the Cloud Function HTTP URL or in my example using Cloud Scheduler to trigger, the HTTP Trigger URL is your endpoint to your Cloud Function.

Cloud Function Dashboard

When you create a Cloud Function with an HTTP trigger, if your use case is to allow an unauthenticated HTTP trigger, then you do not need to do anything. If your use case is to secure the HTTP trigger so you can control who can access the HTTP trigger, then read on.

In your Cloud Functions dashboard, in the column Authentication, you can find what Authentication status your function has. If it says Allow unauthenticated, then your Cloud Function is open to the public internet, which means that anyone could trigger your cloud function if they have the URL to the cloud function.

cloud-function-dashboard-inauthenticated
cloud-function-dashboard-inauthenticated

If you care about security then your Cloud Function should be authenticated and your dashboard should look like this.

running secure cloud functions http triggers
running secure cloud functions http triggers

Cloud Function Trigger

In the Cloud Function, you will find your URL trigger under the label TRIGGER, as shown below.

https-trigger-cloud-function
https-trigger-cloud-function

Remove unauthenticated

If you have Cloud Function that is set to Allow unauthenticated, it is very simple to change – click on the Cloud Function name from the Cloud Function Dashboard that opens up details about your Cloud Function, choose permissions and then Cloud Functions Invoker from the list of Roles – if you have an allUsers Role that means your Cloud Function is unauthenticated, to make it authenticated just delete the allUsers from your Cloud Functions permissions.

allUsers permission cloud functions
allUsers permission cloud functions

Cloud IAM & Admin

Here are the steps to make Cloud Scheduler trigger an HTTP triggered Cloud Function that doesn’t allow unauthenticated invocations: Create a service account, which will have the following form [SA-NAME]@[PROJECT-ID].iam.gserviceaccount.com.

Add the service account [SA-NAME]@[PROJECT-ID].iam.gserviceaccount.com as a project member and add the following roles to the service account: Cloud Functions Invoker, Secret Manager Admin, Cloud Build Admin, Firebase Admin and Cloud Scheduler Admin.

service account settings GCP
service account settings GCP

Add Service Account to Cloud Function

Deploy an HTTP triggered Cloud Function that doesn’t allow public (unauthenticated) access and that used the recently created service account [SA-NAME]@[PROJECT-ID].iam.gserviceaccount.com on the Service account field (click more and look for the Service account field, by default it should be set to the App Engine default service account) and take notice of the Cloud Function’s URL.

Tying it up with Cloud Scheduler

Create a Cloud Scheduler job with authentication by issuing the following command from the Cloud Shell:

gcloud scheduler jobs create http getNews --schedule="0 10 * * *" --uri=<function Trigger URL> --oidc-service-account-email=<service-account>
Cloud-Schedule-Triggers-HTTP function
Cloud-Schedule-Triggers-HTTP function

If you have to edit an old cloud schedule to trigger an Authenticated – you need to apply authentication to the Cloud trigger to a service account that is associated with your Cloud Function. To do this, you apply OIDC token – you can edit your cloud schedule entry and add an OIDC token.

Do Not

Do not run this gcloud command as it will set allUsers making your cloud functions all unauthorized

"gcloud functions add-iam-policy-binding <function name> --region=<region> --member=allUsers --role=roles/cloudfunctions.invoker"

If you deploy your Cloud Function from the command line with gcloud – do not include –allow-unauthenticated your cloud command should look like something like this

gcloud functions deploy getNews_http --runtime python37 --trigger-http --region=europe-west1 --memory=128MB

If you deploy using Google Cloud Build, you should not include –allow-unauthenticated, it should look something likes this your cloudbuild.yaml file

steps:
    - name: "gcr.io/cloud-builders/gcloud"
      waitFor: ["-"]
      args:
        - functions
        - deploy
        - getNewsGuardian_http
        - --runtime=python37
        - --trigger-http
        - --region=europe-west1
        - --memory=512MB
        - --timeout=240
      id: "deploying-serverless-guardian_bot"
      dir: "socialclimatetech-news-guardian"

Wrapping Up

That is it, I hope it was clear and that you know have the knowledge of applying this to your Cloud Functions. As always I look for feedback, please add your comments below.


Posted

in

, , ,

by

Comments

8 responses to “Securing HTTP trigger in Google Cloud Functions”

  1. Richa Avatar
    Richa

    Great document. Do you have any more such blogs for GCP security?

    1. Torbjorn Zetterlund Avatar
      Torbjorn Zetterlund

      Not much + if you program a Cloud Function you can read about how to secure your credentials in GCP + https://torbjornzetterlund.com/using-secret-manager-in-a-google-cloud-function-with-python/

  2. Alberto Avatar
    Alberto

    Hi Torbjorn,

    Great article.

    What if I have to call this function externally? How would look like the call? Would I have to get some sort of token assigned to the service account and use it as a ‘Bearer + Token’ for example, in order for the function to execute and being triggered?

    I’m interested on knowing how to call a secure function using IAM if that’s possible.

    Thanks,
    Alberto

    1. Torbjorn Zetterlund Avatar
      Torbjorn Zetterlund

      You need to create a service account, you can read from your external application to give that application access to the cloud function. Here is a code snippet in Python that shows how to use a service account in a third-party app.

      #Load Libraries
      from oauth2client.service_account import ServiceAccountCredentials
      from apiclient.discovery import build
      import httplib2
      import pandas as pd

      #Create service credentials
      #Rename your JSON key to client_secrets.json and save it to your working folder
      credentials = ServiceAccountCredentials.from_json_keyfile_name('client_secrets.json', ['https://www.googleapis.com/auth/analytics.readonly'])

      #Create a service object
      http = credentials.authorize(httplib2.Http())

    2. Jayakumar Avatar
      Jayakumar

      Hi Alberto,

      I also have the same query.
      I need to invoke the cloud function using the bearer token.

      Have you found any approach ?

  3. Jayakumar Avatar
    Jayakumar

    Hi Alberto,

    I also have the same query.
    I need to invoke the cloud function using the bearer token.

    Have you found any approach ?

    1. Torbjorn Zetterlund Avatar
      Torbjorn Zetterlund

      If your cloud function is to make an HTTP request you can do this with Python

      # Get the secret
      token = _getsecrets("token")

      # Get the secret for
      companyid = _getsecrets("company_id")

      # Create the encoded authentication parameters
      auth = companyid + ':' + token
      encoded_u = base64.b64encode(auth.encode()).decode()
      # Create the Header and url
      headers = {
      "Authorization" : "Basic %s" % encoded_u
      }
      # Make a request
      response = requests.get(url, params={'page': 1, 'per_page': 400}, headers=header)

      I hope this answers your question

Leave a Reply

Your email address will not be published. Required fields are marked *