fastapi+cloud run+apigee

Hello,

I’m currently working on a project that involves several endpoints created using FastAPI. My intention is to deploy these endpoints on Google Cloud Run.

Once deployed, my goal is to manage these APIs using a service from GCP, specifically something designed for API management. My initial attempt involved using Google’s API Gateway. However, I encountered a compatibility issue: API Gateway requires the OpenAPI Specification (OAS) version 2, but FastAPI produces documentation compliant with the OpenAPI version 3. This mismatch led me to seek an alternative solution.

My next attempt was using Apigee. While I was able to follow the provided documentations to some extent and make it work, I found the instructions somewhat ambiguous and unclear. Furthermore, I ran into an error that prevented me from calling my deployed application on Cloud Run. This error occurred when I attempted to use an API proxy and set the link within Apigee.

After doing some searchs, I realized that it might be a problem with service account. In my effort to troubleshoot, I tried to add a service account and assign it the “Cloud Run Invoker” role. This role is typically responsible for permission to send requests to Cloud Run services. I attempted to add this service account during the deployment of the API proxy, but it did not yield the desired results.

When I navigated to the service account section within the GCP Console, I noticed that the roles I previously assigned were not visible. This added to my confusion. The interface presented me with a “grant access” option, but when I attempted to add the service account email and searched for the “Cloud Run Invoker” role, I was unable to find it.

This whole process has left me feeling perplexed and overwhelmed. Concepts like principals, permissions, roles, and their interplay are proving to be quite challenging to grasp in this context. I anticipated that the process would be straightforward, but I’m finding it difficult to resolve these issues on my own.

I would greatly appreciate any guidance or assistance with these challenges. Specifically, if there’s a clear and direct method for integrating FastAPI with Cloud Run and either API Gateway (despite the OpenAPI version conflict) or Apigee, that would be extremely helpful for my project. If anyone has experience with these technologies and can offer insight, it would mean a great deal to me.

2 3 1,761
3 REPLIES 3

Ok I think I generally understand the issues and problems you're describing. I'm sorry it's so complicated, and I agree with you, and empathize with you, regarding that experience. There are lots of concerns, different moving parts, and it seems there are numerous things to configure before the data path works as desired. That seems to be an inevitable result of building onto GCP, for which default security is "locked down".  You need to take explicit actions to open things up, to allow the connections. And those things require roles, service accounts, and VPC connectivity. etc. So I empathize with you on the challenge.  I also agree that it's a shame that Google API Gateway does not support OpenAPI Spec v3.0 yet. There's an open issue for that.

Before I go further let's make sure I am clear on what your situation is. 

  1. When you say FastAPI, you are referring to the framework for building APIs, for Python.  Is that right? That's what we're talking about here, yes?
  2. And ... you have no problem hosting your Python app in Cloud Run.  Is that right?  You've got that working correctly.   And you are able to invoke the API endpoints from outside, when you do that. Is that correct? If not, then you might want to consider reviewing this starter tutorial covering how to build a python app(service) and deploy it to cloud run. 
  3. You said you would like to place that cloud run service behind an API Management layer. You didn't say WHY. What is the purpose of using APIM?Your first attempt was to use API Gateway.  In my opinion, API Gateway is not an API Management tool.  It's an API Gateway!  An API Gateway is  not the same as an API management tool !  I think of Management as - providing a comprehensive configurable gateway with lots of options; providing an audit trail of changes; being able to enforce common, required policies for every API; exposing and configuring an "API Marketplace" listing the APIs that are available; allowing developers to subscribe to one or more of those APIs, get credentials, and start using the APIs; providing analytics on the API usage and traffic; bot detection and mitigation.  This is all well beyond "gateway" function. So which do you want? Apigee is a good choice if you want management.  If you want simple API Gateway... then.... you could be able to do that with a managed instance-group (MIG) of Envoy proxies. Or something similar. I'm not an expert in these things and not sure how to configure Envoyproxy or other gateways to validate an incoming request against an API Specification, if that's what you want to do. 

If you think Apigee is the right thing, please see this Video tutorial on how to configure a cloud run service with an Apigee proxy in front of it.  and Here is the github repo with the source code for that tutorial.  You can run it yourself with the Cloud Shell link.

If you want to tell Apigee to validate an incoming request, use the OASValidation policy and provide your spec.

Thank you for the quick reply @dchiesa1 

1- yes, true. I think in my case, it doesn't matter that much. I'm now more struggling to call an endpoint on cloud run from apigee.

2- yes, I can deploy my app on cloud run. When I deploy it, I set `--no-allo-unauthenticated`, so no one can call it from outside, and it should pass through apigee for authentication. I can call my endpoint using:

`curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" "$SERVICE_URL"`

I checked cloud run logs and I see the following:

"The request was not authenticated. Either allow unauthenticated invocations or set the proper Authorization header."

I thought because both services are from google and in the same project, there would not be such a problem. I didn't set any API key or policy on apigee yet. I also added a service account with cloud run invoker role (I see in the IAM section the roles now instead of service account section) but it didn't solve the problem. Then tried to add a policy to the API proxy, but still not sure if I did it right or not. It still doesn't work and the documentation is not synced with the current UI! I watch many videos but all have a different UI. I don't know why they changed it so quickly :)) 

3- Let me explain what I have and what I want then. Maybe it makes everything more clear. I have several endpoints developed using FastAPI and I want to deploy them on GCP (cloud run or maybe a VM). Right now, I manage API key verification in my Python code. So the user will send a request with the API key in the header and I verify it in my endpoint. As I have several endpoints and it would be messy, I want to use SOMETHING to give me a fixed link, with just the last part changing for endpoints: 'https://example.com/A', 'https://example.com/B', 'https://example.com/C'. And also handles authentication for me and I remove the verification part in my code. That's why I'm looking for a service on GCP. I tried to use API Gateway but it needs OpenAPI v2. I don't want to change FastAPI and also tried some converters to convert my json file from OpenAPI v3 to v2 but because of some features in my code, it didn't work. I see over the internet that it works for some people. So, this is not an option for me. 

I'll try to test MIG and play more with Apigee now to see what I can do. 

Thanks again for your time and help 🙂

 

I thought because both services are from google and in the same project, there would not be such a problem. I didn't set any API key or policy on apigee yet.

What is SERVICE_URL ? is that the direct link to the cloudrun service? Or is it the link to the Apigee facade for the service?

Also, your assumption about "both services are from google and are in the same project" is not valid. The tutorial I linked gives instructions for how to connect Apigee to a cloud run service.

It still doesn't work and the documentation is not synced with the current UI! I watch many videos but all have a different UI. I don't know why they changed it so quickly :))

I get what you're saying. I'm sorry about that. All of that sounds frustrating. You make a good point - when the documentation and videos are not current with the actual UI, it's not a good thing. 

Let me explain what I have and what I want then.

ok thanks for that explanation, very clear. And I think you're on the right track, trying to separate the concern of "API Key validation" out of your own code. Apigee can do that, and once you coordinate a few things (configuring the API Product, the developer, and the app), it is pretty straightforward.  

But It sounds like, for you, even getting the VerifyAPIKey policy set up in Apigee has been a challenge. This video shows how to do it, using the prior UI !  😞  I don't know if there's a video that shows how to do that, in the current UI.  That's a shame.  I'll see if I can find or make one. Here's a quick video I just recorded showing how to do this in the new Cloud Console UI.

What you may want to do is decompose the problem .  One problem is getting Apigee to verify an API key.  Another problem is connecting an Apigee proxy to cloudrun.  A suggestion maybe? Solve them independently and then merge them.  The tutorial I showed covers the latter problem. The video I just cited covers the first problem. Remember, you can create a "loopback" proxy in Apigee that doesn't connect to any backend, to work out things like API Key verification. Then modify that proxy to connect to a target (like cloud run). 

The key to connecting Apigee to a Cloud Run service is :

  • In the Apigee Proxy, in the TargetEndpoint, Use the Authentication in the HTTPTargetEndpoint configuration.  Within that, specify GoogleAccessToken. (explained here)
  • When you deploy the proxy, attach a particular service account, which has CloudRunInvoker role (explained in same doc cited above)
  • To do this, the USER or principal that deploys the API proxy must have "actAs" permission on that serviceaccount.  (same)

Related to that "actAs" requirement, I think doing this: 

 

curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" "$CLOUD_RUN_SERVICE_URL"

 

 ... will not simulate the connection from Apigee to Cloud Run.   For the command you tried, the token that will be injected into the Authorization header here is an identity token, not an access token. And it identifies YOU, not the service account.  I think you want to present an Access token, not an identity token, and I think you want that access token to be generated for the ServiceAccount, not for you. To get a token like that, you can use something like this:

 

gcloud auth print-access-token --impersonate-service-account=PRIV_SA

 

(source)

Therefore the sequence to sort of "simulate" what Apigee will do to connect to a Cloud Run service, is like this: 

 

TOKEN=$(gcloud auth print-access-token --impersonate-service-account=PRIV_SA)
curl -i -H "Authorization: Bearer $TOKEN" $URL_FOR_CLOUD_RUN_SERVICE

 

And here, again, you need "actAs" permission on that PRIV_SA.  In other words, You need permissions to impersonate the ServiceAccount.  This is the same permission you would need if you deployed the Apigee proxy , attaching that service account. The Tutorial I cited in my prior reply shows the gcloud commands to make this all happen.