GCP Cloud Scheduler AND Cloud Functions are not able to call a Cloud Function without Owner IAM permissions

127 Views Asked by At

I'm using Google Cloud Platform to host my infrastructure. It basically consists of a Cloud Scheduler and about 3 or 5 Cloud Functions chained together. I'm not using Workflow, each function simply calls the next one.

It works like this: Cloud Scheduler > Control (Cloud Function 2gen) > Login (Cloud Function 2gen) > and so on...

I created one Service Account (SA) for the Cloud Scheduler and Control Function, e.g. "[email protected]" to use OIDC Auth; and one SA only for the Login Function, e.g. "[email protected]";

I gave those SAs, the following permissions.

For [email protected]: Cloud Run Invoker (the only one that docs explicitly says it's needed), Cloud Scheduler Admin, Cloud Scheduler Job Runner, Cloud Scheduler Service Agent, Firestore Service Agent, Service Account Token Creator and OWNER;

For [email protected]: Cloud Pub/Sub Service Agent, Cloud Run Admin, Cloud Scheduler Service Agent, Firestore Service Agent and OWNER.

The Control Function, only controls which accounts will be used to login. And it uses google-auth-library to authenticate the call to the Login Function.

Ingress settings is set to Allow all traffic in all Functions.

My problem is: Everything works fine with OWNER permission. Whenever I remove OWNER permission from the SAs, I receive these errors:

For Control Function:

    GET 500 699B 151ms Google-Cloud-Scheduler https://function-url.app

    {
    errorGroups: [1]
    insertId: "65aae2e2000698ca2697d4b5"
    labels: {2}
    logName: "projects/project/logs/run.googleapis.com%2Fstderr"
    receiveTimestamp: "2024-01-19T21:00:18.518683682Z"
    resource: {2}
    severity: "ERROR"
    textPayload: "Error: 7 PERMISSION_DENIED: Missing or insufficient permissions.
        at callErrorFromStatus (/workspace/node_modules/@grpc/grpc-js/build/src/call.js:31:19)
        at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client.js:192:76)
        at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:360:141)
        at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:323:181)
        at /workspace/node_modules/@grpc/grpc-js/build/src/resolving-call.js:99:78
        at process.processTicksAndRejections (node:internal/process/task_queues:77:11)"
    timestamp: "2024-01-19T21:00:18.432330Z"
    }

For Login Function:

Error 7 PERMISSION_DENIED: Missing or insufficient permissions.

I followed these tutorials for Cloud Scheduler calls to Cloud Functions first; second. And this tutorial for Cloud Function calls to another Cloud Functions.

I also tried to:

  • delete the Cloud Scheduler, the Cloud Function and the SA to create in different orders (SA before Cloud Function and vice-versa);
  • use the default scheduler-SA on Cloud Scheduler and Control Function;
  • Remove scheduler-SA aswell as disable and re-enable the Cloud Scheduler API, as suggested here;
  • manually add Cloud Scheduler SA, as suggested here.

I tried pretty much everything that is suggested in these questions: One; two and three.

P.S: I thought about creating one question for Cloud Functions invocation through Cloud Scheduler and another one for Cloud Functions invocation through Cloud Functions. But it's the same problem for both scenarios and I really think it's something messed up with permissions.

UPDATES:

  • I just tried what Guillaume suggested here and it still doesn't work.

  • As John Hanley asked:

  1. This is the service accounts (I redacted project_id): service accounts

  2. Scheduler-account being used in Scheduler Job: scheduler enter image description here

  3. Cloud Run permissions enter image description here

  4. Cloud Functions permissions enter image description here

  5. Cloud Run Logs enter image description here enter image description here

  6. Cloud Functions Logs enter image description here

  7. Scheduler Job Logs:

{
  "insertId": "166kycqfeg8q73",
  "jsonPayload": {
    "jobName": "projects/project/locations/europe-west6/jobs/control-light",
    "@type": "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished",
    "url": "https://europe-west8-project_id.cloudfunctions.net/control",
    "targetType": "HTTP",
    "status": "INTERNAL"
  },
  "httpRequest": {
    "status": 500
  },
  "resource": {
    "type": "cloud_scheduler_job",
    "labels": {
      "job_id": "control-light",
      "project_id": "project_id",
      "location": "europe-west6"
    }
  },
  "timestamp": "2024-01-29T13:00:18.544518124Z",
  "severity": "ERROR",
  "logName": "projects/project/logs/cloudscheduler.googleapis.com%2Fexecutions",
  "receiveTimestamp": "2024-01-29T13:00:18.544518124Z"
}
1

There are 1 best solutions below

5
guillaume blaquiere On

With Cloud Functions 2nd generation, you must grant Cloud Functions Invoker AND Cloud Run invoker role on the SA. (Cloud Functions 2nd gen is a "wrapper" of Cloud Run which is behind the scene)

The owner role grant you the 2, but it's a bad practice, prefer the 2 mentioned above.