[PYTHON] Authenticate GAE services with IAP and perform HTTP communication within the same GCP project

Introduction

GAE is convenient, isn't it? It's easy to deploy and publish. You can also manage application deployment version, traffic management, and AB testing.

By creating multiple services in GAE in one GCP project, you can set up the environment like microservices.

This time, we will talk about authentication between GAE services that span multiple services.

What I wanted to do

--Among multiple GAE services, service A is an open web application, service B is a closed API, and service B can only be accessed from service A. --In consideration of security, service B wants to be accessible only from service A. ――If possible, I want to authenticate with the upper layer (GCP) instead of in-app authentication.

How did you do

Can I authenticate with the service account set by default on GAE?

--If you deploy at least one service on GAE, a service account called [PROJECT-ID] @ appspot.gserviceaccount.com will be created automatically. ――I thought it would be easier if I could authenticate using that account, so I looked it up.

Why not use Identity-Aware Proxy (IAP)?

――When I researched various things, I found that the function Identity-Aware Proxy (IAP) made it higher than the GAE app. Will provide an authentication step. ――Let's try it right away! image.png --When IAP is enabled, both Service A and Service B are applied, and the entire GAE is closed ...

What I want to do is to open service A to the public and restrict access to service B only with IAP.

Access from a web browser is redirected to Google's authentication screen, but how to authenticate when accessing the API on the server side

――Now, you have set the GCP around access restrictions, but next time you need to authenticate when you hit the API of service B from service A. ――If you make a request normally in this state, authentication will fail with a 403 error. ――That's where the GAE service account comes in. --Register the service account as an authenticated user of service B. image.png --Now, using this service account will give you access to service B.

Acquisition of Token on the program side

--Since you have set the access authority on GCP, let's actually send the HTTP request. --When sending an HTTP request, you can authenticate with the service account by adding an OICD token to the request of the GAE service account. -Refer to this page and perform the following processing. --Although it is written in Python here, there is a sample in another language in Official document, so I think there is no problem. ..

import requests
from google.auth.transport.requests import Request
from google.oauth2 import id_token

IAP_CLIENT_ID = "Client ID obtained from the IAP credentials page"

def make_open_id_connect_token(client_id=""):
    if not client_id:
        client_id = IAP_CLIENT_ID

    open_id_connect_token = id_token.fetch_id_token(Request(), client_id)
    return open_id_connect_token


token = make_open_id_connect_token()
headers = {
    "Authorization": f"Bearer {token}",
}

res = requests.get(url="https://Service B/api/", headers=headers)
print(res.content)

--You can authenticate by getting the OICD token with make_open_id_connect_token () and including it in the request header to access it.

at the end

――Now you can communicate with public Web services and closed APIs between GAE services with authentication, which you originally wanted to do. ――However, the disadvantages are as follows. --If there are services that are already open and operated, downtime will occur because IAP authentication will be temporarily added to all services when IAP is enabled. --Even if you set allUsers so that all users can access through IAP, I think there is (probably) some kind of authentication step, so I think it is minor, but it seems to affect the response etc. --Every time you add a new public service on the project with GAE, you need to add allUsers permissions. ――I think it's best to use them properly in consideration of these disadvantages.

Articles that I used as a reference

-[Authentication between services with GAE 2nd-gen](https://medium.com/google-cloud-jp/gae-2nd-gen-%E3%81%A7%E3%81%AE%E3%82% B5% E3% 83% BC% E3% 83% 93% E3% 82% B9% E9% 96% 93% E8% AA% 8D% E8% A8% BC-1ed1d8b1abce) ――This was very helpful. Thank you very much. -Searched for Google App Engine service-to-service communication authentication (unsolved)

Recommended Posts

Authenticate GAE services with IAP and perform HTTP communication within the same GCP project