blob: 6d5b01abdb47127203eee082dc2ef4643c6446a5 [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001# Copyright 2020 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style
3# license that can be found in the LICENSE file.
4
5#!/usr/bin/env python
6"""
7This script requires `google-auth` 1.15.0 or higher.
8To update this for monorail's third_party run the following from
9monorail/third_party/google:
10bash ./update.sh 1.15.0
11
12This is an example of how a script might make calls to monorail's v3 pRPC API.
13
14Usage example:
15```
16python v3_test_call.py \
17monorail.v3.Issues GetIssue '{"name": "projects/monorail/issues/404"}'
18```
19
20The email of your service account should be allow-listed with Monorail.
21"""
22
23import argparse
24import json
25import logging
26import os
27import sys
28import requests
29
30monorail_dir = os.path.dirname(os.path.abspath(__file__ + '/..'))
31third_party_path = os.path.join(monorail_dir, 'third_party')
32if third_party_path not in sys.path:
33 sys.path.insert(0, third_party_path)
34
35# Older versions of https://github.com/googleapis/google-auth-library-python
36# do not have the fetch_id_token() method called below.
37# v1.15.0 or later should be fine.
38from google.oauth2 import id_token
39from google.auth.transport import requests as google_requests
40
41# Download and save your service account credentials file in
42# api/service-account-key.json.
43# id_token.fetch_id_token looks inside GOOGLE_APPLICATION_CREDENTIALS to fetch
44# service account credentials.
45os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'service-account-key.json'
46
47# BASE_URL can point to any monorail-dev api service version.
48# However, you MAY get ssl cert errors when BASE_URL is not the
49# default below. If this happens you will have to test your version
50# by using the existing BASE_URL and migrating all traffic to your api
51# version via pantheon.
52BASE_URL = 'https://api-dot-monorail-dev.appspot.com/prpc'
53
54# TARGET_AUDIENCE should not change as long as BASE_URL is pointing to
55# some monorail-dev version. If BASE_URL is updated to point to
56# monorail-{staging|prod}, update TARGET_AUDIENCE accordingly.
57TARGET_AUDIENCE = 'https://monorail-dev.appspot.com'
58
59# XSSI_PREFIX found at the beginning of every prpc response.
60XSSI_PREFIX = ")]}'\n"
61
62import httplib2
63from oauth2client.client import GoogleCredentials
64
65
66def make_call(service, method, json_body):
67 # Fetch ID token
68 request = google_requests.Request()
69 token = id_token.fetch_id_token(request, TARGET_AUDIENCE)
70 # Note: ID tokens for service accounts can also be fetched with with the
71 # Cloud IAM API projects.serviceAccounts.generateIdToken
72 # generateIdToken only needs the service account email or ID and the
73 # target_audience.
74
75 # Call monorail's API.
76 headers = {
77 'Authorization': 'Bearer %s' % token,
78 'Content-Type': 'application/json',
79 'Accept': 'application/json',
80 }
81
82 url = "%s/%s/%s" % (BASE_URL, service, method)
83
84 body = json.loads(json_body)
85 resp = requests.post(url, data=json.dumps(body), headers=headers)
86 logging.info(resp)
87 logging.info(resp.text)
88 logging.info(resp.content)
89 logging.info(json.dumps(json.loads(resp.content[len(XSSI_PREFIX):])))
90
91 # Verify and decode ID token to take a look at what's inside.
92 # API users should not have to do this. This is just for learning about
93 # how ID tokens work.
94 request = google_requests.Request()
95 id_info = id_token.verify_oauth2_token(token, request)
96 logging.info('id_info %s' % id_info)
97
98
99if __name__ == '__main__':
100 parser = argparse.ArgumentParser(description='Process some integers.')
101 parser.add_argument('service', help='pRPC service name.')
102 parser.add_argument('method', help='pRPC method name.')
103 parser.add_argument('json_body', help='pRPC HTTP body in valid JSON.')
104 args = parser.parse_args()
105 log_level = logging.INFO
106 logging.basicConfig(format='%(levelname)s: %(message)s', level=log_level)
107 make_call(args.service, args.method, args.json_body)