| # Copyright 2020 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style |
| # license that can be found in the LICENSE file. |
| |
| #!/usr/bin/env python |
| """ |
| This is an example of how a script might make calls to monorail's v3 pRPC API. |
| |
| Usage example: |
| ``` |
| python v3_test_call.py \ |
| monorail.v3.Issues GetIssue '{"name": "projects/monorail/issues/404"}' |
| ``` |
| |
| The email of your service account should be allow-listed with Monorail. |
| """ |
| |
| import argparse |
| import json |
| import logging |
| import os |
| import requests |
| |
| |
| # Older versions of https://github.com/googleapis/google-auth-library-python |
| # do not have the fetch_id_token() method called below. |
| # v1.15.0 or later should be fine. |
| from google.oauth2 import id_token |
| from google.auth.transport import requests as google_requests |
| |
| # Download and save your service account credentials file in |
| # api/service-account-key.json. |
| # id_token.fetch_id_token looks inside GOOGLE_APPLICATION_CREDENTIALS to fetch |
| # service account credentials. |
| os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'service-account-key.json' |
| |
| # BASE_URL can point to any monorail-dev api service version. |
| # However, you MAY get ssl cert errors when BASE_URL is not the |
| # default below. If this happens you will have to test your version |
| # by using the existing BASE_URL and migrating all traffic to your api |
| # version via pantheon. |
| BASE_URL = 'https://api-dot-monorail-dev.appspot.com/prpc' |
| |
| # TARGET_AUDIENCE should not change as long as BASE_URL is pointing to |
| # some monorail-dev version. If BASE_URL is updated to point to |
| # monorail-{staging|prod}, update TARGET_AUDIENCE accordingly. |
| TARGET_AUDIENCE = 'https://monorail-dev.appspot.com' |
| |
| # XSSI_PREFIX found at the beginning of every prpc response. |
| XSSI_PREFIX = ")]}'\n" |
| |
| import httplib2 |
| from oauth2client.client import GoogleCredentials |
| |
| |
| def make_call(service, method, json_body): |
| # Fetch ID token |
| request = google_requests.Request() |
| token = id_token.fetch_id_token(request, TARGET_AUDIENCE) |
| # Note: ID tokens for service accounts can also be fetched with with the |
| # Cloud IAM API projects.serviceAccounts.generateIdToken |
| # generateIdToken only needs the service account email or ID and the |
| # target_audience. |
| |
| # Call monorail's API. |
| headers = { |
| 'Authorization': 'Bearer %s' % token, |
| 'Content-Type': 'application/json', |
| 'Accept': 'application/json', |
| } |
| |
| url = "%s/%s/%s" % (BASE_URL, service, method) |
| |
| body = json.loads(json_body) |
| resp = requests.post(url, data=json.dumps(body), headers=headers) |
| logging.info(resp) |
| logging.info(resp.text) |
| logging.info(resp.content) |
| logging.info(json.dumps(json.loads(resp.content[len(XSSI_PREFIX):]))) |
| |
| # Verify and decode ID token to take a look at what's inside. |
| # API users should not have to do this. This is just for learning about |
| # how ID tokens work. |
| request = google_requests.Request() |
| id_info = id_token.verify_oauth2_token(token, request) |
| logging.info('id_info %s' % id_info) |
| |
| |
| if __name__ == '__main__': |
| parser = argparse.ArgumentParser(description='Process some integers.') |
| parser.add_argument('service', help='pRPC service name.') |
| parser.add_argument('method', help='pRPC method name.') |
| parser.add_argument('json_body', help='pRPC HTTP body in valid JSON.') |
| args = parser.parse_args() |
| log_level = logging.INFO |
| logging.basicConfig(format='%(levelname)s: %(message)s', level=log_level) |
| make_call(args.service, args.method, args.json_body) |