Google Cloud Tasks trigger Cloud Function with INTERNAL only ingress
Asked Answered
B

3

10

How can I trigger a Cloud Function from Cloud Tasks when that function has its ingress settings set to "allow internal only"?

With that setting, the function rejects the incoming HTTP traffic from Cloud Tasks. This behavior occurs even if Cloud Tasks is in the same project as the function.

Boots answered 22/10, 2020 at 15:46 Comment(0)
T
6

It's funny because I asked Google PMs exactly about that on Tuesday this week! Because today you can't! It's in the radar of the PMs, with not timeline but it will be possible, a day.

My solution today.

If I have a cloud function in internal only mode which is used internally AND externally (or by Google serverless products not compliant with VPC connector, like Cloud Task, Cloud Scheduler, PubSub and Workflows), I create a "proxy function"

  • This proxy function is deployed in ingress=all mode and with no-allow-unauthenticated param
  • I grant only the service account of the external product on it as cloudfunctions.invoker on the proxy function to be sure that only this service account will be able to call the proxy function
  • I create a serverless VPC connector and add it to the proxy function
  • The proxy function only call the internal function.
Trott answered 22/10, 2020 at 19:14 Comment(0)
Z
1

Recently ran into this problem and providing a follow up for any people that are interested.

Two things of note, as mentioned by @guillaumeblaquiere Google PMs are aware of this and based on a recent support ticket I've opened with Google its been mentioned that they've put internal support for Cloud Tasks on their road map so potentially might be supported by EOY (2022). Here's two related issue trackers if anyone's interested and wants to show the need for this sort of feature.

In regards to the problem at hand, I would not recommend the above proxy function solution, this was also proposed by Google support. It's functionally no different than just making your original Cloud Function ingress settings to allow all traffic. You're just adding another hoop that doesn't provide a private solution.

A solution my team built instead looked like Cloud Tasks -> Pub/Sub -> Cloud Function.
This pattern allows you to keep everything within the VPC since Cloud Functions has a native trigger for Pub/Sub. Cloud Task can then interact with Pub/Sub through its REST API. This pattern can then be further secured by creating a runtime SA for Cloud Task that has the following permissions, can be granted at either the project level or resource depending on security needs:

  • Cloud Tasks Enqueuer
  • Pub/Sub Publisher
  • Cloud Functions Invoker
Zadoc answered 29/6, 2022 at 20:54 Comment(3)
Thanks for the status update, the documentation for this is painfully inexistant. Hoping for a fix by the end of the year, then.Chaffer
Damn, I just wasted a few hours on this. Apparently, it is still not resolved.Sarmentum
Yeah Google provided an update on this issue issuetracker.google.com/issues/154481516 as of Nov 16, 2022 "Thought I'd give an update on this bug as well. Cloud Tasks can now target Cloud Functions and Cloud Run with VPC-SC or using internal-only ingress. We are working on adding support for VPC private IPs as well in 2023." There wasn't any follow up in the ticket by others and I haven't conducted testing so not sure if the change was actually implemented/implemented well.Zadoc
L
-4

Hello @guillaume & @Thomas, I am facing challenge to invoke cloud Function from cloud task. Here are details of my IAM & Code:

const { CloudTasksClient } = require('@google-cloud/tasks');
const client = new CloudTasksClient();

//See https://cloud.google.com/tasks/docs/tutorial-gcf
module.exports = async (payload, scheduleTimeInSec) => {
  const project = process.env.GOOGLE_APPLICATION_PROJECTID;
  const queue = process.env.QUEUE_NAME;
  const location = process.env.QUEUE_LOCATION;
  const callBackUrl = https://asia-south2-trial-288318.cloudfunctions.net/cloud-function-node-expres/;

  // Construct the fully qualified queue name.
  const parent = client.queuePath(project, location, queue);

  const body = Buffer.from(JSON.stringify(payload)).toString('base64');

  const task = {
    httpRequest: {
      httpMethod: 'POST',
      url: callBackUrl,
      headers: { 'Content-Type': 'application/json' },
      body
    },
    scheduleTime: {
      seconds: scheduleTimeInSec,
    }
  };

  if (process.env.GOOGLE_APPLICATION_SERVICE_ACCOUNT_EMAIL) {
    task.httpRequest.oidcToken = {
      serviceAccountEmail: process.env.GOOGLE_APPLICATION_SERVICE_ACCOUNT_EMAIL
    }
  }

  const request = {
    parent: parent,
    task: task,
  };

  // Send create task request.
  try {
    let [responses] = await client.createTask(request);

    return ({ sts: true, taskName: responses.name, msg: "Email Schedule Task Created" })
  }
  catch (e) {
    return ({ sts: true, err: true, errInfo: e, msg: "Unable to Schedule Task. Internal Error." })
  }
}

The process.env.GOOGLE_APPLICATION_SERVICE_ACCOUNT_EMAIL has Cloud Functions Invoker role and the Cloud Function has allAuthenticatedUsers member with role Cloud Functions Invoker as per the doc.

But still I am seeing the 401 resposnse recevied by Cloud Task and Cloud Function is not getting called(See below image):

enter image description here

Any comment on this, whats going wrong here

Leland answered 10/11, 2020 at 5:52 Comment(2)
please ask this as a separate questionBoots
Hi @thomas-ruble & guillaume, Apologies for the inconvenience. Can you please help me for similar kind of issue I have asked : https://mcmap.net/q/1168380/-facing-challenge-to-invoke-cloud-function-from-cloud-task-using-oidctoken/3076704Leland

© 2022 - 2024 — McMap. All rights reserved.