问题
I've been trying to invoke a GCP function (--runtime nodejs8 --trigger-http
) from GCP scheduler, both located within the same project. I can only make it work, if I grant unauthenticated access by adding the allUsers
member to the functions permissions, with the Cloud Functions-Invoker
role applied to it. However, when I only use the service account of the scheduler as the Cloud Functions-Invoker
, I get a PERMISSION DENIED Error.
I created a hello world example, to show in detail, how my setup looks like.
- I set up a service account:
gcloud iam service-accounts create scheduler --display-name="Task Schedule Runner"
- Setting the role:
svc_policy.json:
{
"bindings": [
{
"members": [
"serviceAccount:scheduler@mwsdata-1544225920485.iam.gserviceaccount.com"
],
"role": "roles/cloudscheduler.serviceAgent"
}
]
}
gcloud iam service-accounts set-iam-policy scheduler@mwsdata-1544225920485.iam.gserviceaccount.com svc_policy.json -q
- Deploying the Cloud Function:
gcloud functions deploy helloworld --runtime nodejs8 --trigger-http --entry-point=helloWorld
- Adding the service account as a member to the function:
gcloud functions add-iam-policy-binding helloworld --member serviceAccount:scheduler@mwsdata-1544225920485.iam.gserviceaccount.com --role roles/cloudfunctions.invoker
- Creating the scheduler job:
gcloud beta scheduler jobs create http test-job --schedule "5 * * * *" --http-method=GET --uri=https://us-central1-mwsdata-1544225920485.cloudfunctions.net/helloworld --oidc-service-account-email=scheduler@mwsdata-1544225920485.iam.gserviceaccount.com --oidc-token-audience=https://us-central1-mwsdata-1544225920485.cloudfunctions.net/helloworld
Log: PERMISSION DENIED
{
httpRequest: {
}
insertId: "1ny5xuxf69w0ck"
jsonPayload: {
@type: "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished"
jobName: "projects/mwsdata-1544225920485/locations/europe-west1/jobs/test-job"
status: "PERMISSION_DENIED"
targetType: "HTTP"
url: "https://us-central1-mwsdata-1544225920485.cloudfunctions.net/helloworld"
}
logName: "projects/mwsdata-1544225920485/logs/cloudscheduler.googleapis.com%2Fexecutions"
receiveTimestamp: "2020-02-04T22:05:05.248707989Z"
resource: {
labels: {
job_id: "test-job"
location: "europe-west1"
project_id: "mwsdata-1544225920485"
}
type: "cloud_scheduler_job"
}
severity: "ERROR"
timestamp: "2020-02-04T22:05:05.248707989Z"
}
Update
Here are the corresponding settings.
Scheduler Service Account
gcloud iam service-accounts get-iam-policy scheduler@mwsdata-1544225920485.iam.gserviceaccount.com
bindings:
- members:
- serviceAccount:scheduler@mwsdata-1544225920485.iam.gserviceaccount.com
role: roles/cloudscheduler.serviceAgent
etag: BwWdxuiGNv4=
version: 1
IAM Policy of the function:
gcloud functions get-iam-policy helloworld
bindings:
- members:
- serviceAccount:scheduler@mwsdata-1544225920485.iam.gserviceaccount.com
role: roles/cloudfunctions.invoker
etag: BwWdxyDGOAY=
version: 1
Function Description
gcloud functions describe helloworld
availableMemoryMb: 256
entryPoint: helloWorld
httpsTrigger:
url: https://us-central1-mwsdata-1544225920485.cloudfunctions.net/helloworld
ingressSettings: ALLOW_ALL
labels:
deployment-tool: cli-gcloud
name: projects/mwsdata-1544225920485/locations/us-central1/functions/helloworld
runtime: nodejs8
serviceAccountEmail: mwsdata-1544225920485@appspot.gserviceaccount.com
sourceUploadUrl: https://storage.googleapis.com/gcf-upload-us-central1-671641e6-3f1b-41a1-9ac1-558224a1638a/b4a0e407-69b9-4f3d-a00d-7543ac33e013.zip?GoogleAccessId=service-617967399269@gcf-admin-robot.iam.gserviceaccount.com&Expires=1580854835&Signature=S605ODVtOpnU4LIoRT2MnU4OQN3PqhpR0u2CjgcpRcZZUXstQ5kC%2F1rT6Lv2SusvUpBrCcU34Og2hK1QZ3dOPluzhq9cXEvg5MX1MMDyC5Y%2F7KGTibnV4ztFwrVMlZNTj5N%2FzTQn8a65T%2FwPBNUJWK0KrIUue3GemOQZ4l4fCf9v4a9h6MMjetLPCTLQ1BkyFUHrVnO312YDjSC3Ck7Le8OiXb7a%2BwXjTDtbawR20NZWfgCCVvL6iM9mDZSaVAYDzZ6l07eXHXPZfrEGgkn7vXN2ovMF%2BNGvwHvTx7pmur1yQaLM4vRRprjsnErU%2F3p4JO3tlbbFEf%2B69Wd9dyIKVA%3D%3D
status: ACTIVE
timeout: 60s
updateTime: '2020-02-04T21:51:15Z'
versionId: '1'
Scheduler Job Description
gcloud scheduler jobs describe test-job
attemptDeadline: 180s
httpTarget:
headers:
User-Agent: Google-Cloud-Scheduler
httpMethod: GET
oidcToken:
audience: https://us-central1-mwsdata-1544225920485.cloudfunctions.net/helloworld
serviceAccountEmail: scheduler@mwsdata-1544225920485.iam.gserviceaccount.com
uri: https://us-central1-mwsdata-1544225920485.cloudfunctions.net/helloworld
lastAttemptTime: '2020-02-05T09:05:00.054111Z'
name: projects/mwsdata-1544225920485/locations/europe-west1/jobs/test-job
retryConfig:
maxBackoffDuration: 3600s
maxDoublings: 16
maxRetryDuration: 0s
minBackoffDuration: 5s
schedule: 5 * * * *
scheduleTime: '2020-02-05T10:05:00.085854Z'
state: ENABLED
status:
code: 7
timeZone: Etc/UTC
userUpdateTime: '2020-02-04T22:02:31Z'
回答1:
Here are the steps I followed 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.
- Adde the service account [SA-NAME]@[PROJECT-ID].iam.gserviceaccount.com as a project member and added the following roles to the service account: Cloud Functions Invoker and Cloud Scheduler Admin.
- Deploy an HTTP triggered Cloud Function that doesn't allow public (unauthenticated) access (if you are using the UI, simply uncheck the Allow unauthenticated Invocations checkbox) 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.
- Create a Cloud Scheduler job with authentication by issuing the following command from the Cloud Shell:
gcloud scheduler jobs create http [JOB-NAME] --schedule="* * * * *" --uri=[CLOUD-FUNCTIONS-URL] --oidc-service-account-email=[SA-NAME]@[PROJECT-ID].iam.gserviceaccount.com
In your specific case you are leaving the default App Engine service account for your Cloud Functions. Change it to the service account you created as specified on the previous steps.
回答2:
@Marko I went through the same issue, it seems to re-enable (disable/enable) the scheduler API did the fix. This is why creating a new project makes sense because you probably got a scheduler service account by doing so. So if your project doesn't have a scheduler service account created from google, doing this trick will give you one. And although you don't need to assign this specific service account to any of your tasks, it must be available. You can see my work here: How to invoke Cloud Function from Cloud Scheduler with Authentication
来源:https://stackoverflow.com/questions/60055422/cannot-invoke-google-cloud-function-from-gcp-scheduler