Skip to content

Commit

Permalink
Adding endpoints sample
Browse files Browse the repository at this point in the history
Change-Id: I8327d5ecd2319016503fb8d07dfa34fb90ebef04
  • Loading branch information
Jon Wayne Parrott authored and broady committed Apr 28, 2016
1 parent fe59a33 commit d4f083b
Show file tree
Hide file tree
Showing 10 changed files with 564 additions and 0 deletions.
1 change: 1 addition & 0 deletions managed_vms/endpoints/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
endpoints
95 changes: 95 additions & 0 deletions managed_vms/endpoints/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Google Cloud Endpoints & App Engine Flexible Environment & Python

This sample demonstrates how to use Google Cloud Endpoints on Google App Engine Flexible Environment using Python.

This sample consists of two parts:

1. The backend
2. The clients

## Running locally

### Running the backend

For more info on running Flexible applications locally, see [the getting started documentation](https://cloud.google.com/appengine/docs/managed-vms/python/hello-world).

Install all the dependencies:

$ virtualenv env
$ source env/bin/activate
$ pip install -r requirements.txt

Run the application:

$ python main.py

In your web browser, go to the following address: http://localhost:8080.

### Using the echo client

With the app running locally, you can execute the simple echo client using:

$ python clients/echo-client.py http://localhost:8080 APIKEY

The `APIKEY` doesn't matter as the endpoint proxy is not running to do authentication.

## Deploying to Google App Engine

Open the `swagger.yaml` file and in the `host` property, replace
`YOUR-PROJECT-ID` with your project's ID.

Then, deploy the sample using `gcloud`:

gcloud preview app deploy app.yaml

Once deployed, you can access the application at https://YOUR-PROJECT-ID.appspot.com/.

### Using the echo client

With the project deployed, you'll need to create an API key to access the API.

1. Open the Credentials page of the API Manager in the [Cloud Console](https://console.cloud.google.com/apis/credentials).
2. Click 'Create credentials'.
3. Select 'API Key'.
4. Choose 'Server Key'

With the API key, you can use the echo client to access the API:

$ python clients/echo-client.py https://YOUR-PROJECT-ID.appspot.com YOUR-API-KEY

### Using the JWT client.

The JWT client demonstrates how to use service accounts to authenticate to endpoints. To use the client, you'll need both an API key (as described in the echo client section) and a service account. To create a service account:

1. Open the Credentials page of the API Manager in the [Cloud Console](https://console.cloud.google.com/apis/credentials).
2. Click 'Create credentials'.
3. Select 'Service account key'.
4. In the 'Select service account' dropdown, select 'Create new service account'.
5. Choose 'JSON' for the key type.

To use the service account for authentication:

1. Update the `google_jwt`'s `x-jwks_uri` in `swagger.yaml` with your service account's email address.
2. Redeploy your application.

Now you can use the JWT client to make requests to the API:

$ python clients/google-jwt-client.py https://YOUR-PROJECT-ID.appspot.com YOUR-API-KEY /path/to/service-account.json

### Using the ID Token client.

The ID Token client demonstrates how to use user credentials to authenticate to endpoints. To use the client, you'll need both an API key (as described in the echo client section) and a OAuth2 client ID. To create a client ID:

1. Open the Credentials page of the API Manager in the [Cloud Console](https://console.cloud.google.com/apis/credentials).
2. Click 'Create credentials'.
3. Select 'OAuth client ID'.
4. Choose 'Other' for the application type.

To use the client ID for authentication:

1. Update the `/auth/info/googleidtoken`'s `audiences` in `swagger.yaml` with your client ID.
2. Redeploy your application.

Now you can use the client ID to make requests to the API:

$ python clients/google-id-token-client.py https://YOUR-PROJECT-ID.appspot.com YOUR-API-KEY /path/to/client-id.json
12 changes: 12 additions & 0 deletions managed_vms/endpoints/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
runtime: python
vm: true
entrypoint: gunicorn -b :$PORT main:app

runtime_config:
python_version: 3

beta_settings:
# Enable Google Cloud Endpoints API management.
use_endpoints_api_management: true
# Specify the Swagger API specification.
endpoints_swagger_spec_file: swagger.yaml
60 changes: 60 additions & 0 deletions managed_vms/endpoints/clients/echo-client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env python

# Copyright 2016 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Example of calling a simple Google Cloud Endpoint API."""

import argparse

import requests
from six.moves import urllib


def make_request(host, api_key, message):
"""Makes a request to the auth info endpoint for Google ID tokens."""
url = urllib.parse.urljoin(host, 'echo')
params = {
'key': api_key
}
body = {
'message': message
}

response = requests.post(url, params=params, json=body)

response.raise_for_status()
return response.text


def main(host, api_key, message):
response = make_request(host, api_key, message)
print(response)


if __name__ == '__main__':
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument(
'host', help='Your API host, e.g. https://your-project.appspot.com.')
parser.add_argument(
'api_key', help='Your API key.')
parser.add_argument(
'message',
help='Message to echo.')

args = parser.parse_args()

main(args.host, args.api_key, args.message)
82 changes: 82 additions & 0 deletions managed_vms/endpoints/clients/google-id-token-client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env python

# Copyright 2016 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Example of calling a Google Cloud Endpoint API with an ID token obtained
using the Google OAuth2 flow."""

import argparse

import oauth2client.client
import oauth2client.tools
import oauth2client.file
import requests
from six.moves import urllib


def get_id_token(client_secrets_file, extra_args):
storage = oauth2client.file.Storage('credentials.dat')
credentials = storage.get()

if not credentials or credentials.invalid:
flow = oauth2client.client.flow_from_clientsecrets(
client_secrets_file, scope='email')
credentials = oauth2client.tools.run_flow(
flow, storage, flags=extra_args)

# The ID token is used by Cloud Endpoints, not the access token.
id_token = credentials.token_response['id_token']

return id_token


def make_request(host, api_key, id_token):
"""Makes a request to the auth info endpoint for Google ID tokens."""
url = urllib.parse.urljoin(host, '/auth/info/googleidtoken')
params = {
'key': api_key
}
headers = {
'Authorization': 'Bearer {}'.format(id_token)
}

response = requests.get(url, params=params, headers=headers)

response.raise_for_status()
return response.text


def main(host, api_key, client_secrets_file, extra_args):
id_token = get_id_token(client_secrets_file, extra_args)
response = make_request(host, api_key, id_token)
print(response)


if __name__ == '__main__':
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter,
parents=[oauth2client.tools.argparser])
parser.add_argument(
'host', help='Your API host, e.g. https://your-project.appspot.com.')
parser.add_argument(
'api_key', help='Your API key.')
parser.add_argument(
'client_secrets_file',
help='The path to your OAuth2 client secrets file.')

args = parser.parse_args()

main(args.host, args.api_key, args.client_secrets_file, args)
92 changes: 92 additions & 0 deletions managed_vms/endpoints/clients/google-jwt-client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/usr/bin/env python

# Copyright 2016 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Example of calling a Google Cloud Endpoint API with a JWT signed by
a Google API Service Account."""

import argparse
import time

import oauth2client.crypt
from oauth2client.service_account import ServiceAccountCredentials
import requests
from six.moves import urllib


def generate_jwt(service_account_file):
"""Generates a signed JSON Web Token using a Google API Service Account."""
credentials = ServiceAccountCredentials.from_json_keyfile_name(
service_account_file)

now = int(time.time())

payload = {
'iat': now,
'exp': now + credentials.MAX_TOKEN_LIFETIME_SECS,
# aud must match 'audience' in the security configuration in your
# swagger spec. It can be any string.
'aud': 'echo.endpoints.sample.google.com',
# iss must match 'issuer' in the security configuration in your
# swagger spec. It can be any string.
'iss': 'jwt-client.endpoints.sample.google.com',
# sub and email are mapped to the user id and email respectively.
'sub': '12345678',
'email': 'user@example.com'
}

signed_jwt = oauth2client.crypt.make_signed_jwt(
credentials._signer, payload, key_id=credentials._private_key_id)

return signed_jwt


def make_request(host, api_key, signed_jwt):
"""Makes a request to the auth info endpoint for Google JWTs."""
url = urllib.parse.urljoin(host, '/auth/info/googlejwt')
params = {
'key': api_key
}
headers = {
'Authorization': 'Bearer {}'.format(signed_jwt)
}

response = requests.get(url, params=params, headers=headers)

response.raise_for_status()
return response.text


def main(host, api_key, service_account_file):
signed_jwt = generate_jwt(service_account_file)
response = make_request(host, api_key, signed_jwt)
print(response)


if __name__ == '__main__':
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument(
'host', help='Your API host, e.g. https://your-project.appspot.com.')
parser.add_argument(
'api_key', help='Your API key.')
parser.add_argument(
'service_account_file',
help='The path to your service account json file.')

args = parser.parse_args()

main(args.host, args.api_key, args.service_account_file)
19 changes: 19 additions & 0 deletions managed_vms/endpoints/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Endpoints Echo &amp; Auth Sample</title>
</head>
<body>
<h1>Welcome to your Endpoints Sample</h1>
<p>Congratulations on successfully setting up and deploying your Endpoints bookstore sample.</p>
<p>Here are some helpful links:</p>
<ul>
<li><a href="/echo">Echo Sample</a> - a simple echo service.</li>
<li><a href="/api-docs">Raw Swagger Spec</a> - a link to your <pre>swagger.json</pre>.</li>
<li><a href="https://github.com/swagger-api/swagger-ui">Swagger UI</a> - a documentation tool to explore your Swagger spec</li>
<li><a href="https://console.cloud.google.com">Google Cloud Console</a> - manage your deployment</li>
</ul>
</body>
</html>
Loading

0 comments on commit d4f083b

Please sign in to comment.