Search code examples
google-cloud-platformgoogle-cloud-functionsgoogle-cloud-tasks

How do I grant permission for a Google Cloud Task created by Cloud Functions


I have two Google Cloud Functions, one of them 'caller' creates a Cloud Task which then calls a http endpoint tied to a different Cloud Function 'worker'

When I assign allUsers to the worker function as a Cloud Functions Invoker this works. When I remove this permission and assign the caller function Service Account instead as the Invoker, it fails. What am I doing wrong?

If there is any code it would be helpful to see to diagnose this, let me know. It doesn't seem to be a code issue though since the same code passes or fails depending on the permissions I have set.My permissions look like this:

...@appspot.gserviceaccount.com     App Engine default service account Cloud Functions Invoker 



export function main(
project:any, // Your GCP Project id
queue:any, // Name of your Queue
location:any, // The GCP region of your queue
url:any, // The full url path that the request will be sent to
payload:any, // The task HTTP request body
inSeconds = 0 // Delay in task execution
) {
// [START cloud_tasks_create_http_task]
// Imports the Google Cloud Tasks library.
const {CloudTasksClient} = require('@google-cloud/tasks');

// Instantiates a client.
const client = new CloudTasksClient();

async function createHttpTask() {
    // TODO(developer): Uncomment these lines and replace with your values.
    // const project = 'my-project-id';
    // const queue = 'my-queue';
    // const location = 'us-central1';
    // const url = 'https://example.com/taskhandler';
    // const payload = 'Hello, World!';
    // const inSeconds = 180;

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

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

    if (payload) {
        const convertedPayload = JSON.stringify(payload);
        task.httpRequest.body = Buffer.from(convertedPayload).toString('base64');
    }

    if (inSeconds) {
        // The time when the task is scheduled to be attempted.
        task.scheduleTime = {
            seconds: inSeconds + Date.now() / 1000,
        };
    }

    // Send create task request.
    console.log('Sending task:');
    console.log(task);
    const request = {parent: parent, task: task};
    const [response] = await client.createTask(request);
    console.log(`Created task ${response.name}`);
}
createHttpTask();
// [END cloud_tasks_create_http_task]

}


Solution

  • Oh fine, you forgot the OIDC part

        const task = {
            httpRequest: {
                httpMethod: 'POST',
                url,
                body: '',
                headers: {
                    "Content-Type": "application/json",
                },
    ######### This part is missing #############
                oidcToken: {
                     serviceAccountEmail,
                },
    ######### End of missing part  #############
            },
            scheduleTime: {}
        };
    

    Set the service account email that you want to use to call your cloud functions, of course a service account with the permission to invoke the cloud functions and it should work.