diff options
author | arithmetic1728 <58957152+arithmetic1728@users.noreply.github.com> | 2021-10-21 15:25:46 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-21 15:25:46 -0700 |
commit | 5bd5ccf7cf229f033c7152ce0b650a40feb25f81 (patch) | |
tree | fb08f54a8732706a7633da0d464ae3823fd3fb4b /system_tests | |
parent | e2b3c98cd8c67b702be1b711c06ee7b9bbedb8ba (diff) | |
download | google-auth-library-python-5bd5ccf7cf229f033c7152ce0b650a40feb25f81.tar.gz |
fix: add back python 2.7 for gcloud usage only (#892)
* fix: add back python 2.7 for gcloud
* fix: fix setup and tests
* fix: add enum34 for python 2.7
* fix: add app engine app and fix noxfile
* fix: move test_app_engine.py
* fix: fix downscoped
* fix: fix downscoped
* fix: remove py2 from classifiers
Diffstat (limited to 'system_tests')
9 files changed, 253 insertions, 15 deletions
diff --git a/system_tests/noxfile.py b/system_tests/noxfile.py index 540727e..459b71c 100644 --- a/system_tests/noxfile.py +++ b/system_tests/noxfile.py @@ -171,7 +171,7 @@ def configure_cloud_sdk(session, application_default_credentials, project=False) TEST_DEPENDENCIES_ASYNC = ["aiohttp", "pytest-asyncio", "nest-asyncio"] TEST_DEPENDENCIES_SYNC = ["pytest", "requests", "mock"] PYTHON_VERSIONS_ASYNC = ["3.7"] -PYTHON_VERSIONS_SYNC = ["3.7"] +PYTHON_VERSIONS_SYNC = ["2.7", "3.7"] def default(session, *test_paths): @@ -287,6 +287,50 @@ def compute_engine(session): ) +@nox.session(python=["2.7"]) +def app_engine(session): + if SKIP_GAE_TEST_ENV in os.environ: + session.log("Skipping App Engine tests.") + return + + session.install(LIBRARY_DIR) + # Unlike the default tests above, the App Engine system test require a + # 'real' gcloud sdk installation that is configured to deploy to an + # app engine project. + # Grab the project ID from the cloud sdk. + project_id = ( + subprocess.check_output( + ["gcloud", "config", "list", "project", "--format", "value(core.project)"] + ) + .decode("utf-8") + .strip() + ) + + if not project_id: + session.error( + "The Cloud SDK must be installed and configured to deploy to App " "Engine." + ) + + application_url = GAE_APP_URL_TMPL.format(GAE_TEST_APP_SERVICE, project_id) + + # Vendor in the test application's dependencies + session.chdir(os.path.join(HERE, "system_tests_sync/app_engine_test_app")) + session.install(*TEST_DEPENDENCIES_SYNC) + session.run( + "pip", "install", "--target", "lib", "-r", "requirements.txt", silent=True + ) + + # Deploy the application. + session.run("gcloud", "app", "deploy", "-q", "app.yaml") + + # Run the tests + session.env["TEST_APP_URL"] = application_url + session.chdir(HERE) + default( + session, "system_tests_sync/test_app_engine.py", + ) + + @nox.session(python=PYTHON_VERSIONS_SYNC) def grpc(session): session.install(LIBRARY_DIR) @@ -339,9 +383,8 @@ def mtls_http(session): def external_accounts(session): session.install( *TEST_DEPENDENCIES_SYNC, - "google-auth", + LIBRARY_DIR, "google-api-python-client", - "enum34", ) default( session, @@ -354,7 +397,7 @@ def external_accounts(session): def downscoping(session): session.install( *TEST_DEPENDENCIES_SYNC, - "google-auth", + LIBRARY_DIR, "google-cloud-storage", ) default( diff --git a/system_tests/system_tests_sync/app_engine_test_app/.gitignore b/system_tests/system_tests_sync/app_engine_test_app/.gitignore new file mode 100644 index 0000000..7951405 --- /dev/null +++ b/system_tests/system_tests_sync/app_engine_test_app/.gitignore @@ -0,0 +1 @@ +lib
\ No newline at end of file diff --git a/system_tests/system_tests_sync/app_engine_test_app/app.yaml b/system_tests/system_tests_sync/app_engine_test_app/app.yaml new file mode 100644 index 0000000..06f2270 --- /dev/null +++ b/system_tests/system_tests_sync/app_engine_test_app/app.yaml @@ -0,0 +1,12 @@ +api_version: 1 +service: google-auth-system-tests +runtime: python27 +threadsafe: true + +handlers: +- url: .* + script: main.app + +libraries: +- name: ssl + version: 2.7.11
\ No newline at end of file diff --git a/system_tests/system_tests_sync/app_engine_test_app/appengine_config.py b/system_tests/system_tests_sync/app_engine_test_app/appengine_config.py new file mode 100644 index 0000000..1197ab5 --- /dev/null +++ b/system_tests/system_tests_sync/app_engine_test_app/appengine_config.py @@ -0,0 +1,30 @@ +# Copyright 2016 Google LLC +# +# 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. + +from google.appengine.ext import vendor + +# Add any libraries installed in the "lib" folder. +vendor.add("lib") + + +# Patch os.path.expanduser. This should be fixed in GAE +# versions released after Nov 2016. +import os.path + + +def patched_expanduser(path): + return path + + +os.path.expanduser = patched_expanduser
\ No newline at end of file diff --git a/system_tests/system_tests_sync/app_engine_test_app/main.py b/system_tests/system_tests_sync/app_engine_test_app/main.py new file mode 100644 index 0000000..f44ed4c --- /dev/null +++ b/system_tests/system_tests_sync/app_engine_test_app/main.py @@ -0,0 +1,129 @@ +# Copyright 2016 Google LLC 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. + +"""App Engine standard application that runs basic system tests for +google.auth.app_engine. +This application has to run tests manually instead of using pytest because +pytest currently doesn't work on App Engine standard. +""" + +import contextlib +import json +import sys +from StringIO import StringIO +import traceback + +from google.appengine.api import app_identity +import google.auth +from google.auth import _helpers +from google.auth import app_engine +import google.auth.transport.urllib3 +import urllib3.contrib.appengine +import webapp2 + +FAILED_TEST_TMPL = """ +Test {} failed: {} +Stacktrace: +{} +Captured output: +{} +""" +TOKEN_INFO_URL = "https://www.googleapis.com/oauth2/v3/tokeninfo" +EMAIL_SCOPE = "https://www.googleapis.com/auth/userinfo.email" +HTTP = urllib3.contrib.appengine.AppEngineManager() +HTTP_REQUEST = google.auth.transport.urllib3.Request(HTTP) + + +def test_credentials(): + credentials = app_engine.Credentials() + scoped_credentials = credentials.with_scopes([EMAIL_SCOPE]) + + scoped_credentials.refresh(None) + + assert scoped_credentials.valid + assert scoped_credentials.token is not None + + # Get token info and verify scope + url = _helpers.update_query( + TOKEN_INFO_URL, {"access_token": scoped_credentials.token} + ) + response = HTTP_REQUEST(url=url, method="GET") + token_info = json.loads(response.data.decode("utf-8")) + + assert token_info["scope"] == EMAIL_SCOPE + + +def test_default(): + credentials, project_id = google.auth.default() + + assert isinstance(credentials, app_engine.Credentials) + assert project_id == app_identity.get_application_id() + + +@contextlib.contextmanager +def capture(): + """Context manager that captures stderr and stdout.""" + oldout, olderr = sys.stdout, sys.stderr + try: + out = StringIO() + sys.stdout, sys.stderr = out, out + yield out + finally: + sys.stdout, sys.stderr = oldout, olderr + + +def run_test_func(func): + with capture() as capsys: + try: + func() + return True, "" + except Exception as exc: + output = FAILED_TEST_TMPL.format( + func.func_name, exc, traceback.format_exc(), capsys.getvalue() + ) + return False, output + + +def run_tests(): + """Runs all tests. + Returns: + Tuple[bool, str]: A tuple containing True if all tests pass, False + otherwise, and any captured output from the tests. + """ + status = True + output = "" + + tests = (test_credentials, test_default) + + for test in tests: + test_status, test_output = run_test_func(test) + status = status and test_status + output += test_output + + return status, output + + +class MainHandler(webapp2.RequestHandler): + def get(self): + self.response.headers["content-type"] = "text/plain" + + status, output = run_tests() + + if not status: + self.response.status = 500 + + self.response.write(output) + + +app = webapp2.WSGIApplication([("/", MainHandler)], debug=True)
\ No newline at end of file diff --git a/system_tests/system_tests_sync/app_engine_test_app/requirements.txt b/system_tests/system_tests_sync/app_engine_test_app/requirements.txt new file mode 100644 index 0000000..cb8a382 --- /dev/null +++ b/system_tests/system_tests_sync/app_engine_test_app/requirements.txt @@ -0,0 +1,3 @@ +urllib3 +# Relative path to google-auth-python's source. +../../..
\ No newline at end of file diff --git a/system_tests/system_tests_sync/test_app_engine.py b/system_tests/system_tests_sync/test_app_engine.py new file mode 100644 index 0000000..79776ce --- /dev/null +++ b/system_tests/system_tests_sync/test_app_engine.py @@ -0,0 +1,22 @@ +# Copyright 2016 Google LLC +# +# 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. + +import os + +TEST_APP_URL = os.environ["TEST_APP_URL"] + + +def test_live_application(http_request): + response = http_request(method="GET", url=TEST_APP_URL) + assert response.status == 200, response.data.decode("utf-8")
\ No newline at end of file diff --git a/system_tests/system_tests_sync/test_downscoping.py b/system_tests/system_tests_sync/test_downscoping.py index 77224ae..fdb4efa 100644 --- a/system_tests/system_tests_sync/test_downscoping.py +++ b/system_tests/system_tests_sync/test_downscoping.py @@ -28,7 +28,7 @@ import pytest # The object prefix used to test access to files beginning with this prefix. _OBJECT_PREFIX = "customer-a" # The object name of the object inaccessible by the downscoped token. -_ACCESSIBLE_OBJECT_NAME = f"{_OBJECT_PREFIX}-data.txt" +_ACCESSIBLE_OBJECT_NAME = "{0}-data.txt".format(_OBJECT_PREFIX) # The content of the object accessible by the downscoped token. _ACCESSIBLE_CONTENT = "hello world" # The content of the object inaccessible by the downscoped token. @@ -76,13 +76,13 @@ def get_token_from_broker(bucket_name, object_prefix): Tuple[str, datetime.datetime]: The downscoped access token and its expiry date. """ # Initialize the Credential Access Boundary rules. - available_resource = f"//storage.googleapis.com/projects/_/buckets/{bucket_name}" + available_resource = "//storage.googleapis.com/projects/_/buckets/{0}".format(bucket_name) # Downscoped credentials will have readonly access to the resource. available_permissions = ["inRole:roles/storage.objectViewer"] # Only objects starting with the specified prefix string in the object name # will be allowed read access. availability_expression = ( - f"resource.name.startsWith('projects/_/buckets/{bucket_name}/objects/{object_prefix}')" + "resource.name.startsWith('projects/_/buckets/{0}/objects/{1}')".format(bucket_name, object_prefix) ) availability_condition = downscoped.AvailabilityCondition(availability_expression) # Define the single access boundary rule using the above properties. diff --git a/system_tests/system_tests_sync/test_external_accounts.py b/system_tests/system_tests_sync/test_external_accounts.py index c2855a2..e24c7b4 100644 --- a/system_tests/system_tests_sync/test_external_accounts.py +++ b/system_tests/system_tests_sync/test_external_accounts.py @@ -32,21 +32,19 @@ # original service account key. -from http.server import BaseHTTPRequestHandler -from http.server import HTTPServer import json import os import socket -import sys from tempfile import NamedTemporaryFile import threading -import pytest -from mock import patch - +import sys import google.auth from googleapiclient import discovery +from six.moves import BaseHTTPServer from google.oauth2 import service_account +import pytest +from mock import patch # Populate values from the output of scripts/setup_external_accounts.sh. _AUDIENCE_OIDC = "//iam.googleapis.com/projects/79992041559/locations/global/workloadIdentityPools/pool-73wslmxn/providers/oidc-73wslmxn" @@ -177,7 +175,7 @@ def test_file_based_external_account( # This test makes sure that setting up an http server to provide credentials # works to allow access to Google resources. def test_url_based_external_account(dns_access, oidc_credentials, service_account_info): - class TestResponseHandler(BaseHTTPRequestHandler): + class TestResponseHandler(BaseHTTPServer.BaseHTTPRequestHandler): def do_GET(self): if self.headers["my-header"] != "expected-value": self.send_response(400) @@ -201,7 +199,7 @@ def test_url_based_external_account(dns_access, oidc_credentials, service_accoun json.dumps({"access_token": oidc_credentials.token}).encode("utf-8") ) - class TestHTTPServer(HTTPServer, object): + class TestHTTPServer(BaseHTTPServer.HTTPServer, object): def __init__(self): self.port = self._find_open_port() super(TestHTTPServer, self).__init__(("", self.port), TestResponseHandler) |