I have this rather simple python and bash script that should create SA, deploy cloud function (with HTTP trigger) and set scheduler to trigger this function.
main.py
import functions_framework
# Register an HTTP function with the Functions Framework
@functions_framework.http
def my_http_function(request):
# Your code here
# Return an HTTP response
return 'OK'
requirements.txt
functions-framework==3.*
commands.sh
#!/bin/bash
SA_NAME=cf-sa-test
PROJECT=<PROJECT-ID>
REGION=europe-west1
SA_EMAIL=$SA_NAME@$PROJECT.iam.gserviceaccount.com
PROJECT_NUMBER=$(gcloud projects list --filter="$PROJECT" --format="value(PROJECT_NUMBER)")
CF_NAME=my_http_function
gcloud iam service-accounts create $SA_NAME --project=$PROJECT --description="CF SA TEST" --display-name="CF SA TEST"
gcloud functions deploy $CF_NAME --project=$PROJECT --gen2 --region=$REGION --runtime=python311 --source=. --entry-point=my_http_function --trigger-http --run-service-account=$SA_EMAIL --no-allow-unauthenticated
gcloud scheduler jobs create http cf-test-job \
--location=$REGION \
--schedule="0 */6 * * *" \
--uri="$(gcloud functions describe $CF_NAME --gen2 --project=$PROJECT --region=$REGION --format="value(serviceConfig.uri)")" \
--http-method=GET \
--oidc-service-account-email=$SA_EMAIL
When executed commands.sh
adds SA, deploy cloud function but it throws error on gcloud scheduler jobs create
:
$ ./commands.sh
Created service account [cf-sa-test].
Preparing function...done.
✓ Deploying function...
✓ [Build] Logs are available at [https://console.cloud.google.com/cloud-build/builds;region=europe-west1/b219ea91-2cbe-4bfe-a813-27779ecab550?project=<PROJECT-NUMBER>]
✓ [Service]
. [ArtifactRegistry]
. [Healthcheck]
. [Triggercheck]
Done.
You can view your function in the Cloud Console here: https://console.cloud.google.com/functions/details/europe-west1/my_http_function?project=<PROJECT-ID>
buildConfig:
build: projects/<PROJECT-NUMBER>/locations/europe-west1/builds/b219ea91-2cbe-4bfe-a813-27779ecab550
entryPoint: my_http_function
runtime: python311
source:
storageSource:
bucket: gcf-v2-sources-<PROJECT-NUMBER>-europe-west1
object: my_http_function/function-source.zip
sourceProvenance:
resolvedStorageSource:
bucket: gcf-v2-sources-<PROJECT-NUMBER>-europe-west1
generation: '1685431646792344'
object: my_http_function/function-source.zip
environment: GEN_2
labels:
deployment-tool: cli-gcloud
name: projects/<PROJECT-ID>/locations/europe-west1/functions/my_http_function
serviceConfig:
allTrafficOnLatestRevision: true
availableCpu: '0.1666'
availableMemory: 256M
ingressSettings: ALLOW_ALL
maxInstanceCount: 100
maxInstanceRequestConcurrency: 1
revision: my-http-function-00001-bij
service: projects/<PROJECT-ID>/locations/europe-west1/services/my-http-function
serviceAccountEmail: cf-sa-test@<PROJECT-ID>.iam.gserviceaccount.com
timeoutSeconds: 60
uri: https://<FUNCTION-URL>
state: ACTIVE
updateTime: '2023-05-30T07:28:19.023163428Z'
ERROR: (gcloud.scheduler.jobs.create.http) PERMISSION_DENIED: The principal (user or service account) lacks IAM permission "iam.serviceAccounts.actAs" for the resource "cf-sa-test@<PROJECT-ID>.iam.gserviceaccount.com" (or the resource may not exist)
I figured out that maybe scheduler SA needs to have access to cloud function SA so I tried to run
gcloud iam service-accounts add-iam-policy-binding $SA_EMAIL --project=$PROJECT --member=serviceAccount:service-$PROJECT_NUMBER@gcp-sa-cloudscheduler.iam.gserviceaccount.com --role=roles/iam.serviceAccountUser
gcloud iam service-accounts add-iam-policy-binding $SA_EMAIL --project=$PROJECT --member=serviceAccount:service-$PROJECT_NUMBER@gcp-sa-cloudscheduler.iam.gserviceaccount.com --role=roles/iam.serviceAccountTokenCreator
Result was:
Updated IAM policy for serviceAccount [cf-sa-test@<PROJECT-ID>.iam.gserviceaccount.com].
bindings:
- members:
- serviceAccount:service-<PROJECT-NUMBER>@gcp-sa-cloudscheduler.iam.gserviceaccount.com
role: roles/iam.serviceAccountTokenCreator
- members:
- serviceAccount:service-<PROJECT-NUMBER>@gcp-sa-cloudscheduler.iam.gserviceaccount.com
role: roles/iam.serviceAccountUser
etag: BwX85KXvXas=
version: 1
I waited like 10 minutes just in case but result was the same:
ERROR: (gcloud.scheduler.jobs.create.http) PERMISSION_DENIED: The principal (user or service account) lacks IAM permission "iam.serviceAccounts.actAs" for the resource "cf-sa-test@<PROJECT-ID>.iam.gserviceaccount.com" (or the resource may not exist)
I must be doing some silly mistake because all those steps look correct. What am I doing wrong here? Thanks.
Thanks to @Veera Nagireddy suggestions to check permissions and a night of good sleep I finally managed to find out why I could not create scheduler job with OIDC. Scheduler did not have permissions to service account because I tried to create scheduler job in different project than cloud function... I was missing --project=$PROJECT
in gcloud
command and it was using default project instead.