1818import google .auth .compute_engine .credentials
1919import google .auth .iam
2020from google .auth .transport .requests import Request
21+ from google .oauth2 import id_token
2122import google .oauth2 .credentials
2223import google .oauth2 .service_account
2324import requests
@@ -66,7 +67,6 @@ def trigger_dag(data, context=None):
6667# START COPIED IAP CODE
6768def make_iap_request (url , client_id , method = 'GET' , ** kwargs ):
6869 """Makes a request to an application protected by Identity-Aware Proxy.
69-
7070 Args:
7171 url: The Identity-Aware Proxy-protected URL to fetch.
7272 client_id: The client ID used by Identity-Aware Proxy.
@@ -75,54 +75,16 @@ def make_iap_request(url, client_id, method='GET', **kwargs):
7575 **kwargs: Any of the parameters defined for the request function:
7676 https://github.com/requests/requests/blob/master/requests/api.py
7777 If no timeout is provided, it is set to 90 by default.
78-
7978 Returns:
8079 The page body, or raises an exception if the page couldn't be retrieved.
8180 """
8281 # Set the default timeout, if missing
8382 if 'timeout' not in kwargs :
8483 kwargs ['timeout' ] = 90
8584
86- # Figure out what environment we're running in and get some preliminary
87- # information about the service account.
88- bootstrap_credentials , _ = google .auth .default (
89- scopes = [IAM_SCOPE ])
90-
91- # For service account's using the Compute Engine metadata service,
92- # service_account_email isn't available until refresh is called.
93- bootstrap_credentials .refresh (Request ())
94-
95- signer_email = bootstrap_credentials .service_account_email
96- if isinstance (bootstrap_credentials ,
97- google .auth .compute_engine .credentials .Credentials ):
98- # Since the Compute Engine metadata service doesn't expose the service
99- # account key, we use the IAM signBlob API to sign instead.
100- # In order for this to work:
101- # 1. Your VM needs the https://www.googleapis.com/auth/iam scope.
102- # You can specify this specific scope when creating a VM
103- # through the API or gcloud. When using Cloud Console,
104- # you'll need to specify the "full access to all Cloud APIs"
105- # scope. A VM's scopes can only be specified at creation time.
106- # 2. The VM's default service account needs the "Service Account Actor"
107- # role. This can be found under the "Project" category in Cloud
108- # Console, or roles/iam.serviceAccountActor in gcloud.
109- signer = google .auth .iam .Signer (
110- Request (), bootstrap_credentials , signer_email )
111- else :
112- # A Signer object can sign a JWT using the service account's key.
113- signer = bootstrap_credentials .signer
114-
115- # Construct OAuth 2.0 service account credentials using the signer
116- # and email acquired from the bootstrap credentials.
117- service_account_credentials = google .oauth2 .service_account .Credentials (
118- signer , signer_email , token_uri = OAUTH_TOKEN_URI , additional_claims = {
119- 'target_audience' : client_id
120- })
121- # service_account_credentials gives us a JWT signed by the service
122- # account. Next, we use that to obtain an OpenID Connect token,
123- # which is a JWT signed by Google.
124- google_open_id_connect_token = get_google_open_id_connect_token (
125- service_account_credentials )
85+ # Obtain an OpenID Connect (OIDC) token from metadata server or using service
86+ # account.
87+ google_open_id_connect_token = id_token .fetch_id_token (Request (), client_id )
12688
12789 # Fetch the Identity-Aware Proxy-protected URL, including an
12890 # Authorization header containing "Bearer " followed by a
@@ -132,49 +94,14 @@ def make_iap_request(url, client_id, method='GET', **kwargs):
13294 headers = {'Authorization' : 'Bearer {}' .format (
13395 google_open_id_connect_token )}, ** kwargs )
13496 if resp .status_code == 403 :
135- raise Exception ('Service account {} does not have permission to '
136- 'access the IAP-protected application.' .format (
137- signer_email ))
97+ raise Exception ('Service account does not have permission to '
98+ 'access the IAP-protected application.' )
13899 elif resp .status_code != 200 :
139100 raise Exception (
140101 'Bad response from application: {!r} / {!r} / {!r}' .format (
141102 resp .status_code , resp .headers , resp .text ))
142103 else :
143104 return resp .text
144-
145-
146- def get_google_open_id_connect_token (service_account_credentials ):
147- """Get an OpenID Connect token issued by Google for the service account.
148-
149- This function:
150-
151- 1. Generates a JWT signed with the service account's private key
152- containing a special "target_audience" claim.
153-
154- 2. Sends it to the OAUTH_TOKEN_URI endpoint. Because the JWT in #1
155- has a target_audience claim, that endpoint will respond with
156- an OpenID Connect token for the service account -- in other words,
157- a JWT signed by *Google*. The aud claim in this JWT will be
158- set to the value from the target_audience claim in #1.
159-
160- For more information, see
161- https://developers.google.com/identity/protocols/OAuth2ServiceAccount .
162- The HTTP/REST example on that page describes the JWT structure and
163- demonstrates how to call the token endpoint. (The example on that page
164- shows how to get an OAuth2 access token; this code is using a
165- modified version of it to get an OpenID Connect token.)
166- """
167-
168- service_account_jwt = (
169- service_account_credentials ._make_authorization_grant_assertion ())
170- request = google .auth .transport .requests .Request ()
171- body = {
172- 'assertion' : service_account_jwt ,
173- 'grant_type' : google .oauth2 ._client ._JWT_GRANT_TYPE ,
174- }
175- token_response = google .oauth2 ._client ._token_endpoint_request (
176- request , OAUTH_TOKEN_URI , body )
177- return token_response ['id_token' ]
178105# END COPIED IAP CODE
179106
180107# [END composer_trigger]
0 commit comments