2
votes

Scenario

I'm hosting an API in Cloud Run (grpc, but the question would also hold for http) that I wish to secure. The goal is to provide access to multiple applications in our organization. Note that every app has multiple instances running at another location (one for every external client). The API is for internal use only and will not be directly hit by web browsers.

Options

I've identified the following options:

  1. Not using Cloud Endpoints: I can just have my API non-public and secured by a service account. Bearer tokens (id tokens) can be automatically generated in the appliction.
  2. Cloud Endpoints + API keys: For every App I generate an API key that is used by all instances of that app. this is very easy to setup as it just requires sending an additional header.
  3. Cloud Endpoints + self-signed jwt: I use a service account to generate a self-signed token (see GCP documentation on Service-to-Service communication) and have the endpoint configured with that service account. Multiple apps get either their own service account, or I generate new keys from the same one. Note that self-signing the token is not available in all libraries and requires some manual work. Hence refreshing the token is also manual.
  4. Cloud Endpoints + Google ID: This only provides Authentication, no authorization. It also means that everyone with a Google account can access my API (!). The advantage is that there is easy tooling to generate ID tokens.
  5. Cloud Endpoints + API Key + Google ID
  6. Cloud Endpoints + API Key + self-signed jwt

Questions

  1. Which option is the most advised for my scenario? (other options/suggestions are welcome)
  2. Is option 1 generally considered secure? If so, why even bother with Cloud Endpoints?
  3. The Google Documentation mentions different forms of Authentication (see GCP documentation on Authentication methods). However, it feels like some of them are Authorization (e.g. API Keys and Service accounts) and some of then are Authentication (e.g. Google IDs). Is this a correct assessment?
  4. I assume GCP understands that 3 deals with service accounts and it can verify them in their own way; there is no way someone without a key for the service account can get access.
  5. In option 3: I would think using multiple service accounts is better, one for every app, and preferably a key per instance. Would that be considered the best way for option 3?
  6. Is it worthwhile do perform an additional validation in the actual API? If so, why would I even have Cloud Endpoints?
  7. The GCP documentation does not mention the big issue with option 4. I think this should be made much more clear.
  8. What would be the benefit of using option 5? The fact that I can identify who makes the call? Why not make more API keys then?
  9. Is option 6 even useful? Although this is considered Authentication in Cloud Endpoints, this is really Authorization, correct?
  10. What would change if the API would be hit by a web browser?
1

1 Answers

2
votes

Here my opinion (but your question is opinion based, and might be closed)

  1. It depends!! Mostly of your client app capability! If you are able to generate a Google Signed JWT based on a service account, it's perfect (not Cloud Endpoint, native security of the product). Remember that adding an additional layer implies a new possible point of failure, a new stuff to maintain and to update. If you can avoid it, it's better!

  2. Yes, see my previous question. If your client app can't generate a dynamic credential, you can use a static credential like API Key (with all the problems of a static credential, like rotation, steal, expiration,...)

  3. Google performs Authentication is all cases. Only for GCP product, it performs authorization based on IAM roles and permission.

  4. For the #3, the public key of the signature must be known. With service account, Google know the public key. You can configure a custom authentication, and you can provide your own public key (of your PKI, if you use a self managed OIDC server for example)

  5. 1 service account per app if great: each app can have different permission. If one app is compromised (and the service account steal), the service account isn't overgranted and you don't have to change the service account key on the other apps. However, you are limited to 100 service accounts per project. I didn't catch the "key per instance". You can generate several keys if you need to rotate them or to keep one in a safe (on your side). If you have another in mind, please comment!

  6. It depends!! Do your client apps have different authorization? If so, you have to identify the identity of the caller, and then match its authorization internally in your service (we usually do this with Firestore). If a simple authentication is enough, don't perform additional checks. Why Cloud Endpoint? If you have a Cloud Run in private mode (accept only Google Signed JWT), and you client app can only use API KEY, you need an intermediary to authenticate the client APP and to generate the JWT while forwarding the request

  7. As said before, only authentication is performed by Google. For you own app, you have to manage the authorization by yourselves. And yes, if you accept 3rd party OIDC provider (Google, Facebook, LinkedIn, as you can do with Firebase Auth (or Cloud Identity Platform), you open your API to all the valid authentication)

  8. In this case, the Google ID is used for the authentication (of the caller) and the API KEY for the authentication (of the project). Firstly, an API key identify a GCP project, not an account (user or service) or an app. Only a project! (that implies if you want to identify strictly the different app (because you have different authorization per app), you need a GCP project per app, and an API Key per project, and you can't generate automatically an API key, thus you need to do this manually,... Boring moment...). Secondly, in this case, you can use the API Keys for the quotas and the rate limit feature (indeed, you need an API key for this and not Google ID, it works only with API Key)

  9. Same as before

  10. If you mean a browser with authenticated users, use Firebase Auth (or Cloud Identity Platform) to authenticate your users, and that's all.

It's a lot of information, maybe not clear or in the wrong order. I wrote 2 articles if you want, with authentication with API Keys, and the second for the Quotas/rate limit.

I only have french video that talk about this topic. But I will present it in english to the Serverless Day Zurich later in September, I will try to explain clearer this concept of API Keys and when to use them!