Skip to content

Commit fb25b01

Browse files
3a3crwilcoxleahecole
authored
fix make_iap_request (GoogleCloudPlatform#3731)
* fix make_iap_request * Update composer_storage_trigger.py Co-authored-by: Christopher Wilcox <crwilcox@google.com> Co-authored-by: Leah E. Cole <6719667+leahecole@users.noreply.github.com>
1 parent abdbcb7 commit fb25b01

File tree

1 file changed

+6
-79
lines changed

1 file changed

+6
-79
lines changed

functions/composer/composer_storage_trigger.py

Lines changed: 6 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import google.auth.compute_engine.credentials
1919
import google.auth.iam
2020
from google.auth.transport.requests import Request
21+
from google.oauth2 import id_token
2122
import google.oauth2.credentials
2223
import google.oauth2.service_account
2324
import requests
@@ -66,7 +67,6 @@ def trigger_dag(data, context=None):
6667
# START COPIED IAP CODE
6768
def 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

Comments
 (0)