3

I have a Python app on Google App Engine Standard which is secured using Google Cloud Identity Aware Proxy (IAP).

I would like to trigger a part of my app every day by using Cloud Scheduler. (It is calling an API, doing calculations, and stores results in Google Cloud Storage.)

To do so, I tried triggering a POST request on an "App Engine HTTP". example URL: "/refresh_data"

When running the job, I get the following error:

jsonPayload: {
status: "FAILED_PRECONDITION"
relativeUrl: "/refresh_data"
jobName: "..."
@type: "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished"
targetType: "APP_ENGINE_HTTP"
}

I can't find any documentation relative to the "FAILED_PRECONDITION" error so I'm feeling kind of stuck here.

As an alternative, I tried to trigger a POST request to a simple "HTTP" and by granting the Owner access level in IAP to the service account I am using for Cloud Scheduler. This time, the error message I get is the following :

 jsonPayload: {
 status: "UNAUTHENTICATED"
 @type: "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished"
 jobName: "..."
 targetType: "HTTP"
 url: "https:.../refresh_data"
 }

I really don't understand how to make this work... The Cloud Scheduler documentation barely documents the "App Engine HTTP" option, and nothing is documented relative to te use of IAP...

Any help would be much appreciated :)

tim
  • 103
  • 2
  • 6

4 Answers4

2

It's the dark side of IAP. I sent this feedback to Google months ago. Same thing with Pubsub, you can't trigger and App Engine IAP protected from these serverless product, even if you use a service account with the correct authorization.

guillaume blaquiere
  • 66,369
  • 2
  • 47
  • 76
  • alright... thanks a lot, that's super useful ! do you have any other alternative method that you think I could use instead of cloud scheduler ? – tim Sep 04 '20 at 07:39
  • Cloud scheduler is the right tool for this, but not to call directly App Engine. Call a functions or a Cloud Run instead. From there, you can call the App Engine endpoint through IAP. However, how long does your refresh_data process take ? – guillaume blaquiere Sep 04 '20 at 12:08
  • Perfect, because you have 9 minutes of timeout with Cloud Functions. Take care, the default function timeout is 60s, change this default value when you deploy your function! – guillaume blaquiere Sep 04 '20 at 18:21
  • 1
    I moved my code to a Cloud Function triggered by pub/sub, and synced that with Cloud Scheduler. I had to change some stuff to make it work but now it works perfectly! Thanks ! – tim Sep 10 '20 at 13:22
  • 1
    There's no problem to trigger a AppEngine service behind IAP from Cloud Scheduler. You simply need to use a special trigger type for it - AppEngine HTTP and it should work. I tried it in my GCP project and it worked. I see, tim@, you had some strange issue "FAILED_PRECONDITION" though, which I believe might be caused by headers requirement mismatch between the server and trigger and not by IAP (btw did you try to disable IAP to verify it works?). Could you provide more details what endpoint you tried to call? @tim – Shrike Apr 09 '21 at 13:24
0

You can check this relevant documentation from IAP on how to authenticate with a Service Account.

Whenever you are using Cloud Scheduler, the requests will be done with its Service Account, therefore the guide to follow should be the one linked above as you are basically trying to authenticate programmatically rather than with the Google sign-in.

That being said, you would need to generate the OIDC token prior to making a request to an IAP-secured endpoint. Once you have the OIDC token, it needs to be included in the Authorization: Bearer header.

bhito
  • 2,083
  • 7
  • 13
  • thank you! I saw this documentation but as it seemed rather complicated to implement (as opposed to the extreme simplicity of IAP) I thought App Engine would handle this kind of stuff for me. I'll try to implement this. Did you try it on your end and did it work ? – tim Sep 04 '20 at 07:52
0

I had a similar problem when upgrading my GAE app from python 2.7 to python3 (standard). I got the same error message as you (status: "FAILED_PRECONDITION") when running my previous cron.yaml jobs set up as cloud scheduler jobs. And the upload of previous cron.yaml files did not work to run either. Then I found out that just adding an ending '/' on the url fixed it. So a cron like:

cron:
- description: competition participants pilot list update
  url: /daily1/
  schedule: every 8 hours from 05:00 to 21:00

worked after being uploaded with cloud SDK:

gcloud app deploy cron.yaml --project my-gae-project

(and I forgot that) I also had to:

gcloud services enable cloudscheduler.googleapis.com --project my-gae-project
  • wow, ok. I did not test this because the answer from @guillaume blaquiere solved my issue, but is your app protected by IAP too ? – tim Mar 01 '21 at 11:12
  • No, sorry. I just had the same error message. And I edited above that I also had to enable the scheduler service... – StaffanRolfsson Mar 01 '21 at 13:47
0

I got this working recently for HTTP endpoints behind an IAP (we use cloud run, but it should be similar for any IAP protected HTTP endpoint). This is the Cloud Scheduler configuration that worked for me:

  • Auth Header: "Add OIDC Token"
  • Service account: Select a service account with the role "IAP-secured Web App User" (if you recently added this permission, it can take a few minutes to propagate)
  • Audience: Your IAP's Client ID (from here: https://console.cloud.google.com/apis/credentials)
Coops
  • 61
  • 1
  • 2