2121import google .oauth2 .credentials
2222import google .oauth2 .service_account
2323import requests
24-
24+ from google . oauth2 import id_token
2525
2626IAM_SCOPE = 'https://www.googleapis.com/auth/iam'
2727OAUTH_TOKEN_URI = 'https://www.googleapis.com/oauth2/v4/token'
@@ -66,7 +66,6 @@ def trigger_dag(data, context=None):
6666# START COPIED IAP CODE
6767def make_iap_request (url , client_id , method = 'GET' , ** kwargs ):
6868 """Makes a request to an application protected by Identity-Aware Proxy.
69-
7069 Args:
7170 url: The Identity-Aware Proxy-protected URL to fetch.
7271 client_id: The client ID used by Identity-Aware Proxy.
@@ -75,54 +74,16 @@ def make_iap_request(url, client_id, method='GET', **kwargs):
7574 **kwargs: Any of the parameters defined for the request function:
7675 https://github.com/requests/requests/blob/master/requests/api.py
7776 If no timeout is provided, it is set to 90 by default.
78-
7977 Returns:
8078 The page body, or raises an exception if the page couldn't be retrieved.
8179 """
8280 # Set the default timeout, if missing
8381 if 'timeout' not in kwargs :
8482 kwargs ['timeout' ] = 90
8583
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 )
84+ # Obtain an OpenID Connect (OIDC) token from metadata server or using service
85+ # account.
86+ google_open_id_connect_token = id_token .fetch_id_token (Request (), client_id )
12687
12788 # Fetch the Identity-Aware Proxy-protected URL, including an
12889 # Authorization header containing "Bearer " followed by a
@@ -132,49 +93,14 @@ def make_iap_request(url, client_id, method='GET', **kwargs):
13293 headers = {'Authorization' : 'Bearer {}' .format (
13394 google_open_id_connect_token )}, ** kwargs )
13495 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 ))
96+ raise Exception ('Service account does not have permission to '
97+ 'access the IAP-protected application.' )
13898 elif resp .status_code != 200 :
13999 raise Exception (
140100 'Bad response from application: {!r} / {!r} / {!r}' .format (
141101 resp .status_code , resp .headers , resp .text ))
142102 else :
143103 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' ]
178104# END COPIED IAP CODE
179105
180106# [END composer_trigger]
0 commit comments