aboutsummaryrefslogtreecommitdiff
path: root/system_tests
diff options
context:
space:
mode:
authorarithmetic1728 <58957152+arithmetic1728@users.noreply.github.com>2021-10-21 15:25:46 -0700
committerGitHub <noreply@github.com>2021-10-21 15:25:46 -0700
commit5bd5ccf7cf229f033c7152ce0b650a40feb25f81 (patch)
treefb08f54a8732706a7633da0d464ae3823fd3fb4b /system_tests
parente2b3c98cd8c67b702be1b711c06ee7b9bbedb8ba (diff)
downloadgoogle-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')
-rw-r--r--system_tests/noxfile.py51
-rw-r--r--system_tests/system_tests_sync/app_engine_test_app/.gitignore1
-rw-r--r--system_tests/system_tests_sync/app_engine_test_app/app.yaml12
-rw-r--r--system_tests/system_tests_sync/app_engine_test_app/appengine_config.py30
-rw-r--r--system_tests/system_tests_sync/app_engine_test_app/main.py129
-rw-r--r--system_tests/system_tests_sync/app_engine_test_app/requirements.txt3
-rw-r--r--system_tests/system_tests_sync/test_app_engine.py22
-rw-r--r--system_tests/system_tests_sync/test_downscoping.py6
-rw-r--r--system_tests/system_tests_sync/test_external_accounts.py14
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)