Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f5cb089

Browse files
committed
Explore new IAP sample
1 parent f13dcb3 commit f5cb089

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed

iap/service_account_iap_request.py

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
#!/bin/python
2+
# Copyright 2019 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.rom googleapiclient import discovery
15+
16+
"""Use a service account to access an IAP protected resource"""
17+
18+
19+
def get_private_key(json_file_name):
20+
"""Gets a service account's private key
21+
22+
Args:
23+
json_file_name: the file containing the downloaded key information
24+
25+
Returns:
26+
The private key from the file
27+
"""
28+
29+
import json
30+
31+
with open(json_file_name, 'r') as f:
32+
json_key = f.read()
33+
34+
key = json.loads(json_key)
35+
return key['private_key']
36+
37+
38+
def build_claim(client_id, service_account):
39+
"""Creates the necessary claim to request access to an IAP protected URL
40+
Args:
41+
client_id: the OAuth client ID. Available from API/Credentials console
42+
service_account: the service account email
43+
44+
45+
Returns:
46+
The claim
47+
"""
48+
import time
49+
50+
oauth_endpoint = 'https://www.googleapis.com/oauth2/v4/token'
51+
now = int(time.time())
52+
53+
claim = {
54+
'iss': service_account,
55+
'target_audience': client_id,
56+
'iat': now,
57+
'exp': now + 3600,
58+
'aud': oauth_endpoint
59+
}
60+
61+
return claim
62+
63+
64+
def create_assertion(claim, private_key):
65+
"""Creates an assertion - a signed claim of authorization
66+
67+
Args:
68+
claim: the claim to send to the OAuth2 service (from build_claim)
69+
private_key: the service account's private key (in PEM format)
70+
71+
Returns:
72+
The assertion
73+
"""
74+
import jwt
75+
76+
assertion = jwt.encode(
77+
claim,
78+
private_key,
79+
algorithm='RS256'
80+
)
81+
82+
return assertion
83+
84+
85+
def get_id_token(claim, private_key):
86+
"""Gets an OpenID Connect token for the given private key
87+
88+
Args:
89+
claim: the claim to send to the OAuth2 service (from build_claim)
90+
private_key: the service account's private key (in PEM format)
91+
92+
Returns:
93+
An OpenID connect token to authenticate requests from the service acct
94+
"""
95+
96+
import json
97+
import requests
98+
99+
assertion = create_assertion(claim, private_key)
100+
101+
endpoint = claim['aud']
102+
grant_type = 'urn:ietf:params:oauth:grant-type:jwt-bearer'
103+
104+
response = requests.post(
105+
endpoint,
106+
data = {
107+
'grant_type': grant_type,
108+
'assertion': assertion
109+
}
110+
)
111+
112+
print(response.text)
113+
114+
id_token = response.json()['id_token']
115+
return id_token
116+
117+
118+
def request(client_id, service_account, private_key, method, url, **kwargs):
119+
"""Acts like requests.request, but includes IAP required authentication
120+
121+
Args:
122+
client_id: the OAuth client ID. Available from API/Credentials console
123+
service_account: the service account email
124+
private_key: the service account's private key, in PEM format
125+
126+
Remaining arguments are passed through to requests.request
127+
method: the HTTP method
128+
url: the address to access
129+
kwargs: other arguments to pass to requests.request
130+
131+
Returns:
132+
The requests Response object from the request
133+
"""
134+
135+
import requests
136+
137+
# Add Authorization header using service account and client information
138+
claim = build_claim(client_id, service_account)
139+
id_token = get_id_token(claim, private_key)
140+
141+
if 'headers' not in kwargs:
142+
kwargs['headers'] = {}
143+
kwargs['headers']['Authorization'] = 'Bearer {}'.format(id_token)
144+
145+
# Make request with added Authorization header
146+
return requests.request(method, url, **kwargs)
147+
148+
149+
def main():
150+
"""Make a GET request to the IAP-protected URL using service account creds
151+
"""
152+
153+
import argparse
154+
155+
parser = argparse.ArgumentParser(
156+
description='Call IAP protected resource with service account'
157+
)
158+
159+
parser.add_argument('client_id', help="The protected site's client ID")
160+
parser.add_argument('service_account', help="The service account's email")
161+
parser.add_argument('key_file', help="The service account's key file")
162+
parser.add_argument('url', help="URL to access")
163+
164+
args = parser.parse_args()
165+
166+
private_key = get_private_key(args.key_file)
167+
168+
response = request(
169+
args.client_id, args.service_account, private_key, 'GET', args.url
170+
)
171+
172+
print('Status code: {} {}'.format(response.status_code, response.reason))
173+
print('Headers:')
174+
for key in response.headers:
175+
print(' {}: {}'.format(key, response.headers[key]))
176+
print('Body:')
177+
print(response.text)
178+
179+
180+
if __name__ == '__main__':
181+
main()

0 commit comments

Comments
 (0)