diff options
author | 2017-12-23 21:49:35 +0100 | |
---|---|---|
committer | 2017-12-23 21:49:58 +0100 | |
commit | 1100c66ce03a059ebe7ece9734e799b49b3a5a9e (patch) | |
tree | a057e7e7511f6675a9327b79e6919f07c5f89f07 /keystonemiddleware-moon | |
parent | 7a4dfdde6314476ae2a1a1c881ff1e3c430f790e (diff) |
moonv4 cleanup
Change-Id: Icef927f3236d985ac13ff7376f6ce6314b2b39b0
Signed-off-by: WuKong <rebirthmonkey@gmail.com>
Diffstat (limited to 'keystonemiddleware-moon')
130 files changed, 0 insertions, 14349 deletions
diff --git a/keystonemiddleware-moon/.coveragerc b/keystonemiddleware-moon/.coveragerc deleted file mode 100644 index 75b0fcb0..00000000 --- a/keystonemiddleware-moon/.coveragerc +++ /dev/null @@ -1,7 +0,0 @@ -[run] -branch = True -source = keystonemiddleware -omit = keystonemiddleware/tests/*,keystonemiddleware/openstack/* - -[report] -ignore-errors = True diff --git a/keystonemiddleware-moon/.gitignore b/keystonemiddleware-moon/.gitignore deleted file mode 100644 index bd6a3658..00000000 --- a/keystonemiddleware-moon/.gitignore +++ /dev/null @@ -1,55 +0,0 @@ -*.py[cod] - -# C extensions -*.so - -# Packages -*.egg -*.egg-info -dist -build -eggs -parts -bin -var -sdist -develop-eggs -.installed.cfg -lib -lib64 - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -.coverage -.tox -nosetests.xml -.testrepository -cover - -# Translations -*.mo - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# Complexity -output/*.html -output/*/index.html - -# Sphinx -doc/build - -# pbr generates these -AUTHORS -ChangeLog - -# Editors -*~ -.*.swp - -# Oslo Sync -.update-venv diff --git a/keystonemiddleware-moon/.gitreview b/keystonemiddleware-moon/.gitreview deleted file mode 100644 index 99b3a27f..00000000 --- a/keystonemiddleware-moon/.gitreview +++ /dev/null @@ -1,4 +0,0 @@ -[gerrit] -host=review.openstack.org -port=29418 -project=openstack/keystonemiddleware.git diff --git a/keystonemiddleware-moon/.testr.conf b/keystonemiddleware-moon/.testr.conf deleted file mode 100644 index 06f67a02..00000000 --- a/keystonemiddleware-moon/.testr.conf +++ /dev/null @@ -1,8 +0,0 @@ -[DEFAULT] -test_command= - OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ - OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ - OS_LOG_CAPTURE=${OS_LOG_CAPTURE:-1} \ - ${PYTHON:-python} -m subunit.run discover -t ./ ./keystonemiddleware/tests $LISTOPT $IDOPTION -test_id_option=--load-list $IDFILE -test_list_option=--list diff --git a/keystonemiddleware-moon/CONTRIBUTING.rst b/keystonemiddleware-moon/CONTRIBUTING.rst deleted file mode 100644 index ba308f23..00000000 --- a/keystonemiddleware-moon/CONTRIBUTING.rst +++ /dev/null @@ -1,16 +0,0 @@ -If you would like to contribute to the development of OpenStack, -you must follow the steps in this page: - - http://docs.openstack.org/infra/manual/developers.html - -Once those steps have been completed, changes to OpenStack -should be submitted for review via the Gerrit tool, following -the workflow documented at: - - http://docs.openstack.org/infra/manual/developers.html#development-workflow - -Pull requests submitted through GitHub will be ignored. - -Bugs should be filed on Launchpad, not GitHub: - - https://bugs.launchpad.net/keystonemiddleware diff --git a/keystonemiddleware-moon/HACKING.rst b/keystonemiddleware-moon/HACKING.rst deleted file mode 100644 index 77de6b32..00000000 --- a/keystonemiddleware-moon/HACKING.rst +++ /dev/null @@ -1,24 +0,0 @@ -Keystone Style Commandments -=========================== - -- Step 1: Read the OpenStack Style Commandments - http://docs.openstack.org/developer/hacking/ -- Step 2: Read on - -Exceptions ----------- - -When dealing with exceptions from underlying libraries, translate those -exceptions to an instance or subclass of ClientException. - -======= -Testing -======= - -Keystone Middleware uses testtools and testr for its unittest suite -and its test runner. Basic workflow around our use of tox and testr can -be found at http://wiki.openstack.org/testr. If you'd like to learn more -in depth: - - https://testtools.readthedocs.org/ - https://testrepository.readthedocs.org/ diff --git a/keystonemiddleware-moon/LICENSE b/keystonemiddleware-moon/LICENSE deleted file mode 100644 index 4a5b9421..00000000 --- a/keystonemiddleware-moon/LICENSE +++ /dev/null @@ -1,210 +0,0 @@ -Copyright (c) 2009 Jacob Kaplan-Moss - initial codebase (< v2.1) -Copyright (c) 2011 Rackspace - OpenStack extensions (>= v2.1) -Copyright (c) 2011 Nebula, Inc - Keystone refactor (>= v2.7) -Copyright (c) 2017 Orange - Moon platform (>= v3.0) -All rights reserved. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - ---- License for python-keystoneclient versions prior to 2.1 --- - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. Neither the name of this project nor the names of its contributors may - be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/keystonemiddleware-moon/MANIFEST.in b/keystonemiddleware-moon/MANIFEST.in deleted file mode 100644 index 29c06765..00000000 --- a/keystonemiddleware-moon/MANIFEST.in +++ /dev/null @@ -1,7 +0,0 @@ -include README.rst -include AUTHORS HACKING LICENSE -include ChangeLog -include run_tests.sh tox.ini -recursive-include doc * -recursive-include tests * -recursive-include tools * diff --git a/keystonemiddleware-moon/README.rst b/keystonemiddleware-moon/README.rst deleted file mode 100644 index fcbdbdde..00000000 --- a/keystonemiddleware-moon/README.rst +++ /dev/null @@ -1,19 +0,0 @@ -Middleware for the OpenStack Identity API (Keystone) -==================================================== - -This package contains middleware modules designed to provide authentication and -authorization features to web services other than `Keystone -<https://github.com/openstack/keystone>`. The most prominent module is -``keystonemiddleware.auth_token``. This package does not expose any CLI or -Python API features. - -For information on contributing, see ``CONTRIBUTING.rst``. - -* License: Apache License, Version 2.0 -* Documentation: http://docs.openstack.org/developer/keystonemiddleware -* Source: http://git.openstack.org/cgit/openstack/keystonemiddleware -* Bugs: http://bugs.launchpad.net/keystonemiddleware - -For any other information, refer to the parent project, Keystone: - - https://github.com/openstack/keystone diff --git a/keystonemiddleware-moon/babel.cfg b/keystonemiddleware-moon/babel.cfg deleted file mode 100644 index 79cd39bf..00000000 --- a/keystonemiddleware-moon/babel.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[python: **.py] - - diff --git a/keystonemiddleware-moon/bandit.yaml b/keystonemiddleware-moon/bandit.yaml deleted file mode 100644 index d4e7dbca..00000000 --- a/keystonemiddleware-moon/bandit.yaml +++ /dev/null @@ -1,134 +0,0 @@ -# optional: after how many files to update progress -#show_progress_every: 100 - -# optional: plugins directory name -#plugins_dir: 'plugins' - -# optional: plugins discovery name pattern -plugin_name_pattern: '*.py' - -# optional: terminal escape sequences to display colors -#output_colors: -# DEFAULT: '\033[0m' -# HEADER: '\033[95m' -# INFO: '\033[94m' -# WARN: '\033[93m' -# ERROR: '\033[91m' - -# optional: log format string -#log_format: "[%(module)s]\t%(levelname)s\t%(message)s" - -# globs of files which should be analyzed -include: - - '*.py' - - '*.pyw' - -# a list of strings, which if found in the path will cause files to be excluded -# for example /tests/ - to remove all all files in tests directory -exclude_dirs: - - '/tests/' - -profiles: - keystone_conservative: - include: - - blacklist_functions - - blacklist_imports - - request_with_no_cert_validation - - exec_used - - set_bad_file_permissions - - subprocess_popen_with_shell_equals_true - - linux_commands_wildcard_injection - - ssl_with_bad_version - - - keystone_verbose: - include: - - blacklist_functions - - blacklist_imports - - request_with_no_cert_validation - - exec_used - - set_bad_file_permissions - - hardcoded_tmp_directory - - subprocess_popen_with_shell_equals_true - - any_other_function_with_shell_equals_true - - linux_commands_wildcard_injection - - ssl_with_bad_version - - ssl_with_bad_defaults - -blacklist_functions: - bad_name_sets: - - pickle: - qualnames: [pickle.loads, pickle.load, pickle.Unpickler, - cPickle.loads, cPickle.load, cPickle.Unpickler] - message: "Pickle library appears to be in use, possible security issue." - - marshal: - qualnames: [marshal.load, marshal.loads] - message: "Deserialization with the marshal module is possibly dangerous." - - md5: - qualnames: [hashlib.md5] - message: "Use of insecure MD5 hash function." - - mktemp_q: - qualnames: [tempfile.mktemp] - message: "Use of insecure and deprecated function (mktemp)." - - eval: - qualnames: [eval] - message: "Use of possibly insecure function - consider using safer ast.literal_eval." - - mark_safe: - names: [mark_safe] - message: "Use of mark_safe() may expose cross-site scripting vulnerabilities and should be reviewed." - - httpsconnection: - qualnames: [httplib.HTTPSConnection] - message: "Use of HTTPSConnection does not provide security, see https://wiki.openstack.org/wiki/OSSN/OSSN-0033" - - yaml_load: - qualnames: [yaml.load] - message: "Use of unsafe yaml load. Allows instantiation of arbitrary objects. Consider yaml.safe_load()." - - urllib_urlopen: - qualnames: [urllib.urlopen, urllib.urlretrieve, urllib.URLopener, urllib.FancyURLopener, urllib2.urlopen, urllib2.Request] - message: "Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected." - -shell_injection: - # Start a process using the subprocess module, or one of its wrappers. - subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, - subprocess.check_output, utils.execute, utils.execute_with_timeout] - # Start a process with a function vulnerable to shell injection. - shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4, - popen2.popen2, popen2.popen3, popen2.popen4, popen2.Popen3, - popen2.Popen4, commands.getoutput, commands.getstatusoutput] - # Start a process with a function that is not vulnerable to shell injection. - no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv,os.execve, - os.execvp, os.execvpe, os.spawnl, os.spawnle, os.spawnlp, - os.spawnlpe, os.spawnv, os.spawnve, os.spawnvp, os.spawnvpe, - os.startfile] - -blacklist_imports: - bad_import_sets: - - telnet: - imports: [telnetlib] - level: ERROR - message: "Telnet is considered insecure. Use SSH or some other encrypted protocol." - -hardcoded_password: - word_list: "wordlist/default-passwords" - -ssl_with_bad_version: - bad_protocol_versions: - - 'PROTOCOL_SSLv2' - - 'SSLv2_METHOD' - - 'SSLv23_METHOD' - - 'PROTOCOL_SSLv3' # strict option - - 'PROTOCOL_TLSv1' # strict option - - 'SSLv3_METHOD' # strict option - - 'TLSv1_METHOD' # strict option - -password_config_option_not_marked_secret: - function_names: - - oslo.config.cfg.StrOpt - - oslo_config.cfg.StrOpt - -execute_with_run_as_root_equals_true: - function_names: - - ceilometer.utils.execute - - cinder.utils.execute - - neutron.agent.linux.utils.execute - - nova.utils.execute - - nova.utils.trycmd diff --git a/keystonemiddleware-moon/debian/changelog b/keystonemiddleware-moon/debian/changelog deleted file mode 100644 index ffc44169..00000000 --- a/keystonemiddleware-moon/debian/changelog +++ /dev/null @@ -1,121 +0,0 @@ -python-keystonemiddleware (4.4.0-4) UNRELEASED; urgency=medium - - * Standards-Version is 3.9.8 now (no change) - * d/rules: Changed UPSTREAM_GIT protocol to https - * d/copyright: Changed source URL to https protocol - - -- Ondřej Nový <novy@ondrej.org> Sat, 09 Apr 2016 19:27:43 +0200 - -python-keystonemiddleware (4.4.0-3) unstable; urgency=medium - - * Re-add missing auth options in oslo-config-generator: - - Add re-add-missing-auth-options.patch - - Disable now failing unit tests. - - -- Thomas Goirand <zigo@debian.org> Wed, 06 Apr 2016 22:16:03 +0000 - -python-keystonemiddleware (4.4.0-2) unstable; urgency=medium - - * Added git as build-depends-indep. - - -- Thomas Goirand <zigo@debian.org> Mon, 04 Apr 2016 11:22:51 +0000 - -python-keystonemiddleware (4.4.0-1) unstable; urgency=medium - - [ Ondřej Nový ] - * Fixed homepage (https). - * Fixed VCS URLs (https). - - [ Thomas Goirand ] - * New upstream release. - * Uploading to unstable. - * Fixed (build-)depends for this release. - * Standards-Version: 3.9.7 (no change). - - -- Thomas Goirand <zigo@debian.org> Mon, 04 Apr 2016 12:21:37 +0200 - -python-keystonemiddleware (4.0.0-1) experimental; urgency=medium - - * New upstream release. - * Fixed (build-)depends for this release. - * Also test with Python 3. - * Fixed debian/copyright ordering. - - -- Thomas Goirand <zigo@debian.org> Thu, 10 Dec 2015 16:29:42 +0100 - -python-keystonemiddleware (3.0.0-1) experimental; urgency=medium - - * New upstream release. - * Fixed (build-)depends for this release. - - -- Thomas Goirand <zigo@debian.org> Fri, 04 Dec 2015 11:02:00 +0100 - -python-keystonemiddleware (2.3.0-3) unstable; urgency=medium - - * Uploading to unstable. - - -- Thomas Goirand <zigo@debian.org> Fri, 16 Oct 2015 10:04:17 +0000 - -python-keystonemiddleware (2.3.0-2) experimental; urgency=medium - - * Added Python 3 support. - - -- Thomas Goirand <zigo@debian.org> Sat, 03 Oct 2015 19:48:25 +0200 - -python-keystonemiddleware (2.3.0-1) experimental; urgency=medium - - * New upstream release. - * Align dependencies with upstream. - * d/control: Update uploaders. - - -- Corey Bryant <corey.bryant@canonical.com> Wed, 30 Sep 2015 14:42:41 -0400 - -python-keystonemiddleware (2.1.0-2) experimental; urgency=medium - - * Removed python-bandit build-depends. - - -- Thomas Goirand <zigo@debian.org> Thu, 30 Jul 2015 20:50:50 +0000 - -python-keystonemiddleware (2.1.0-1) experimental; urgency=medium - - * New upstream release. - * Fixed (build-)depends for this release. - * Fixed watch file. - - -- Thomas Goirand <zigo@debian.org> Thu, 30 Jul 2015 07:38:14 +0000 - -python-keystonemiddleware (1.5.0-2) unstable; urgency=high - - * CVE-2015-1852: S3Token TLS cert verification option not honored. Applied - upstream patch. - - -- Thomas Goirand <zigo@debian.org> Wed, 17 Jun 2015 08:28:00 +0000 - -python-keystonemiddleware (1.5.0-1) unstable; urgency=medium - - * New upstream release. - * Fixed (build-)depends for this release. - * Removed nature.css from debian/copyright (and it's BSD licence). - - -- Thomas Goirand <zigo@debian.org> Wed, 08 Apr 2015 10:08:46 +0200 - -python-keystonemiddleware (1.0.0-3) unstable; urgency=medium - - * Added CVE-2014-7144_convert_the_conf_value_into_correct_type.patch. Thanks - to Luciano Bello <luciano@debian.org> for the report (Closes: #762748). - - -- Thomas Goirand <zigo@debian.org> Thu, 25 Sep 2014 07:16:29 +0000 - -python-keystonemiddleware (1.0.0-2) unstable; urgency=medium - - * Do not attempt to run unit tests in Python 2.6, as it needs the discover - package, which we don't want as build-depends. - * Removes intersphinx plugin from docs build. - - -- Thomas Goirand <zigo@debian.org> Mon, 28 Jul 2014 00:29:44 +0800 - -python-keystonemiddleware (1.0.0-1) unstable; urgency=medium - - * Initial release. (Closes: #755135) - - -- Thomas Goirand <zigo@debian.org> Tue, 08 Jul 2014 14:25:47 +0800 diff --git a/keystonemiddleware-moon/debian/compat b/keystonemiddleware-moon/debian/compat deleted file mode 100644 index ec635144..00000000 --- a/keystonemiddleware-moon/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/keystonemiddleware-moon/debian/control b/keystonemiddleware-moon/debian/control deleted file mode 100644 index a6dd5eab..00000000 --- a/keystonemiddleware-moon/debian/control +++ /dev/null @@ -1,136 +0,0 @@ -Source: python-keystonemiddleware -Section: python -Priority: optional -Maintainer: PKG OpenStack <openstack-devel@lists.alioth.debian.org> -Uploaders: Thomas Goirand <zigo@debian.org>, - Corey Bryant <corey.bryant@canonical.com>, -Build-Depends: debhelper (>= 9), - dh-python, - openstack-pkg-tools, - python-all, - python-pbr (>= 1.8), - python-setuptools, - python-sphinx, - python3-all, - python3-pbr (>= 1.8), - python3-setuptools, -Build-Depends-Indep: git, - python-bandit, - python-coverage, - python-crypto, - python-fixtures (>= 1.3.1), - python-hacking, - python-keystoneauth1 (>= 2.1.0), - python-keystoneclient (>= 1:1.6.0), - python-memcache (>= 1.56), - python-mock (>= 1.2), - python-oslo.config (>= 1:3.7.0), - python-oslo.context (>= 0.2.0), - python-oslo.i18n (>= 2.1.0), - python-oslo.messaging (>= 4.0.0), - python-oslo.serialization (>= 1.10.0), - python-oslo.utils (>= 3.5.0), - python-oslosphinx (>= 2.5.0), - python-oslotest (>= 1.10.0), - python-positional (>= 1.0.1), - python-pycadf (>= 1.1.0), - python-requests (>= 2.8.1), - python-requests-mock (>= 0.7.0), - python-six (>= 1.9.0), - python-stevedore (>= 1.5.0), - python-testresources, - python-testtools (>= 1.4.0), - python-webob, - python3-bandit, - python3-crypto, - python3-fixtures (>= 1.3.1), - python3-keystoneauth1 (>= 2.1.0), - python3-keystoneclient (>= 1:1.6.0), - python3-memcache (>= 1.56), - python3-mock (>= 1.2), - python3-oslo.config (>= 1:3.7.0), - python3-oslo.context (>= 0.2.0), - python3-oslo.i18n (>= 2.1.0), - python3-oslo.messaging (>= 4.0.0), - python3-oslo.serialization (>= 1.10.0), - python3-oslo.utils (>= 3.5.0), - python3-oslotest (>= 1.10.0), - python3-positional (>= 1.0.1), - python3-pycadf (>= 1.1.0), - python3-requests (>= 2.8.1), - python3-requests-mock (>= 0.7.0), - python3-six (>= 1.9.0), - python3-stevedore (>= 1.5.0), - python3-subunit, - python3-testresources, - python3-testtools (>= 1.4.0), - python3-webob, - subunit, - testrepository, -Standards-Version: 3.9.8 -Vcs-Browser: https://anonscm.debian.org/cgit/openstack/python-keystonemiddleware.git/ -Vcs-Git: https://anonscm.debian.org/git/openstack/python-keystonemiddleware.git -Homepage: https://launchpad.net/keystonemiddleware - -Package: python-keystonemiddleware -Architecture: all -Depends: python-keystoneauth1 (>= 2.1.0), - python-keystoneclient (>= 1:1.6.0), - python-oslo.config (>= 1:3.7.0), - python-oslo.context (>= 0.2.0), - python-oslo.i18n (>= 2.1.0), - python-oslo.serialization (>= 1.10.0), - python-oslo.utils (>= 3.5.0), - python-pbr (>= 1.8), - python-positional (>= 1.0.1), - python-pycadf (>= 1.1.0), - python-requests (>= 2.8.1), - python-six (>= 1.9.0), - python-webob, - ${misc:Depends}, - ${python:Depends}, -Description: Middleware for OpenStack Identity (Keystone) - Python 2.x - This package contains middleware modules designed to provide authentication - and authorization features to web services other than Keystone. The most - prominent module is keystonemiddleware.auth_token. This package does not - expose any CLI or Python API features. - . - This package contains the Python 2.x module. - -Package: python3-keystonemiddleware -Architecture: all -Depends: python3-keystoneauth1 (>= 2.1.0), - python3-keystoneclient (>= 1:1.6.0), - python3-oslo.config (>= 1:3.7.0), - python3-oslo.context (>= 0.2.0), - python3-oslo.i18n (>= 2.1.0), - python3-oslo.serialization (>= 1.10.0), - python3-oslo.utils (>= 3.5.0), - python3-pbr (>= 1.8), - python3-positional (>= 1.0.1), - python3-pycadf (>= 1.1.0), - python3-requests (>= 2.8.1), - python3-six (>= 1.9.0), - python3-webob, - ${misc:Depends}, - ${python3:Depends}, -Description: Middleware for OpenStack Identity (Keystone) - Python 3.x - This package contains middleware modules designed to provide authentication - and authorization features to web services other than Keystone. The most - prominent module is keystonemiddleware.auth_token. This package does not - expose any CLI or Python API features. - . - This package contains the Python 3.x module. - -Package: python-keystonemiddleware-doc -Section: doc -Architecture: all -Depends: ${misc:Depends}, - ${sphinxdoc:Depends}, -Description: Middleware for OpenStack Identity (Keystone) - doc - This package contains middleware modules designed to provide authentication - and authorization features to web services other than Keystone. The most - prominent module is keystonemiddleware.auth_token. This package does not - expose any CLI or Python API features. - . - This package contains the documentation. diff --git a/keystonemiddleware-moon/debian/copyright b/keystonemiddleware-moon/debian/copyright deleted file mode 100644 index cae54f2a..00000000 --- a/keystonemiddleware-moon/debian/copyright +++ /dev/null @@ -1,27 +0,0 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: keystonemiddleware -Source: https://launchpad.net/keystonemiddleware - -Files: * -Copyright: (c) 2013-2016, OpenStack Foundation <openstack-dev@lists.openstack.org> -License: Apache-2 - -Files: debian/* -Copyright: (c) 2014-2016, Thomas Goirand <zigo@debian.org> -License: Apache-2 - -License: Apache-2 - 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. - . - On Debian-based systems the full text of the Apache version 2.0 license - can be found in /usr/share/common-licenses/Apache-2.0. diff --git a/keystonemiddleware-moon/debian/create_deb.py b/keystonemiddleware-moon/debian/create_deb.py deleted file mode 100644 index 03d6b790..00000000 --- a/keystonemiddleware-moon/debian/create_deb.py +++ /dev/null @@ -1,196 +0,0 @@ -#!/usr/bin/env python3.5 - -import os -import sys -import subprocess -import glob -import argparse - - -parser = argparse.ArgumentParser() -parser.add_argument('--src', help='Do not clone Moon repository, use SRC as source directory', dest="src") -args = parser.parse_args() - - -TMP_DIR = "/tmp/debian-moon" -MOON_DIR = os.path.join(TMP_DIR, "moon") -INIT_dir = os.path.split(os.path.abspath(sys.argv[0]))[0] - -print("init dir: {}".format(INIT_dir)) - -_run = subprocess.run(["mkdir", "-p", TMP_DIR]) -if _run.returncode != 0: - exit("\033[31mCannot create tmp dir\033[m") - -os.chdir(TMP_DIR) - -_run = subprocess.run(["sudo", "apt-get", "install", "-y", "git"]) -if _run.returncode != 0: - exit("\033[31mCannot install Git\033[m") - -# print("\033[32mCloning Debian version\033[m") -# _run = subprocess.run(["git", "clone", "https://anonscm.debian.org/git/openstack/python-keystonemiddleware.git"]) -# if _run.returncode != 0: -# os.chdir(os.path.join(TMP_DIR, "python-keystonemiddleware")) -# _run = subprocess.run(["git", "pull"]) -# if _run.returncode != 0: -# print("\033[31mCannot clone ou pull debian version\033[m") - -os.chdir(TMP_DIR) - -if args.src: - print("\033[32mUsing {} as source directory\033[m".format(args.src)) - MOON_DIR = args.src -else: - print("\033[32mCloning Moon project\033[m") - _run = subprocess.run(["git", "clone", "https://git.opnfv.org/moon"]) - if _run.returncode != 0: - os.chdir(os.path.join(TMP_DIR, "moon")) - _run = subprocess.run(["git", "pull"]) - if _run.returncode != 0: - print("\033[31mCannot clone Moon project\033[m") - -os.chdir(TMP_DIR) - -# src_path = os.path.join(TMP_DIR, "python-keystonemiddleware", "debian") -# dst_path = os.path.join(TMP_DIR, "moon", "keystonemiddleware-moon") -# print("\033[32mCopying from {} to {}\033[m".format(src_path, dst_path)) -# _run = subprocess.run(["cp", -# "-rv", -# src_path, -# dst_path]) - -print("\033[32mBuilding Moon project\033[m") -os.chdir(os.path.join(MOON_DIR, "keystonemiddleware-moon")) - -mandatory_deb_pkg = """dh-apparmor -dh-systemd -openstack-pkg-tools -python-all python-pbr -python-sphinx -python-bashate -python-keystonemiddleware -python-ldap -python-ldappool -python-memcache -python-migrate -python-mock -python-msgpack -python-oslo.cache -python-oslo.concurrency -python-oslo.config -python-oslo.context -python-oslo.db -python-oslo.i18n -python-oslo.log -python-oslo.messaging -python-oslo.policy -python-oslo.serialization -python-oslo.service -python-oslo.utils -python-oslosphinx -python-oslotest -python-os-testr -python-passlib -python-paste -python-pastedeploy -python-pycadf -python-pymongo -python-pysaml2 -python-pysqlite2 -python-routes -python-sqlalchemy -python-stevedore -python-testscenarios -python-testtools -python-unittest2 -python-webob -python-webtest -subunit -testrepository -python-coverage -python-dogpile.cache -python-eventlet -python-hacking -python-oslo.cache -python-oslo.concurrency -python-oslo.config -python-oslo.db -python-oslo.log -python-oslo.messaging -python-oslo.middleware -python-tempest-lib -python-oauthlib -python-pam -python3-all -python3-setuptools -python-bandit -python-requests-mock -python-testresources -python3-bandit -python3-crypto -python3-keystoneauth1 -python3-keystoneclient -python3-memcache -python3-mock -python3-oslo.config -python3-oslo.context -python3-oslo.i18n -python3-oslo.messaging -python3-oslo.serialization -python3-oslo.utils -python3-oslotest -python3-positional -python3-pycadf -python3-requests-mock -python3-stevedore -python3-testresources -python3-webob -""" - -_command = ["sudo", "apt-get", "install", "-y"] -_command.extend(mandatory_deb_pkg.split()) -_run = subprocess.run(_command) - -print("\033[32mremove a Debian patch as it inserts a bug in Moon\033[m") -series_filename = os.path.join(MOON_DIR, "keystonemiddleware-moon", - "debian", "patches", "series") -series_lines = open(series_filename).readlines() - -output = open(series_filename, "w") -for line in series_lines: - if "re-add-missing-auth-options.patch" not in line: - output.write(line) - output.write("\n") -output.close() -os.remove(os.path.join(MOON_DIR, "keystonemiddleware-moon", - "debian", "patches", "re-add-missing-auth-options.patch")) - -os.putenv("DEB_BUILD_OPTIONS", "nocheck") - -changelog = open(os.path.join(MOON_DIR, "keystonemiddleware-moon", "debian", "changelog"), "rt") -changelog_str = changelog.read() -# print(changelog_str.splitlines()[0]) -current_version = changelog_str.splitlines()[0].split("(")[1].split(")")[0] -changelog.close() -changelog = open(os.path.join(MOON_DIR, "keystonemiddleware-moon", "debian", "changelog"), "wt") -changelog.write("""python-keystonemiddleware ({version}) UNRELEASED; urgency=medium - - * integration of the Moon platform. - - -- Thomas Duval <thomas.duval@orange.com> {date} - -""".format( - version=current_version+"-moon", - date=subprocess.Popen(["date"], stdin=None, stdout=subprocess.PIPE).communicate()[0].decode("utf-8").strip())) -changelog.write(changelog_str) -changelog.close() - -_run = subprocess.run(["dpkg-buildpackage", "-b", "-us"]) - -print("\033[32mResults:\033[m") -subprocess.run(["mkdir", "-p", "/tmp/deb"]) - -files = glob.glob(os.path.join(MOON_DIR, "*.deb")) -for _file in files: - subprocess.run(["mv", "-v", _file, "/tmp/deb/"]) diff --git a/keystonemiddleware-moon/debian/gbp.conf b/keystonemiddleware-moon/debian/gbp.conf deleted file mode 100644 index 7436424b..00000000 --- a/keystonemiddleware-moon/debian/gbp.conf +++ /dev/null @@ -1,9 +0,0 @@ -[DEFAULT] -upstream-branch = master -debian-branch = debian/mitaka -upstream-tag = %(version)s -compression = xz - -[buildpackage] -export-dir = ../build-area/ - diff --git a/keystonemiddleware-moon/debian/patches/no-intersphinx.patch b/keystonemiddleware-moon/debian/patches/no-intersphinx.patch deleted file mode 100644 index a5e25751..00000000 --- a/keystonemiddleware-moon/debian/patches/no-intersphinx.patch +++ /dev/null @@ -1,17 +0,0 @@ -Description: Remove the intersphinx plugin. - Do not use the intersphinx plugin which is doing network access during - the build. -Author: Thomas Goirand <zigo@debian.org> -Forwarded: no -Last-Update: 2014-07-28 - ---- python-keystonemiddleware-1.0.0.orig/doc/source/conf.py -+++ python-keystonemiddleware-1.0.0/doc/source/conf.py -@@ -42,7 +42,6 @@ sys.path.insert(0, os.path.abspath(os.pa - extensions = ['sphinx.ext.autodoc', - 'sphinx.ext.todo', - 'sphinx.ext.coverage', -- 'sphinx.ext.intersphinx', - # NOTE(blk-u): Uncomment the [pbr] section in setup.cfg and - # remove this Sphinx extension when - # https://launchpad.net/bugs/1260495 is fixed. diff --git a/keystonemiddleware-moon/debian/patches/re-add-missing-auth-options.patch b/keystonemiddleware-moon/debian/patches/re-add-missing-auth-options.patch deleted file mode 100644 index fc981d0c..00000000 --- a/keystonemiddleware-moon/debian/patches/re-add-missing-auth-options.patch +++ /dev/null @@ -1,18 +0,0 @@ -Description: Re-add missing auth options - Upstream went a bit quick to remove Auth options from the default generated - config files. -Author: Thomas Goirand <zigo@debian.org> -Forwarded: no -Last-Update: 2016-04-07 - ---- python-keystonemiddleware-4.4.0.orig/keystonemiddleware/auth_token/__init__.py -+++ python-keystonemiddleware-4.4.0/keystonemiddleware/auth_token/__init__.py -@@ -370,7 +370,7 @@ _OPTS = [ - ' only while migrating from a less secure algorithm to a more' - ' secure one. Once all the old tokens are expired this option' - ' should be set to a single value for better performance.'), --] -+] + _auth.OPTS - - CONF = cfg.CONF - CONF.register_opts(_OPTS, group=_base.AUTHTOKEN_GROUP) diff --git a/keystonemiddleware-moon/debian/patches/series b/keystonemiddleware-moon/debian/patches/series deleted file mode 100644 index 3c47073f..00000000 --- a/keystonemiddleware-moon/debian/patches/series +++ /dev/null @@ -1,2 +0,0 @@ -no-intersphinx.patch -re-add-missing-auth-options.patch diff --git a/keystonemiddleware-moon/debian/python-keystonemiddleware-doc.doc-base b/keystonemiddleware-moon/debian/python-keystonemiddleware-doc.doc-base deleted file mode 100644 index bd08be62..00000000 --- a/keystonemiddleware-moon/debian/python-keystonemiddleware-doc.doc-base +++ /dev/null @@ -1,9 +0,0 @@ -Document: keystonemiddleware-doc -Title: keystonemiddleware Documentation -Author: N/A -Abstract: Sphinx documentation for keystonemiddleware -Section: Programming/Python - -Format: HTML -Index: /usr/share/doc/python-keystonemiddleware-doc/html/index.html -Files: /usr/share/doc/python-keystonemiddleware-doc/html/* diff --git a/keystonemiddleware-moon/debian/rules b/keystonemiddleware-moon/debian/rules deleted file mode 100755 index 2229093a..00000000 --- a/keystonemiddleware-moon/debian/rules +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/make -f - -PYTHONS:=$(shell pyversions -vr) -PYTHON3S:=$(shell py3versions -vr) - -UPSTREAM_GIT := https://github.com/openstack/keystonemiddleware.git -include /usr/share/openstack-pkg-tools/pkgos.make - -export OSLO_PACKAGE_VERSION=$(shell dpkg-parsechangelog | grep Version: | cut -d' ' -f2 | sed -e 's/^[[:digit:]]*://' -e 's/[-].*//' -e 's/~/.0/' | head -n 1) - -%: - dh $@ --buildsystem=python_distutils --with python2,python3,sphinxdoc - -override_dh_auto_install: - set -e ; for pyvers in $(PYTHONS); do \ - python$$pyvers setup.py install --install-layout=deb \ - --root $(CURDIR)/debian/python-keystonemiddleware; \ - done - set -e ; for pyvers in $(PYTHON3S); do \ - python$$pyvers setup.py install --install-layout=deb \ - --root $(CURDIR)/debian/python3-keystonemiddleware; \ - done - -override_dh_auto_test: -ifeq (,$(findstring nocheck, $(DEB_BUILD_OPTIONS))) - echo "===> Running tests" - set -e ; for i in 2.7 $(PYTHON3S) ; do \ - PYMAJOR=`echo $$i | cut -d'.' -f1` ; \ - echo "===> Testing with python$$i (python$$PYMAJOR)" ; \ - rm -rf .testrepository ; \ - testr-python$$PYMAJOR init ; \ - TEMP_REZ=`mktemp -t` ; \ - PYTHONPATH=$(CURDIR) PYTHON=python$$i testr-python$$PYMAJOR run --subunit 'keystonemiddleware.tests\.unit\.(?!(.*OptsTestCase.test_entry_point.*|.*test_opts.OptsTestCase.test_list_auth_token_opts.*|.*test_opts.OptsTestCase.test_original_list_all_options.*))' | tee $$TEMP_REZ | subunit2pyunit ; \ - cat $$TEMP_REZ | subunit-filter -s --no-passthrough | subunit-stats ; \ - rm -f $$TEMP_REZ ; \ - testr-python$$PYMAJOR slowest ; \ - done -endif - -override_dh_clean: - dh_clean -O--buildsystem=python_distutils - rm -rf build - -override_dh_sphinxdoc: - sphinx-build -b html doc/source debian/python-keystonemiddleware-doc/usr/share/doc/python-keystonemiddleware-doc/html - dh_sphinxdoc -O--buildsystem=python_distutils - -# Commands not to run -override_dh_installcatalogs: -override_dh_installemacsen override_dh_installifupdown: -override_dh_installinfo override_dh_installmenu override_dh_installmime: -override_dh_installmodules override_dh_installlogcheck: -override_dh_installpam override_dh_installppp override_dh_installudev override_dh_installwm: -override_dh_installxfonts override_dh_gconf override_dh_icons override_dh_perl override_dh_usrlocal: diff --git a/keystonemiddleware-moon/debian/source/format b/keystonemiddleware-moon/debian/source/format deleted file mode 100644 index 163aaf8d..00000000 --- a/keystonemiddleware-moon/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) diff --git a/keystonemiddleware-moon/debian/source/options b/keystonemiddleware-moon/debian/source/options deleted file mode 100644 index cb61fa52..00000000 --- a/keystonemiddleware-moon/debian/source/options +++ /dev/null @@ -1 +0,0 @@ -extend-diff-ignore = "^[^/]*[.]egg-info/" diff --git a/keystonemiddleware-moon/debian/watch b/keystonemiddleware-moon/debian/watch deleted file mode 100644 index d7d3dbeb..00000000 --- a/keystonemiddleware-moon/debian/watch +++ /dev/null @@ -1,3 +0,0 @@ -version=3 -opts="uversionmangle=s/\.(b|rc)/~$1/" \ -https://github.com/openstack/keystonemiddleware/tags .*/(\d[\d\.]+)\.tar\.gz diff --git a/keystonemiddleware-moon/doc/.gitignore b/keystonemiddleware-moon/doc/.gitignore deleted file mode 100644 index edde2181..00000000 --- a/keystonemiddleware-moon/doc/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -build/ -source/api/ diff --git a/keystonemiddleware-moon/doc/Makefile b/keystonemiddleware-moon/doc/Makefile deleted file mode 100644 index 84f00bd5..00000000 --- a/keystonemiddleware-moon/doc/Makefile +++ /dev/null @@ -1,90 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -SPHINXSOURCE = source -PAPER = -BUILDDIR = build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SPHINXSOURCE) - -.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest - -help: - @echo "Please use \`make <target>' where <target> is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/keystonemiddleware.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/keystonemiddleware.qhc" - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ - "run these through (pdf)latex." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/keystonemiddleware-moon/doc/ext/__init__.py b/keystonemiddleware-moon/doc/ext/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/keystonemiddleware-moon/doc/ext/__init__.py +++ /dev/null diff --git a/keystonemiddleware-moon/doc/ext/apidoc.py b/keystonemiddleware-moon/doc/ext/apidoc.py deleted file mode 100644 index 2575f422..00000000 --- a/keystonemiddleware-moon/doc/ext/apidoc.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2014 OpenStack Foundation -# -# 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. - -# NOTE(blk-u): Uncomment the [pbr] section in setup.cfg and remove this -# Sphinx extension when https://launchpad.net/bugs/1260495 is fixed. - -import os.path as path - -from sphinx import apidoc - - -# NOTE(blk-u): pbr will run Sphinx multiple times when it generates -# documentation. Once for each builder. To run this extension we use the -# 'builder-inited' hook that fires at the beginning of a Sphinx build. -# We use ``run_already`` to make sure apidocs are only generated once -# even if Sphinx is run multiple times. -run_already = False - - -def run_apidoc(app): - global run_already - if run_already: - return - run_already = True - - package_dir = path.abspath(path.join(app.srcdir, '..', '..', - 'keystonemiddleware')) - source_dir = path.join(app.srcdir, 'api') - apidoc.main(['apidoc', package_dir, '-f', - '-H', 'keystonemiddleware Modules', - '-o', source_dir]) - - -def setup(app): - app.connect('builder-inited', run_apidoc) diff --git a/keystonemiddleware-moon/doc/source/audit.rst b/keystonemiddleware-moon/doc/source/audit.rst deleted file mode 100644 index d23f8168..00000000 --- a/keystonemiddleware-moon/doc/source/audit.rst +++ /dev/null @@ -1,81 +0,0 @@ -.. - Copyright 2014 IBM Corp - - 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. - -.. _middleware: - -================= - Audit middleware -================= - -The Keystone middleware library provides an optional WSGI middleware filter -which allows the ability to audit API requests for each component of OpenStack. - -The audit middleware filter utilises environment variables to build the CADF -event. - -.. figure:: ./images/audit.png - :width: 100% - :align: center - :alt: Figure 1: Audit middleware in Nova pipeline - -The figure above shows the middleware in Nova's pipeline. - -Enabling audit middleware -========================= -To enable auditing, oslo.messaging_ should be installed. If not, the middleware -will log the audit event instead. Auditing can be enabled for a specific -project by editing the project's api-paste.ini file to include the following -filter definition: - -:: - - [filter:audit] - paste.filter_factory = keystonemiddleware.audit:filter_factory - audit_map_file = /etc/nova/api_audit_map.conf - -The filter should be included after Keystone middleware's auth_token middleware -so it can utilise environment variables set by auth_token. Below is an example -using Nova's WSGI pipeline:: - - [composite:openstack_compute_api_v2] - use = call:nova.api.auth:pipeline_factory - noauth = faultwrap sizelimit noauth ratelimit osapi_compute_app_v2 - keystone = faultwrap sizelimit authtoken keystonecontext ratelimit audit osapi_compute_app_v2 - keystone_nolimit = faultwrap sizelimit authtoken keystonecontext audit osapi_compute_app_v2 - -.. _oslo.messaging: http://www.github.com/openstack/oslo.messaging - -Configure audit middleware -========================== -To properly audit api requests, the audit middleware requires an -api_audit_map.conf to be defined. The project's corresponding -api_audit_map.conf file is included in the `pyCADF library`_. - -The location of the mapping file should be specified explicitly by adding the -path to the 'audit_map_file' option of the filter definition:: - - [filter:audit] - paste.filter_factory = keystonemiddleware.audit:filter_factory - audit_map_file = /etc/nova/api_audit_map.conf - -Additional options can be set:: - - [filter:audit] - paste.filter_factory = pycadf.middleware.audit:filter_factory - audit_map_file = /etc/nova/api_audit_map.conf - service_name = test # opt to set HTTP_X_SERVICE_NAME environ variable - ignore_req_list = GET,POST # opt to ignore specific requests - -.. _pyCADF library: https://github.com/openstack/pycadf/tree/master/etc/pycadf diff --git a/keystonemiddleware-moon/doc/source/conf.py b/keystonemiddleware-moon/doc/source/conf.py deleted file mode 100644 index ff4b24cc..00000000 --- a/keystonemiddleware-moon/doc/source/conf.py +++ /dev/null @@ -1,237 +0,0 @@ -# -*- coding: utf-8 -*- -# -# keystonemiddleware documentation build configuration file, created by -# sphinx-quickstart on Sun Dec 6 14:19:25 2009. -# -# This file is execfile()d with the current directory set to its containing -# dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -from __future__ import unicode_literals - -import os -import sys - -import pbr.version - - -sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..'))) - -# NOTE(blk-u): Path for our Sphinx extension, remove when -# https://launchpad.net/bugs/1260495 is fixed. -sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), - '..'))) - - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.append(os.path.abspath('.')) - -# -- General configuration ---------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', - 'sphinx.ext.todo', - 'sphinx.ext.coverage', - 'sphinx.ext.intersphinx', - # NOTE(blk-u): Uncomment the [pbr] section in setup.cfg and - # remove this Sphinx extension when - # https://launchpad.net/bugs/1260495 is fixed. - 'ext.apidoc', - 'oslosphinx' - ] - -todo_include_todos = True - -# Add any paths that contain templates here, relative to this directory. -#templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = 'keystonemiddleware' -copyright = 'OpenStack Contributors' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -version_info = pbr.version.VersionInfo('keystonemiddleware') -# The short X.Y version. -version = version_info.version_string() -# The full version, including alpha/beta/rc tags. -release = version_info.release_string() - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = [] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -modindex_common_prefix = ['keystonemiddleware.'] - -# Grouping the document tree for man pages. -# List of tuples 'sourcefile', 'target', 'title', 'Authors name', 'manual' - -man_pages = [] - -# -- Options for HTML output -------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -#html_theme_path = ["."] -#html_theme = '_theme' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -#html_static_path = ['static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -git_cmd = "git log --pretty=format:'%ad, commit %h' --date=local -n1" -html_last_updated_fmt = os.popen(git_cmd).read() - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_use_modindex = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'keystonemiddlewaredoc' - - -# -- Options for LaTeX output ------------------------------------------------- - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]) -# . -latex_documents = [ - ('index', 'keystonmiddleware.tex', - 'keystonemiddleware Documentation', - 'Nebula Inc, based on work by Rackspace and Jacob Kaplan-Moss', - 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_use_modindex = True - -keystoneclient = 'http://docs.openstack.org/developer/python-keystoneclient/' - -intersphinx_mapping = {'keystoneclient': (keystoneclient, None), - } diff --git a/keystonemiddleware-moon/doc/source/images/audit.png b/keystonemiddleware-moon/doc/source/images/audit.png Binary files differdeleted file mode 100644 index 5c2b1305..00000000 --- a/keystonemiddleware-moon/doc/source/images/audit.png +++ /dev/null diff --git a/keystonemiddleware-moon/doc/source/images/graphs_authComp.svg b/keystonemiddleware-moon/doc/source/images/graphs_authComp.svg deleted file mode 100644 index 6be629c1..00000000 --- a/keystonemiddleware-moon/doc/source/images/graphs_authComp.svg +++ /dev/null @@ -1,48 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" - "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<!-- Generated by graphviz version 2.27.20101213.0545 (20101213.0545) - --> -<!-- Title: AuthComp Pages: 1 --> -<svg width="510pt" height="118pt" - viewBox="0.00 0.00 510.00 118.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> -<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 114)"> -<title>AuthComp</title> -<polygon fill="white" stroke="white" points="-4,5 -4,-114 507,-114 507,5 -4,5"/> -<!-- AuthComp --> -<g id="node2" class="node"><title>AuthComp</title> -<polygon fill="#fdefe3" stroke="#c00000" points="292,-65 194,-65 194,-25 292,-25 292,-65"/> -<text text-anchor="middle" x="243" y="-48.4" font-family="Helvetica,sans-Serif" font-size="14.00">Auth</text> -<text text-anchor="middle" x="243" y="-32.4" font-family="Helvetica,sans-Serif" font-size="14.00">Component</text> -</g> -<!-- Reject --> -<!-- AuthComp->Reject --> -<g id="edge3" class="edge"><title>AuthComp->Reject</title> -<path fill="none" stroke="black" d="M193.933,-51.2787C157.514,-55.939 108.38,-62.2263 73.8172,-66.649"/> -<polygon fill="black" stroke="black" points="73.0637,-63.2168 63.5888,-67.9578 73.9522,-70.1602 73.0637,-63.2168"/> -<text text-anchor="middle" x="129" y="-97.4" font-family="Times,serif" font-size="14.00">Reject</text> -<text text-anchor="middle" x="129" y="-82.4" font-family="Times,serif" font-size="14.00">Unauthenticated</text> -<text text-anchor="middle" x="129" y="-67.4" font-family="Times,serif" font-size="14.00">Requests</text> -</g> -<!-- Service --> -<g id="node6" class="node"><title>Service</title> -<polygon fill="#d1ebf1" stroke="#1f477d" points="502,-65 408,-65 408,-25 502,-25 502,-65"/> -<text text-anchor="middle" x="455" y="-48.4" font-family="Helvetica,sans-Serif" font-size="14.00">OpenStack</text> -<text text-anchor="middle" x="455" y="-32.4" font-family="Helvetica,sans-Serif" font-size="14.00">Service</text> -</g> -<!-- AuthComp->Service --> -<g id="edge5" class="edge"><title>AuthComp->Service</title> -<path fill="none" stroke="black" d="M292.17,-45C323.626,-45 364.563,-45 397.52,-45"/> -<polygon fill="black" stroke="black" points="397.917,-48.5001 407.917,-45 397.917,-41.5001 397.917,-48.5001"/> -<text text-anchor="middle" x="350" y="-77.4" font-family="Times,serif" font-size="14.00">Forward</text> -<text text-anchor="middle" x="350" y="-62.4" font-family="Times,serif" font-size="14.00">Authenticated</text> -<text text-anchor="middle" x="350" y="-47.4" font-family="Times,serif" font-size="14.00">Requests</text> -</g> -<!-- Start --> -<!-- Start->AuthComp --> -<g id="edge7" class="edge"><title>Start->AuthComp</title> -<path fill="none" stroke="black" d="M59.1526,-21.4745C90.4482,-25.4792 142.816,-32.1802 183.673,-37.4084"/> -<polygon fill="black" stroke="black" points="183.43,-40.9057 193.793,-38.7034 184.318,-33.9623 183.43,-40.9057"/> -</g> -</g> -</svg> diff --git a/keystonemiddleware-moon/doc/source/images/graphs_authCompDelegate.svg b/keystonemiddleware-moon/doc/source/images/graphs_authCompDelegate.svg deleted file mode 100644 index 4788829a..00000000 --- a/keystonemiddleware-moon/doc/source/images/graphs_authCompDelegate.svg +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" - "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<!-- Generated by graphviz version 2.27.20101213.0545 (20101213.0545) - --> -<!-- Title: AuthCompDelegate Pages: 1 --> -<svg width="588pt" height="104pt" - viewBox="0.00 0.00 588.00 104.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> -<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 100)"> -<title>AuthCompDelegate</title> -<polygon fill="white" stroke="white" points="-4,5 -4,-100 585,-100 585,5 -4,5"/> -<!-- AuthComp --> -<g id="node2" class="node"><title>AuthComp</title> -<polygon fill="#fdefe3" stroke="#c00000" points="338,-65 240,-65 240,-25 338,-25 338,-65"/> -<text text-anchor="middle" x="289" y="-48.4" font-family="Helvetica,sans-Serif" font-size="14.00">Auth</text> -<text text-anchor="middle" x="289" y="-32.4" font-family="Helvetica,sans-Serif" font-size="14.00">Component</text> -</g> -<!-- Reject --> -<!-- AuthComp->Reject --> -<g id="edge3" class="edge"><title>AuthComp->Reject</title> -<path fill="none" stroke="black" d="M239.6,-50.1899C191.406,-55.2531 118.917,-62.8686 73.5875,-67.6309"/> -<polygon fill="black" stroke="black" points="73.0928,-64.1635 63.5132,-68.6893 73.8242,-71.1252 73.0928,-64.1635"/> -<text text-anchor="middle" x="152" y="-83.4" font-family="Times,serif" font-size="14.00">Reject Requests</text> -<text text-anchor="middle" x="152" y="-68.4" font-family="Times,serif" font-size="14.00">Indicated by the Service</text> -</g> -<!-- Service --> -<g id="node6" class="node"><title>Service</title> -<polygon fill="#d1ebf1" stroke="#1f477d" points="580,-65 486,-65 486,-25 580,-25 580,-65"/> -<text text-anchor="middle" x="533" y="-48.4" font-family="Helvetica,sans-Serif" font-size="14.00">OpenStack</text> -<text text-anchor="middle" x="533" y="-32.4" font-family="Helvetica,sans-Serif" font-size="14.00">Service</text> -</g> -<!-- AuthComp->Service --> -<g id="edge5" class="edge"><title>AuthComp->Service</title> -<path fill="none" stroke="black" d="M338.009,-49.0804C344.065,-49.4598 350.172,-49.7828 356,-50 405.743,-51.8535 418.259,-51.9103 468,-50 470.523,-49.9031 473.101,-49.7851 475.704,-49.6504"/> -<polygon fill="black" stroke="black" points="476.03,-53.1374 485.807,-49.0576 475.62,-46.1494 476.03,-53.1374"/> -<text text-anchor="middle" x="412" y="-68.4" font-family="Times,serif" font-size="14.00">Forward Requests</text> -<text text-anchor="middle" x="412" y="-53.4" font-family="Times,serif" font-size="14.00">with Identiy Status</text> -</g> -<!-- Service->AuthComp --> -<g id="edge7" class="edge"><title>Service->AuthComp</title> -<path fill="none" stroke="black" d="M495.062,-24.9037C486.397,-21.2187 477.064,-17.9304 468,-16 419.314,-5.63183 404.743,-5.9037 356,-16 349.891,-17.2653 343.655,-19.116 337.566,-21.2803"/> -<polygon fill="black" stroke="black" points="336.234,-18.0426 328.158,-24.9003 338.748,-24.5757 336.234,-18.0426"/> -<text text-anchor="middle" x="412" y="-33.4" font-family="Times,serif" font-size="14.00">Send Response OR</text> -<text text-anchor="middle" x="412" y="-18.4" font-family="Times,serif" font-size="14.00">Reject Message</text> -</g> -<!-- Start --> -<!-- Start->AuthComp --> -<g id="edge9" class="edge"><title>Start->AuthComp</title> -<path fill="none" stroke="black" d="M59.0178,-20.8384C99.2135,-25.0613 175.782,-33.1055 229.492,-38.7482"/> -<polygon fill="black" stroke="black" points="229.265,-42.2435 239.576,-39.8076 229.997,-35.2818 229.265,-42.2435"/> -</g> -</g> -</svg> diff --git a/keystonemiddleware-moon/doc/source/index.rst b/keystonemiddleware-moon/doc/source/index.rst deleted file mode 100644 index 9092ec79..00000000 --- a/keystonemiddleware-moon/doc/source/index.rst +++ /dev/null @@ -1,46 +0,0 @@ -Python Middleware for OpenStack Identity API (Keystone) -======================================================= - -This is the middleware provided for integrating with the OpenStack -Identity API and handling authorization enforcement based upon the -data within the OpenStack Identity tokens. Also included is middleware that -provides the ability to create audit events based on API requests. - -Contents: - -.. toctree:: - :maxdepth: 1 - - middlewarearchitecture - audit - -Related Identity Projects -========================= - -In addition to creating the Python Middleware for OpenStack Identity -API, the Keystone team also provides `Identity Service`_, as well as -`Python Client Library`_. - -.. _`Identity Service`: http://docs.openstack.org/developer/keystone/ -.. _`Python Client Library`: http://docs.openstack.org/developer/python-keystoneclient/ - -Contributing -============ - -Code is hosted `on GitHub`_. Submit bugs to the Keystone project on -`Launchpad`_. Submit code to the ``openstack/keystonemiddleware`` project -using `Gerrit`_. - -.. _on GitHub: https://github.com/openstack/keystonemiddleware -.. _Launchpad: https://launchpad.net/keystonemiddleware -.. _Gerrit: http://docs.openstack.org/infra/manual/developers.html#development-workflow - -Run tests with ``python setup.py test``. - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - diff --git a/keystonemiddleware-moon/doc/source/middlewarearchitecture.rst b/keystonemiddleware-moon/doc/source/middlewarearchitecture.rst deleted file mode 100644 index e543be47..00000000 --- a/keystonemiddleware-moon/doc/source/middlewarearchitecture.rst +++ /dev/null @@ -1,472 +0,0 @@ -.. Copyright 2011-2013 OpenStack Foundation -.. 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. - -======================= -Middleware Architecture -======================= - -Abstract -======== - -The Keystone middleware architecture supports a common authentication protocol -in use between the OpenStack projects. By using keystone as a common -authentication and authorization mechanism, the OpenStack project can plug in -to existing authentication and authorization systems in use by existing -environments. - -In this document, we describe the architecture and responsibilities of the -authentication middleware which acts as the internal API mechanism for -OpenStack projects based on the WSGI standard. - -This documentation describes the implementation in -:class:`keystonemiddleware.auth_token` - -Specification Overview -====================== - -'Authentication' is the process of determining that users are who they say they -are. Typically, 'authentication protocols' such as HTTP Basic Auth, Digest -Access, public key, token, etc, are used to verify a user's identity. In this -document, we define an ''authentication component'' as a software module that -implements an authentication protocol for an OpenStack service. OpenStack is -using a token based mechanism to represent authentication and authorization. - -At a high level, an authentication middleware component is a proxy that -intercepts HTTP calls from clients and populates HTTP headers in the request -context for other WSGI middleware or applications to use. The general flow -of the middleware processing is: - -* clear any existing authorization headers to prevent forgery -* collect the token from the existing HTTP request headers -* validate the token - - * if valid, populate additional headers representing the identity that has - been authenticated and authorized - * if invalid, or no token present, reject the request (HTTPUnauthorized) - or pass along a header indicating the request is unauthorized (configurable - in the middleware) - * if the keystone service is unavailable to validate the token, reject - the request with HTTPServiceUnavailable. - -.. _authComponent: - -Authentication Component ------------------------- - -Figure 1. Authentication Component - -.. image:: images/graphs_authComp.svg - :width: 100% - :height: 180 - :alt: An Authentication Component - -The middleware may also be configured to operate in a 'delegated mode'. -In this mode, the decision to reject an unauthenticated client is delegated to -the OpenStack service, as illustrated in :ref:`authComponentDelegated`. - -Here, requests are forwarded to the OpenStack service with an identity status -message that indicates whether the client's identity has been confirmed or is -indeterminate. It is the OpenStack service that decides whether or not a reject -message should be sent to the client. - -.. _authComponentDelegated: - -Authentication Component (Delegated Mode) ------------------------------------------ - -Figure 2. Authentication Component (Delegated Mode) - -.. image:: images/graphs_authCompDelegate.svg - :width: 100% - :height: 180 - :alt: An Authentication Component (Delegated Mode) - -.. _deployStrategies: - -Deployment Strategy -=================== - -The middleware is intended to be used inline with OpenStack wsgi components, -based on the Oslo WSGI middleware class. It is typically deployed -as a configuration element in a paste configuration pipeline of other -middleware components, with the pipeline terminating in the service -application. The middleware conforms to the python WSGI standard [PEP-333]_. -In initializing the middleware, a configuration item (which acts like a python -dictionary) is passed to the middleware with relevant configuration options. - -Configuration -------------- - -The middleware is configured within the config file of the main application as -a WSGI component. Example for the auth_token middleware: - -.. code-block:: ini - - [app:myService] - paste.app_factory = myService:app_factory - - [pipeline:main] - pipeline = authtoken myService - - [filter:authtoken] - paste.filter_factory = keystonemiddleware.auth_token:filter_factory - - # Prefix to prepend at the beginning of the path (string - # value) - #auth_admin_prefix= - - # Host providing the admin Identity API endpoint (string - # value) - auth_host=127.0.0.1 - - # Port of the admin Identity API endpoint (integer value) - auth_port=35357 - - # Protocol of the admin Identity API endpoint(http or https) - # (string value) - auth_protocol=https - - # Complete public Identity API endpoint (string value) - #auth_uri=<None> - - # API version of the admin Identity API endpoint (string - # value) - #auth_version=<None> - - # Do not handle authorization requests within the middleware, - # but delegate the authorization decision to downstream WSGI - # components (boolean value) - #delay_auth_decision=false - - # Request timeout value for communicating with Identity API - # server. (boolean value) - #http_connect_timeout=<None> - - # How many times are we trying to reconnect when communicating - # with Identity API Server. (integer value) - #http_request_max_retries=3 - - # Single shared secret with the Keystone configuration used - # for bootstrapping a Keystone installation, or otherwise - # bypassing the normal authentication process. (string value) - #admin_token=<None> - - # Keystone account username (string value) - #admin_user=<None> - - # Keystone account password (string value) - admin_password=SuperSekretPassword - - # Keystone service account tenant name to validate user tokens - # (string value) - #admin_tenant_name=admin - - # Env key for the swift cache (string value) - #cache=<None> - - # Required if Keystone server requires client certificate - # (string value) - #certfile=<None> - - # Required if Keystone server requires client certificate - # (string value) - #keyfile=<None> - - # A PEM encoded Certificate Authority to use when verifying - # HTTPs connections. Defaults to system CAs. (string value) - #cafile=<None> - - # Verify HTTPS connections. (boolean value) - #insecure=false - - # Directory used to cache files related to PKI tokens (string - # value) - #signing_dir=<None> - - # If defined, the memcached server(s) to use for caching (list - # value) - # Deprecated group/name - [DEFAULT]/memcache_servers - #memcached_servers=<None> - - # In order to prevent excessive requests and validations, the - # middleware uses an in-memory cache for the tokens the - # Keystone API returns. This is only valid if memcache_servers - # is defined. Set to -1 to disable caching completely. - # (integer value) - #token_cache_time=300 - - # Value only used for unit testing (integer value) - #revocation_cache_time=1 - - # (optional) if defined, indicate whether token data should be - # authenticated or authenticated and encrypted. Acceptable - # values are MAC or ENCRYPT. If MAC, token data is - # authenticated (with HMAC) in the cache. If ENCRYPT, token - # data is encrypted and authenticated in the cache. If the - # value is not one of these options or empty, auth_token will - # raise an exception on initialization. (string value) - #memcache_security_strategy=<None> - - # (optional, mandatory if memcache_security_strategy is - # defined) this string is used for key derivation. (string - # value) - #memcache_secret_key=<None> - - # (optional) indicate whether to set the X-Service-Catalog - # header. If False, middleware will not ask for service - # catalog on token validation and will not set the X-Service- - # Catalog header. (boolean value) - #include_service_catalog=true - - # Used to control the use and type of token binding. Can be - # set to: "disabled" to not check token binding. "permissive" - # (default) to validate binding information if the bind type - # is of a form known to the server and ignore it if not. - # "strict" like "permissive" but if the bind type is unknown - # the token will be rejected. "required" any form of token - # binding is needed to be allowed. Finally the name of a - # binding method that must be present in tokens. (string - # value) - #enforce_token_bind=permissive - -For services which have a separate paste-deploy ini file, auth_token middleware -can be alternatively configured in [keystone_authtoken] section in the main -config file. For example in Nova, all middleware parameters can be removed -from ``api-paste.ini``: - -.. code-block:: ini - - [filter:authtoken] - paste.filter_factory = keystonemiddleware.auth_token:filter_factory - -and set in ``nova.conf``: - -.. code-block:: ini - - [DEFAULT] - auth_strategy=keystone - - [keystone_authtoken] - auth_host = 127.0.0.1 - auth_port = 35357 - auth_protocol = http - admin_user = admin - admin_password = SuperSekretPassword - admin_tenant_name = service - # Any of the options that could be set in api-paste.ini can be set here. - -Note that middleware parameters in paste config take priority, they must be -removed to use values in [keystone_authtoken] section. - -If the service doesn't use the global oslo.config object (CONF), then the -olso config project name can be set it in paste config and -keystonemiddleware will load the project configuration itself. -Optionally the location of the configuration file can be set if oslo.config -is not able to discover it. - -.. code-block:: ini - - [filter:authtoken] - paste.filter_factory = keystonemiddleware.auth_token:filter_factory - oslo_config_project = nova - # oslo_config_file = /not_discoverable_location/nova.conf - - -Configuration Options ---------------------- - -* ``auth_admin_prefix``: Prefix to prepend at the beginning of the path -* ``auth_host``: (required) the host providing the keystone service API endpoint - for validating and requesting tokens -* ``auth_port``: (optional, default `35357`) the port used to validate tokens -* ``auth_protocol``: (optional, default `https`) -* ``auth_uri``: (optional, defaults to - `auth_protocol`://`auth_host`:`auth_port`) -* ``auth_version``: API version of the admin Identity API endpoint -* ``delay_auth_decision``: (optional, default `0`) (off). If on, the middleware - will not reject invalid auth requests, but will delegate that decision to - downstream WSGI components. -* ``http_connect_timeout``: (optional) Request timeout value for communicating - with Identity API server. -* ``http_request_max_retries``: (default 3) How many times are we trying to - reconnect when communicating with Identity API Server. -* ``http_handler``: (optional) Allows to pass in the name of a fake - http_handler callback function used instead of `httplib.HTTPConnection` or - `httplib.HTTPSConnection`. Useful for unit testing where network is not - available. - -* ``admin_token``: either this or the following three options are required. If - set, this is a single shared secret with the keystone configuration used to - validate tokens. -* ``admin_user``, ``admin_password``, ``admin_tenant_name``: if ``admin_token`` - is not set, or invalid, then admin_user, admin_password, and - admin_tenant_name are defined as a service account which is expected to have - been previously configured in Keystone to validate user tokens. - -* ``cache``: (optional) Env key for the swift cache - -* ``certfile``: (required, if Keystone server requires client cert) -* ``keyfile``: (required, if Keystone server requires client cert) This can be - the same as the certfile if the certfile includes the private key. -* ``cafile``: (optional, defaults to use system CA bundle) the path to a PEM - encoded CA file/bundle that will be used to verify HTTPS connections. -* ``insecure``: (optional, default `False`) Don't verify HTTPS connections - (overrides `cafile`). - -* ``signing_dir``: (optional) Directory used to cache files related to PKI - tokens - -* ``memcached_servers``: (optional) If defined, the memcached server(s) to use - for caching -* ``token_cache_time``: (default 300) In order to prevent excessive requests - and validations, the middleware uses an in-memory cache for the tokens the - Keystone API returns. This is only valid if memcache_servers s defined. Set - to -1 to disable caching completely. -* ``memcache_security_strategy``: (optional) if defined, indicate whether token - data should be authenticated or authenticated and encrypted. Acceptable - values are MAC or ENCRYPT. If MAC, token data is authenticated (with HMAC) - in the cache. If ENCRYPT, token data is encrypted and authenticated in the - cache. If the value is not one of these options or empty, auth_token will - raise an exception on initialization. -* ``memcache_secret_key``: (mandatory if memcache_security_strategy is defined) - this string is used for key derivation. -* ``include_service_catalog``: (optional, default `True`) Indicate whether to - set the X-Service-Catalog header. If False, middleware will not ask for - service catalog on token validation and will not set the X-Service-Catalog - header. -* ``enforce_token_bind``: (default ``permissive``) Used to control the use and - type of token binding. Can be set to: "disabled" to not check token binding. - "permissive" (default) to validate binding information if the bind type is of - a form known to the server and ignore it if not. "strict" like "permissive" - but if the bind type is unknown the token will be rejected. "required" any - form of token binding is needed to be allowed. Finally the name of a binding - method that must be present in tokens. - -Caching for improved response ------------------------------ - -In order to prevent excessive requests and validations, the middleware uses an -in-memory cache for the tokens the keystone API returns. Keep in mind that -invalidated tokens may continue to work if they are still in the token cache, -so token_cache_time is configurable. For larger deployments, the middleware -also supports memcache based caching. - -* ``memcached_servers``: (optonal) if defined, the memcached server(s) to use for - cacheing. It will be ignored if Swift MemcacheRing is used instead. -* ``token_cache_time``: (optional, default 300 seconds) Set to -1 to disable - caching completely. - -When deploying auth_token middleware with Swift, user may elect -to use Swift MemcacheRing instead of the local Keystone memcache. -The Swift MemcacheRing object is passed in from the request environment -and it defaults to 'swift.cache'. However it could be -different, depending on deployment. To use Swift MemcacheRing, you must -provide the ``cache`` option. - -* ``cache``: (optional) if defined, the environment key where the Swift - MemcacheRing object is stored. - -Memcached dependencies -====================== - -In order to use `memcached`_ it is necessary to install the `python-memcached`_ -library. If data stored in `memcached`_ will need to be encrypted it is also -necessary to install the `pycrypto`_ library. These libs are not listed in -the requirements.txt file. - -.. _`memcached`: http://memcached.org/ -.. _`python-memcached`: https://pypi.python.org/pypi/python-memcached -.. _`pycrypto`: https://pypi.python.org/pypi/pycrypto - -Memcached and System Time -========================= - -When using `memcached`_ with ``auth_token`` middleware, ensure that the system -time of memcached hosts is set to UTC. Memcached uses the host's system -time in determining whether a key has expired, whereas Keystone sets -key expiry in UTC. The timezone used by Keystone and memcached must -match if key expiry is to behave as expected. - -Memcache Protection -=================== - -When using memcached, we are storing user tokens and token validation -information into the cache as raw data. Which means that anyone who -has access to the memcached servers can read and modify data stored -there. To mitigate this risk, ``auth_token`` middleware provides an -option to authenticate and optionally encrypt the token data stored in -the cache. - -* ``memcache_security_strategy``: (optional) if defined, indicate - whether token data should be authenticated or authenticated and - encrypted. Acceptable values are ``MAC`` or ``ENCRYPT``. If ``MAC``, - token data is authenticated (with HMAC) in the cache. If - ``ENCRYPT``, token data is encrypted and authenticated in the - cache. If the value is not one of these options or empty, - ``auth_token`` will raise an exception on initialization. -* ``memcache_secret_key``: (optional, mandatory if - ``memcache_security_strategy`` is defined) this string is used for - key derivation. If ``memcache_security_strategy`` is defined and - ``memcache_secret_key`` is absent, ``auth_token`` will raise an - exception on initialization. - -Exchanging User Information -=========================== - -The middleware expects to find a token representing the user with the header -``X-Auth-Token`` or ``X-Storage-Token``. `X-Storage-Token` is supported for -swift/cloud files and for legacy Rackspace use. If the token isn't present and -the middleware is configured to not delegate auth responsibility, it will -respond to the HTTP request with HTTPUnauthorized, returning the header -``WWW-Authenticate`` with the value `Keystone uri='...'` to indicate where to -request a token. The auth_uri returned is configured with the middleware. - -The authentication middleware extends the HTTP request with the header -``X-Identity-Status``. If a request is successfully authenticated, the value -is set to `Confirmed`. If the middleware is delegating the auth decision to the -service, then the status is set to `Invalid` if the auth request was -unsuccessful. - -An ``X-Service-Token`` header may also be included with a request. If present, -and the value of ``X-Auth-Token`` or ``X-Storage-Token`` has not caused the -request to be denied, then the middleware will attempt to validate the value of -``X-Service-Token``. If valid, the authentication middleware extends the HTTP -request with the header ``X-Service-Identity-Status`` having value `Confirmed` -and also extends the request with additional headers representing the identity -authenticated and authorised by the token. - -If ``X-Service-Token`` is present and its value is invalid and the -``delay_auth_decision`` option is True then the value of -``X-Service-Identity-Status`` is set to `Invalid` and no further headers are -added. Otherwise if ``X-Service-Token`` is present and its value is invalid -then the middleware will respond to the HTTP request with HTTPUnauthorized, -regardless of the validity of the ``X-Auth-Token`` or ``X-Storage-Token`` -values. - -Extended the request with additional User Information ------------------------------------------------------ - -:py:class:`keystonemiddleware.auth_token.AuthProtocol` extends the -request with additional information if the user has been authenticated. See the -"What we add to the request for use by the OpenStack service" section in -:py:mod:`keystonemiddleware.auth_token` for the list of fields set by -the auth_token middleware. - - -References -========== - -.. [PEP-333] pep0333 Phillip J Eby. 'Python Web Server Gateway Interface - v1.0.'' http://www.python.org/dev/peps/pep-0333/. diff --git a/keystonemiddleware-moon/examples/pki/certs/cacert.pem b/keystonemiddleware-moon/examples/pki/certs/cacert.pem deleted file mode 100644 index 952bdaea..00000000 --- a/keystonemiddleware-moon/examples/pki/certs/cacert.pem +++ /dev/null @@ -1,23 +0,0 @@ ------BEGIN CERTIFICATE----- -MIID1jCCAr6gAwIBAgIJAJOtRP2+wrM/MA0GCSqGSIb3DQEBBQUAMIGeMQowCAYD -VQQFEwE1MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVN1bm55 -dmFsZTESMBAGA1UEChMJT3BlblN0YWNrMREwDwYDVQQLEwhLZXlzdG9uZTElMCMG -CSqGSIb3DQEJARYWa2V5c3RvbmVAb3BlbnN0YWNrLm9yZzEUMBIGA1UEAxMLU2Vs -ZiBTaWduZWQwIBcNMTMwOTEzMTYyNTQyWhgPMjA3MjAzMDcxNjI1NDJaMIGeMQow -CAYDVQQFEwE1MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVN1 -bm55dmFsZTESMBAGA1UEChMJT3BlblN0YWNrMREwDwYDVQQLEwhLZXlzdG9uZTEl -MCMGCSqGSIb3DQEJARYWa2V5c3RvbmVAb3BlbnN0YWNrLm9yZzEUMBIGA1UEAxML -U2VsZiBTaWduZWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCl8906 -EaRpibQFcCBWfxzLi5x/XpZ9iL6UX92NrSJxcDbaGws7s+GtjgDy8UOEonesRWTe -qQEZtHpC3/UHHOnsA8F6ha/pq9LioqT7RehCnZCLBJwh5Ct+lclpWs15SkjJD2LT -Dkjox0eA9nOBx+XDlWyU/GAyqx5Wsvg/Kxr0iod9/4IcJdnSdUjq4v0Cxg/zNk08 -XPJX+F0bUDhgdUf7JrAmmS5LA8wphRnbIgtVsf6VN9HrbqtHAJDxh8gEfuwdhEW1 -df1fBtZ+6WMIF3IRSbIsZELFB6sqcyRj7HhMoWMkdEyPb2f8mq61MzTgE6lJGIyT -RvEoFie7qtGADIofAgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN -AQEFBQADggEBAJRMdEwAdN+crqI9dBLYlbBbnQ8xr9mk+REMdz9+SKhDCNdVisWU -iLEZvK/aozrsRsDi81JjS4Tz0wXo8zsPPoDnXgDYEicNPTKifbPKgHdDIGFOwBKn -y2cF6fHEn8n3KIBrDCNY6rHcYGZ7lbq/8eF0GoYQboPiuYesvVpynPmIK5/Mmire -EuuZALAe1IFqqFt+l6tiJU2JWUFjLkFARMOD14qFZm+SInl64toi08j6gdou+NMW -7GEMbVHwNTafM/TgFN5j0yP9SAnYubckLSyH6hwR+rM8dztP5769joxQfnc9O/Bn -TBD9KFpeQv6VJWLAxiIKcQCRTTDJLZZ0MQI= ------END CERTIFICATE----- diff --git a/keystonemiddleware-moon/examples/pki/certs/middleware.pem b/keystonemiddleware-moon/examples/pki/certs/middleware.pem deleted file mode 100644 index 7d593efd..00000000 --- a/keystonemiddleware-moon/examples/pki/certs/middleware.pem +++ /dev/null @@ -1,50 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDpjCCAo4CARAwDQYJKoZIhvcNAQEFBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV -BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQK -EwlPcGVuU3RhY2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZr -ZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZDAgFw0x -MzA5MTMxNjI1NDNaGA8yMDcyMDMwNzE2MjU0M1owgZAxCzAJBgNVBAYTAlVTMQsw -CQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3Rh -Y2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBv -cGVuc3RhY2sub3JnMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDL06AaJROwHPgJ9tcySSBepzJ81jYars2sMvLjyuvd -iIBbhWvbS/a9Tw3WgL8H6OALkHiOU/f0A6Rpv8dGDIDsxZQVjT/4SLaQUOeDM+9b -fkKHpSd9G3CsdSSZgOH08n+MyZ7slPHfUHLYWso0SJD0vAi1gmGDlSM/mmhhHTpC -DGo6Wbwqare6JNeTCGJTJYwrxtoMCh/W1ZrslPC5lFvlHD7KBBf6IU2A8Xh/dUa3 -p5pmQeHPW8Em90DzIB1qH0DRXl3KANc24xYRR45pPCVkk6vFsy6P0JwwpnkszB+L -cK6CEsJhLsOYvQFsiQfSZ8m7YGhgrMLxtop4YEPirGGrAgMBAAEwDQYJKoZIhvcN -AQEFBQADggEBAAjU7YomUx/U56p1KWHvr1B7oczHF8fPHYbuk5c/N81WOJeSRy+P -5ZGZ2UPjvqqXByv+78YWMKGY1BZ/2doeWuydr0sdSxEwmIUBYxFpujuYY+0AjS/n -mMr1ZijK7TJssteKM7/MClzghUhPweDZrAg3ff1hbhK5QSy+9UPxUqLH44tfYSVC -/BzM6se0p5ToM0bwdsa8TofaBRE1L1IW/Hg4VIGOoKs0R0uLm7+Oot2me2cEuZ6h -Wls6MED8ND1Nz8EAKwndkeDu2iMM+qx/YFp6K8BQ5E5nXd2rbUZUlQMp1WbUlZ87 -KvC98aT0UYIq6uo1Lx/dQvJs7faAkYd4lmE= ------END CERTIFICATE----- ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDL06AaJROwHPgJ -9tcySSBepzJ81jYars2sMvLjyuvdiIBbhWvbS/a9Tw3WgL8H6OALkHiOU/f0A6Rp -v8dGDIDsxZQVjT/4SLaQUOeDM+9bfkKHpSd9G3CsdSSZgOH08n+MyZ7slPHfUHLY -Wso0SJD0vAi1gmGDlSM/mmhhHTpCDGo6Wbwqare6JNeTCGJTJYwrxtoMCh/W1Zrs -lPC5lFvlHD7KBBf6IU2A8Xh/dUa3p5pmQeHPW8Em90DzIB1qH0DRXl3KANc24xYR -R45pPCVkk6vFsy6P0JwwpnkszB+LcK6CEsJhLsOYvQFsiQfSZ8m7YGhgrMLxtop4 -YEPirGGrAgMBAAECggEATwvbY0hNwlb5uqOIAXBqpUqiQdexU9fG26lGmSDxKBDv -9o5frcRgBDrMWwvDCgY+HT4CAvB9kJx4/qnpVjkzJp/ZNiJ5VIiehIlbv348rXbh -xkk+bz5dDATCFOXuu1fwL2FhyM5anwhMAav0DyK1VLQ3jGzr9GO6L8hqAn+bQFFu -6ngiODwfhBMl5aRoL9UOBEhccK07znrH0JGRz+3+5Cdz59Xw91Bv210LhNNDL58+ -0JD0N+YztVOQd2bgwo0bQbOEijzmYq+0mjoqAnJh1/++y7PlIPs0AnPgqSnFPx9+ -6FsQEVRgk5Uq3kvPLaP4nT2y6MDZSp+ujYldvJhyQQKBgQDuX2pZIJMZ4aFnkG+K -TmJ5wsLa/u9an0TmvAL9RLtBpVpQNKD8cQ+y8PUZavXDbAIt5NWqZVnTbCR79Dnd -mZKblwcHhtsyA5f89el5KcxY2BREWdHdTnJpNd7XRlUECmzvX1zGj77lA982PhII -yflRBRV3vqLkgC8vfoYgRyRElwKBgQDa5jnLdx/RahfYMOgn1HE5o4hMzLR4Y0Dd -+gELshcUbPqouoP5zOb8WOagVJIgZVOSN+/VqbilVYrqRiNTn2rnoxs+HHRdaJNN -3eXllD4J2HfC2BIj1xSpIdyh2XewAJqw9IToHNB29QUhxOtgwseHciPG6JaKH2ik -kqGKH/EKDQKBgFFAftygiOPCkCTgC9UmANUmOQsy6N2H+pF3tsEj43xt44oBVnqW -A1boYXNnjRwuvdNs9BPf9i1l6E3EItFRXrLgWQoMwryakv0ryYh+YeRKyyW9RBbe -fYs1TJ8unx4Ae79gTxxztQsVNcmkgLs0NWKTjAzEE3w14V+cDhYEie1DAoGBAJdI -V5cLrBzBstsB6eBlDR9lqrRRIUS2a8U9m+1mVlcSfiWQSdehSd4K3tDdwePLw3ch -W4qR8n+pYAlLEe0gFvUhn5lMdwt7U5qUCeehjUKmrRYm2FqWsbu2IFJnBjXIJSC4 -zQXRrC0aZ0KQYpAL7XPpaVp1slyhGmPqxuO78Y0dAoGBAMHo3EIMwu9rfuGwFodr -GFsOZhfJqgo5GDNxxf89Q9WWpMDTCdX+wdBTrN/wsMbBuwIDHrUuRnk6D5CWRjSk -/ikCgHN3kOtrbL8zzqRomGAIIWKYGFEIGe1GHVGo5r//HXHdPxFXygvruQ/xbOA4 -RGvmDiji8vVDq7Shho8I6KuT ------END PRIVATE KEY----- diff --git a/keystonemiddleware-moon/examples/pki/certs/signing_cert.pem b/keystonemiddleware-moon/examples/pki/certs/signing_cert.pem deleted file mode 100644 index 63ab2478..00000000 --- a/keystonemiddleware-moon/examples/pki/certs/signing_cert.pem +++ /dev/null @@ -1,22 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDpTCCAo0CAREwDQYJKoZIhvcNAQEFBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV -BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQK -EwlPcGVuU3RhY2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZr -ZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZDAgFw0x -MzA5MTMxNjI1NDNaGA8yMDcyMDMwNzE2MjU0M1owgY8xCzAJBgNVBAYTAlVTMQsw -CQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3Rh -Y2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBv -cGVuc3RhY2sub3JnMREwDwYDVQQDEwhLZXlzdG9uZTCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAMz5WsgsuX3rZUdLwQpZXN2Ro7LQ6jEZnreBqMztVObw -BuC1WdiJsg6dVlC7PVdt+0gY1c8WFg1TKmsucxesQSyfGAPg+9T/hsRMb6y12uJx -fp3Wgqqw0U1HsXvMiaJH87MaGnt043BxzF+R9fhAcDk6Cyj5cx9J0LvZJEOzN4J4 -ZRyO6j/DZZItb3lK5W9xkuoT+mTdDZOQJnXyG818uiWfjdCkLjr1ruytRcBOo4na -Y828voT/A7I95+YCgKgbjiUWhHeTaNmMEQiGy0nGYfteC+oSsHOlxZ3b12azzHPk -83Bh2ez0Ih9vcZoe9DqvlFOXfv9q8OsYc5Yo6gPTXEsCAwEAATANBgkqhkiG9w0B -AQUFAAOCAQEAmaYE98kOQWu6DV84ZcZP/OdT8eeu3vdB247nRj+6+GYItN/Gzqt4 -HVvz7c+FVTolCcAQQ+z3XGswI9fIJ78Hb0p9CgnLprc3L7Xtk60Im59Xlf3tcurn -r/ZnSDcjRBXKiEDrSM0VrhAnc0GoSeb6aDWopec+1hWOWfBVAg9R8yJgU9sUgO3O -0gimGyrw8eubmNhckSQLJTunUTsrkcBjuSg63wAD9OqCiX6c2eoQr+0YBp2eV2/n -aOiJXWNLbeueMKSYiJNyyvM/dlON7/56cdwDTzKzgD34TImouM5VKipUwCX1ovLu -ITLzALzpqFFzc8ugV9pMgUKtDbZoPp9EEA== ------END CERTIFICATE----- diff --git a/keystonemiddleware-moon/examples/pki/certs/ssl_cert.pem b/keystonemiddleware-moon/examples/pki/certs/ssl_cert.pem deleted file mode 100644 index cdd2e4c0..00000000 --- a/keystonemiddleware-moon/examples/pki/certs/ssl_cert.pem +++ /dev/null @@ -1,22 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDpjCCAo4CARAwDQYJKoZIhvcNAQEFBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV -BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQK -EwlPcGVuU3RhY2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZr -ZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZDAgFw0x -MzA5MTMxNjI1NDNaGA8yMDcyMDMwNzE2MjU0M1owgZAxCzAJBgNVBAYTAlVTMQsw -CQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3Rh -Y2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBv -cGVuc3RhY2sub3JnMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDL06AaJROwHPgJ9tcySSBepzJ81jYars2sMvLjyuvd -iIBbhWvbS/a9Tw3WgL8H6OALkHiOU/f0A6Rpv8dGDIDsxZQVjT/4SLaQUOeDM+9b -fkKHpSd9G3CsdSSZgOH08n+MyZ7slPHfUHLYWso0SJD0vAi1gmGDlSM/mmhhHTpC -DGo6Wbwqare6JNeTCGJTJYwrxtoMCh/W1ZrslPC5lFvlHD7KBBf6IU2A8Xh/dUa3 -p5pmQeHPW8Em90DzIB1qH0DRXl3KANc24xYRR45pPCVkk6vFsy6P0JwwpnkszB+L -cK6CEsJhLsOYvQFsiQfSZ8m7YGhgrMLxtop4YEPirGGrAgMBAAEwDQYJKoZIhvcN -AQEFBQADggEBAAjU7YomUx/U56p1KWHvr1B7oczHF8fPHYbuk5c/N81WOJeSRy+P -5ZGZ2UPjvqqXByv+78YWMKGY1BZ/2doeWuydr0sdSxEwmIUBYxFpujuYY+0AjS/n -mMr1ZijK7TJssteKM7/MClzghUhPweDZrAg3ff1hbhK5QSy+9UPxUqLH44tfYSVC -/BzM6se0p5ToM0bwdsa8TofaBRE1L1IW/Hg4VIGOoKs0R0uLm7+Oot2me2cEuZ6h -Wls6MED8ND1Nz8EAKwndkeDu2iMM+qx/YFp6K8BQ5E5nXd2rbUZUlQMp1WbUlZ87 -KvC98aT0UYIq6uo1Lx/dQvJs7faAkYd4lmE= ------END CERTIFICATE----- diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_token_revoked.json b/keystonemiddleware-moon/examples/pki/cms/auth_token_revoked.json deleted file mode 100644 index 3da8f8bb..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_token_revoked.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "access": { - "token": { - "expires": "2038-01-18T21:14:07Z", - "id": "placeholder", - "tenant": { - "id": "tenant_id1", - "enabled": true, - "description": null, - "name": "tenant_name1" - } - }, - "serviceCatalog": [ - { - "endpoints_links": [], - "endpoints": [ - { - "adminURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", - "region": "regionOne", - "internalURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", - "publicURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a" - } - ], - "type": "volume", - "name": "volume" - }, - { - "endpoints_links": [], - "endpoints": [ - { - "adminURL": "http://127.0.0.1:9292/v1", - "region": "regionOne", - "internalURL": "http://127.0.0.1:9292/v1", - "publicURL": "http://127.0.0.1:9292/v1" - } - ], - "type": "image", - "name": "glance" - }, - { - "endpoints_links": [], - "endpoints": [ - { - "adminURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", - "region": "regionOne", - "internalURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", - "publicURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a" - } - ], - "type": "compute", - "name": "nova" - }, - { - "endpoints_links": [], - "endpoints": [ - { - "adminURL": "http://127.0.0.1:35357/v2.0", - "region": "RegionOne", - "internalURL": "http://127.0.0.1:35357/v2.0", - "publicURL": "http://127.0.0.1:5000/v2.0" - } - ], - "type": "identity", - "name": "keystone" - } - ], - "user": { - "username": "revoked_username1", - "roles_links": [ - "role1", - "role2" - ], - "id": "revoked_user_id1", - "roles": [ - { - "name": "role1" - }, - { - "name": "role2" - } - ], - "name": "revoked_username1" - } - } -} diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_token_revoked.pem b/keystonemiddleware-moon/examples/pki/cms/auth_token_revoked.pem deleted file mode 100644 index a685a457..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_token_revoked.pem +++ /dev/null @@ -1,75 +0,0 @@ ------BEGIN CMS----- -MIINnQYJKoZIhvcNAQcCoIINjjCCDYoCAQExCTAHBgUrDgMCGjCCC6oGCSqGSIb3 -DQEHAaCCC5sEgguXew0KICAgICJhY2Nlc3MiOiB7DQogICAgICAgICJ0b2tlbiI6 -IHsNCiAgICAgICAgICAgICJleHBpcmVzIjogIjIwMzgtMDEtMThUMjE6MTQ6MDda -IiwNCiAgICAgICAgICAgICJpZCI6ICJwbGFjZWhvbGRlciIsDQogICAgICAgICAg -ICAidGVuYW50Ijogew0KICAgICAgICAgICAgICAgICJpZCI6ICJ0ZW5hbnRfaWQx -IiwNCiAgICAgICAgICAgICAgICAiZW5hYmxlZCI6IHRydWUsDQogICAgICAgICAg -ICAgICAgImRlc2NyaXB0aW9uIjogbnVsbCwNCiAgICAgICAgICAgICAgICAibmFt -ZSI6ICJ0ZW5hbnRfbmFtZTEiDQogICAgICAgICAgICB9DQogICAgICAgIH0sDQog -ICAgICAgICJzZXJ2aWNlQ2F0YWxvZyI6IFsNCiAgICAgICAgICAgIHsNCiAgICAg -ICAgICAgICAgICAiZW5kcG9pbnRzX2xpbmtzIjogW10sDQogICAgICAgICAgICAg -ICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAg -ICAgICAgICAgICAgICAgICAgImFkbWluVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6 -ODc3Ni92MS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIsDQogICAg -ICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSIsDQogICAg -ICAgICAgICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4w -LjAuMTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwN -CiAgICAgICAgICAgICAgICAgICAgICAgICJwdWJsaWNVUkwiOiAiaHR0cDovLzEy -Ny4wLjAuMTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdh -Ig0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgXSwNCiAg -ICAgICAgICAgICAgICAidHlwZSI6ICJ2b2x1bWUiLA0KICAgICAgICAgICAgICAg -ICJuYW1lIjogInZvbHVtZSINCiAgICAgICAgICAgIH0sDQogICAgICAgICAgICB7 -DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtdLA0KICAgICAg -ICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAgIHsN -CiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJodHRwOi8vMTI3 -LjAuMC4xOjkyOTIvdjEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lv -biI6ICJyZWdpb25PbmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVy -bmFsVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5Mi92MSIsDQogICAgICAgICAg -ICAgICAgICAgICAgICAicHVibGljVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5 -Mi92MSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIF0s -DQogICAgICAgICAgICAgICAgInR5cGUiOiAiaW1hZ2UiLA0KICAgICAgICAgICAg -ICAgICJuYW1lIjogImdsYW5jZSINCiAgICAgICAgICAgIH0sDQogICAgICAgICAg -ICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtdLA0KICAg -ICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAg -IHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJodHRwOi8v -MTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2 -NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lv -bk9uZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAi -aHR0cDovLzEyNy4wLjAuMTo4Nzc0L3YxLjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBm -Y2Y4OWJiNjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInB1YmxpY1VS -TCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVl -OGE2MGZjZjg5YmI2NjE3YSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAg -ICAgICAgICAgIF0sDQogICAgICAgICAgICAgICAgInR5cGUiOiAiY29tcHV0ZSIs -DQogICAgICAgICAgICAgICAgIm5hbWUiOiAibm92YSINCiAgICAgICAgICAgIH0s -DQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5r -cyI6IFtdLA0KICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAg -ICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVS -TCI6ICJodHRwOi8vMTI3LjAuMC4xOjM1MzU3L3YyLjAiLA0KICAgICAgICAgICAg -ICAgICAgICAgICAgInJlZ2lvbiI6ICJSZWdpb25PbmUiLA0KICAgICAgICAgICAg -ICAgICAgICAgICAgImludGVybmFsVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6MzUz -NTcvdjIuMCIsDQogICAgICAgICAgICAgICAgICAgICAgICAicHVibGljVVJMIjog -Imh0dHA6Ly8xMjcuMC4wLjE6NTAwMC92Mi4wIg0KICAgICAgICAgICAgICAgICAg -ICB9DQogICAgICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICAgICAidHlwZSI6 -ICJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAia2V5c3RvbmUi -DQogICAgICAgICAgICB9DQogICAgICAgIF0sDQogICAgICAgICJ1c2VyIjogew0K -ICAgICAgICAgICAgInVzZXJuYW1lIjogInJldm9rZWRfdXNlcm5hbWUxIiwNCiAg -ICAgICAgICAgICJyb2xlc19saW5rcyI6IFsNCiAgICAgICAgICAgICAgICAicm9s -ZTEiLA0KICAgICAgICAgICAgICAgICJyb2xlMiINCiAgICAgICAgICAgIF0sDQog -ICAgICAgICAgICAiaWQiOiAicmV2b2tlZF91c2VyX2lkMSIsDQogICAgICAgICAg -ICAicm9sZXMiOiBbDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAg -ICAgICAibmFtZSI6ICJyb2xlMSINCiAgICAgICAgICAgICAgICB9LA0KICAgICAg -ICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiAicm9sZTIi -DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgXSwNCiAgICAgICAgICAg -ICJuYW1lIjogInJldm9rZWRfdXNlcm5hbWUxIg0KICAgICAgICB9DQogICAgfQ0K -fQ0KMYIByjCCAcYCAQEwgaQwgZ4xCjAIBgNVBAUTATUxCzAJBgNVBAYTAlVTMQsw -CQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3Rh -Y2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBv -cGVuc3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZAIBETAHBgUrDgMCGjAN -BgkqhkiG9w0BAQEFAASCAQAxJMbNZf0/IWg/+/ciWQr9yuW9M48hQdaHcN+t6qvZ -OlPev8N1tP8pNTupW9LXt0N8ZU/8AzPLPeRXHqd4lzuDV6ttesfLL3Ag410o4Elb -Aum11Y1kDGlbwnaYoD9m07FML1ZfOWJ81Z0CITVGGRX90e+jlYjtnmdshmi2saVl -r/Sae6ta52gjptaZE9tOu42uXlfhWNuC0/W7lRuWbWSHZENZWtTHHz2Q+v/HxORf -jY3kwSaVEkx9faQ9Npy6J+rSQg+lIMRAYw/rFWedEsP9MzHKBcKTXid0yIQ2ox1r -1Em3WapL1FDpwJtHaaL92WTEQulpxJUcmzPgEd5H78+Q ------END CMS----- diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_token_revoked.pkiz b/keystonemiddleware-moon/examples/pki/cms/auth_token_revoked.pkiz deleted file mode 100644 index 9fbe8ea2..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_token_revoked.pkiz +++ /dev/null @@ -1 +0,0 @@ -PKIZ_eJylVtly4jgUfddXzHuqK9jGED_Mgze8BInYeEF-8wJeBYTF29ePbEh3p9OZycxQRZUtS_eee87Rlb59oz9J1Qz0hwzXw8s3AA1DZxpsPh8CI6tjJFqxfKBjnSLL0pMli5bayo6oS6l7UlIoawUd31qavH7V1kbEAcVSdTGkg4mrpunG3nZmhllUxRzMV7k0N_b0eR8cMespeGNnkSbsjeKQ-tw5j8jiAoK1MTNkk43Ylol8N1_KYh74fBlrwjHa2_3bZOzbl9DnPbdsaGAxD3V7EiuHGix7tUPdtFkW4hU6hynqY3bJ4XbZ4wkuAgLZIMcsZGBv9ch3p9jBTUAQWSlVjgvMAugkmZE3qbE3q4Ct6igfEXWBnxwjln-JyA0VzT4JNuYV--07FGCA8X9QgAHGDxQSg0l7xIy3duQRySHR7WaVP9XQMbgxgTxtV0XKoR7XSaHWABV2jgjuA2IWuHd7pEAmcLIMFRLBLJ6ufDNHBW4Rq-Y7b3KmQSfbjVQN5Br7oAaR7l2oEsOHKiJ2E7HVNdHRLtKqa3iTMtps6EL9JttdtX2kLa6YdXPwb2X7hS8ewKLsBsL-qxLgs8jvA39OLnjPbtmtHGNg9yNhpLpgP6nGgMS7BrpUD4hAzAhn-nCKOxp5cUl26yal-4HCZO4L-Toh6qcWB18kazDXZDQX1f5n6cE_aT9kjom3D33hetP-TnQpXAf5Aa1zgFTFhM-ixVccaA0cXeH6iUWawYKgoGAIKpADJ7D3qpWmslALiqBIeUwMFhUqh29GaxLfpHyhL22m39b7u3LB33qdoDraSEyifWw0G7Y9RuTSg1EOhhGWMm1fAw-0K43wWI-PObt-c-FndgdfkLCn_DCoE1iYT5tfLT-osP5q9_ldcPAx-lebittARaxBUhh0wBQ262GxzcfanQPfrmi9x0QvPyVw4AIMBN4X15S40W10L1RbXTpSB46TjMJoYJ9eoKJeoJO5sFBn0LFmUElCcINNs5HFNRkg085Ds2W0jCoY3-0u8d1B3h8b7G3-QriCYRDenFYGG1TEpGoS7d5UNJ6JtGb4dgxufEyG4LSMXehbrbGf3PbC_WND-1wR-FkdaXRv5KYw1J5s6NGW35DFRDjTJO_6JaCa0gXuW0sbnjujmvwC2awSIpwC396NAW-GG9fcA3j9zwfmvfN29Lyk5ZkfXDoicYzR-kMJTMx63c8Lg00wKFJuOK-_Geo7T2_lfp8D7pPupDDCztFkMT40aaprYqpK0NBK-t9C69DIIlY8y1qojcpA69zIFlYAHdDUxvTcXl1CsdRExlVlCcrWRG3VQrSkFHmSGDuyh5iI8HxCFhS-uoaSOM4FcgZNh5OqqEIT7KMTtNVGacZMS7XJlsGm6hONti9HraAMv99M6MXEFG3sgx_b1hOjIdD-FmhJhC7oVRdKxphJbOHSZb1zkEtO6CfXwKfXH5oMSA1ePDdTRcwOjWL9fFdSJckS6bVHFfF1IvDP-CWbCmXy9NpVu_BpqcRivc16oLGr4hK_vmoz1BDkvSxetosqVk-l6J5X-elhpsFty70GHNfuNX6VQnbGwedWP0pnp9wFMTBTn1wV_hryDJ7He69j2piEh31eh4yyeDTnVnOUqwekOJskWmXPiGm6R-UlY4xz-ZjMe0C6bus-TBfLy45cLuHM19gyW1Df1s5JbjUu1XU3FphSW7XS6UnvrDYL42XW7YvwyD-fOhBCxpuHZbEsrSeTeY6cR3W5TY66RQ4MmmvZUYXRflFI5uuWEecPjMA9If-BMIFQZVOb04E_O0ai7my7iTy3iyjLPXa6O678kDwyBSTepGIrln2AO_U4mzlzS-TU7WP1_DJr_vwTjHdVFSk_7q1_AfJ_mjc=
\ No newline at end of file diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped.json b/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped.json deleted file mode 100644 index cf18fa18..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "access": { - "token": { - "expires": "2038-01-18T21:14:07Z", - "id": "placeholder", - "tenant": { - "id": "tenant_id1", - "enabled": true, - "description": null, - "name": "tenant_name1" - }, - "audit_ids": [ - "SLIXlXQUQZWUi9VJrqdXqA" - ] - }, - "serviceCatalog": [ - { - "endpoints_links": [], - "endpoints": [ - { - "adminURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", - "region": "regionOne", - "internalURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", - "publicURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a" - } - ], - "type": "volume", - "name": "volume" - }, - { - "endpoints_links": [], - "endpoints": [ - { - "adminURL": "http://127.0.0.1:9292/v1", - "region": "regionOne", - "internalURL": "http://127.0.0.1:9292/v1", - "publicURL": "http://127.0.0.1:9292/v1" - } - ], - "type": "image", - "name": "glance" - }, - { - "endpoints_links": [], - "endpoints": [ - { - "adminURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", - "region": "regionOne", - "internalURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", - "publicURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a" - } - ], - "type": "compute", - "name": "nova" - }, - { - "endpoints_links": [], - "endpoints": [ - { - "adminURL": "http://127.0.0.1:35357/v2.0", - "region": "RegionOne", - "internalURL": "http://127.0.0.1:35357/v2.0", - "publicURL": "http://127.0.0.1:5000/v2.0" - } - ], - "type": "identity", - "name": "keystone" - } - ], - "user": { - "username": "user_name1", - "roles_links": [ - "role1", - "role2" - ], - "id": "user_id1", - "roles": [ - { - "name": "role1" - }, - { - "name": "role2" - } - ], - "name": "user_name1" - } - } -} diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped.pem b/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped.pem deleted file mode 100644 index 68f50493..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped.pem +++ /dev/null @@ -1,77 +0,0 @@ ------BEGIN CMS----- -MIIN5QYJKoZIhvcNAQcCoIIN1jCCDdICAQExDTALBglghkgBZQMEAgEwggvqBgkq -hkiG9w0BBwGgggvbBIIL13sNCiAgICAiYWNjZXNzIjogew0KICAgICAgICAidG9r -ZW4iOiB7DQogICAgICAgICAgICAiZXhwaXJlcyI6ICIyMDM4LTAxLTE4VDIxOjE0 -OjA3WiIsDQogICAgICAgICAgICAiaWQiOiAicGxhY2Vob2xkZXIiLA0KICAgICAg -ICAgICAgInRlbmFudCI6IHsNCiAgICAgICAgICAgICAgICAiaWQiOiAidGVuYW50 -X2lkMSIsDQogICAgICAgICAgICAgICAgImVuYWJsZWQiOiB0cnVlLA0KICAgICAg -ICAgICAgICAgICJkZXNjcmlwdGlvbiI6IG51bGwsDQogICAgICAgICAgICAgICAg -Im5hbWUiOiAidGVuYW50X25hbWUxIg0KICAgICAgICAgICAgfSwNCiAgICAgICAg -ICAgICJhdWRpdF9pZHMiOiBbDQogICAgICAgICAgICAgICAgIlNMSVhsWFFVUVpX -VWk5VkpycWRYcUEiDQogICAgICAgICAgICBdDQogICAgICAgIH0sDQogICAgICAg -ICJzZXJ2aWNlQ2F0YWxvZyI6IFsNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAg -ICAgICAiZW5kcG9pbnRzX2xpbmtzIjogW10sDQogICAgICAgICAgICAgICAgImVu -ZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAg -ICAgICAgICAgICAgImFkbWluVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3Ni92 -MS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIsDQogICAgICAgICAg -ICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSIsDQogICAgICAgICAg -ICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo4 -Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwNCiAgICAg -ICAgICAgICAgICAgICAgICAgICJwdWJsaWNVUkwiOiAiaHR0cDovLzEyNy4wLjAu -MTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIg0KICAg -ICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgXSwNCiAgICAgICAg -ICAgICAgICAidHlwZSI6ICJ2b2x1bWUiLA0KICAgICAgICAgICAgICAgICJuYW1l -IjogInZvbHVtZSINCiAgICAgICAgICAgIH0sDQogICAgICAgICAgICB7DQogICAg -ICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtdLA0KICAgICAgICAgICAg -ICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAg -ICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJodHRwOi8vMTI3LjAuMC4x -OjkyOTIvdjEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJy -ZWdpb25PbmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVybmFsVVJM -IjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5Mi92MSIsDQogICAgICAgICAgICAgICAg -ICAgICAgICAicHVibGljVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5Mi92MSIN -CiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIF0sDQogICAg -ICAgICAgICAgICAgInR5cGUiOiAiaW1hZ2UiLA0KICAgICAgICAgICAgICAgICJu -YW1lIjogImdsYW5jZSINCiAgICAgICAgICAgIH0sDQogICAgICAgICAgICB7DQog -ICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtdLA0KICAgICAgICAg -ICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAgIHsNCiAg -ICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJodHRwOi8vMTI3LjAu -MC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIs -DQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSIs -DQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAiaHR0cDov -LzEyNy4wLjAuMTo4Nzc0L3YxLjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJi -NjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInB1YmxpY1VSTCI6ICJo -dHRwOi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZj -Zjg5YmI2NjE3YSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAg -ICAgIF0sDQogICAgICAgICAgICAgICAgInR5cGUiOiAiY29tcHV0ZSIsDQogICAg -ICAgICAgICAgICAgIm5hbWUiOiAibm92YSINCiAgICAgICAgICAgIH0sDQogICAg -ICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtd -LA0KICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAg -ICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJo -dHRwOi8vMTI3LjAuMC4xOjM1MzU3L3YyLjAiLA0KICAgICAgICAgICAgICAgICAg -ICAgICAgInJlZ2lvbiI6ICJSZWdpb25PbmUiLA0KICAgICAgICAgICAgICAgICAg -ICAgICAgImludGVybmFsVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6MzUzNTcvdjIu -MCIsDQogICAgICAgICAgICAgICAgICAgICAgICAicHVibGljVVJMIjogImh0dHA6 -Ly8xMjcuMC4wLjE6NTAwMC92Mi4wIg0KICAgICAgICAgICAgICAgICAgICB9DQog -ICAgICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICAgICAidHlwZSI6ICJpZGVu -dGl0eSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAia2V5c3RvbmUiDQogICAg -ICAgICAgICB9DQogICAgICAgIF0sDQogICAgICAgICJ1c2VyIjogew0KICAgICAg -ICAgICAgInVzZXJuYW1lIjogInVzZXJfbmFtZTEiLA0KICAgICAgICAgICAgInJv -bGVzX2xpbmtzIjogWw0KICAgICAgICAgICAgICAgICJyb2xlMSIsDQogICAgICAg -ICAgICAgICAgInJvbGUyIg0KICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICJp -ZCI6ICJ1c2VyX2lkMSIsDQogICAgICAgICAgICAicm9sZXMiOiBbDQogICAgICAg -ICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJyb2xlMSIN -CiAgICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAg -ICAgICAgICAgICAgIm5hbWUiOiAicm9sZTIiDQogICAgICAgICAgICAgICAgfQ0K -ICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICJuYW1lIjogInVzZXJfbmFtZTEi -DQogICAgICAgIH0NCiAgICB9DQp9DQoxggHOMIIBygIBATCBpDCBnjEKMAgGA1UE -BRMBNTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTdW5ueXZh -bGUxEjAQBgNVBAoTCU9wZW5TdGFjazERMA8GA1UECxMIS2V5c3RvbmUxJTAjBgkq -hkiG9w0BCQEWFmtleXN0b25lQG9wZW5zdGFjay5vcmcxFDASBgNVBAMTC1NlbGYg -U2lnbmVkAgERMAsGCWCGSAFlAwQCATANBgkqhkiG9w0BAQEFAASCAQCgtkCXRzS8 -s7WjZCsKDhMt6q5JQIm7x6EMKCBaOABQG9EOVIAyqfoJDdjDtz9rZEPO3UVTpPkg -VjtA0QV97qT8bX55AcCkk7kBRDOKTtco5GOGwjMxL+GWbIwWiB7DKIP4RA6NLZtF -WxUbLBY+OgBSiayuHqSx+Rd08QC9oHf25wRkTNp3VFPxtAleDmASzdAoIafoS+FB -Po+9WuTaGdeya7S+ms4SSyXf9cdMKGv010R/aMINWUWaBrkB4wlespYLmKH/XzwS -pENRIdbI9XHEOYTWKqul5tucA3p21IA24ND6acl9CXHr3KeqXpRwclSZ38Kg/23T -92D+SowEjlGf ------END CMS----- diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped.pkiz b/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped.pkiz deleted file mode 100644 index cbfc0821..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped.pkiz +++ /dev/null @@ -1 +0,0 @@ -PKIZ_eJylVkuXojgY3edXzL5OnwLUKlnMgrdBwAJDgOx4KK-gVimC_PoJWFVdM93z6DNuNEFu7nfv98i3b-wjawZ0flPs7bj4BmwIV8s8MtdHAotr6khuqhzZ3nxQFFlcKpKr9SqSLDmneVHnMnFtTcq1Ls_DmZzXr6CoS0PsOFnujJxtHmUI9cXqXEaBU5HQGWB1zHc3k0uEC01K-ATZMxIWXRyaNL3BJwAVeLNVe24hqbeQNscq7DeVxm0qaRaU8AwV80QU9qJidomhVyQoronh0fT-jAMkWBTJwS03pfwMG9xGgXkmwbTm0gOmliKV8bSWyswYny-4UKC1vZ0AWhAFPB1pwoNHk0ZvM11sx733P9QsjCptaJcZ9DqFYCz4xOjFETgKcQ3i0NvHgTfFGtxMhDQaJXrhYazHmMenDSbr9KDXwUqXIeWnF1MB37KGVsR3CpAZ-jkR0pFywsRiLLwuEWibreyPvYIY_CmheIvuWhyzlddtyuXVRnAGrEpqbWXOhMtnzhBds0q7OpVXOk00kMasosEfHNXmCSoKp5KbSIjmm8AsnSrqHUErwUSpwYc4ENu7FiYlAou3Flty1-GUMH3Shomt_8gCjDT-Dwsw0phYrHCZGLTC2LQnJk3BZSvpybote7tKxwM6q9KeNmo6c0pRsLdLwTGgAEjFzmmcykE2Zw-YbgxNsA1SkSpfRA0UnEqbRVtTDLddPuYJWcnXmOVCyotn9v0GxnSE-iUbWWQr2rG4xxiFROj5JPAndiw_Ln_d3zPA0TXwq7Z916u-bRC8AiZY-X-cAH-H_An8L-KCT3URXNiTun8v2M_0AhO9QD-8U20_i6vJzqzyKsIALeVeqZ-AdyC2p9cgCWj7n7xXRnbz3hoiLqpIYwukjASbB_bgDk7gzyMUdaRxmo1Ky6hij1BWwLL7Lmg5CXcjQXZKhMVL0twtBiMlEo7Ue-zX3dQ44pXHperxag3azbmNLJjA6Dh3hpSzZlFvfUl18F8q7p_cAL8S78_CBZ_xHvjJHtYj69QQx8QZQqE_Jc3l3q14bmqiu1B-d8m5JqHMs470Q763yYwwQPbC2MK_AE5As7Hlexem3aQZ-AfRBlahvHNj4ZTz7ieObEdHwFdLfsGRT3DwHV3mo6Y_Rfy_VaHf2arEagWytSmCX8n7aUqx4cJmBLf7YbA0F7oLHTYDF_TDkSx0xhE2zcPp91jOrJlMU2pcU_EO8D6Fbqzb0D8zOLM-IZ4J-ugZ429Y3lnTejwYwAMemHBsOrn9u9JseOJPy77YOx1gf1bnnc1k4wfyHnN_Lul38AmEsdiHvGhHUB4qRZHS43h36EAeu11O5r1SSVDOHSxLPpKQ3yuDZN7XEZIoRrZ77hQ3UrHrQq0zVRdpW1uWDCDxvib3tunPcJscqMBygNoe7DRp-vNa6-hLypT3Z14RCedeQ9LLHfiMFO1CwYfy9tbvYPf1qlPLekHeSEiHzGDN1ZevI1B6B2Lpbh5sz-2Alk8nqVp3QSToG6g7J8IACYtI-8ndSHW_HqLJQHYlLc81aX3lauEoClh6VuT6CVmW_Xx4cUKMVpistrF-8znERbl2fHvMwv1Zg7ipXuENxJolYFGlM8EwxIGkw0pI51zZPri711NwFfOy9-h2eDMzXGe6HAtPSqjDtyZSZq0lXBUA-dVBNQ9FszxyDqe-1DG0sq2P0nb_-vCoLDptv3s43RpcnC1-vVPWh6J_uR7D1-xVklHsgVJt1t5DSq3mbKql9HradSuMTCoWQ_HywKdLk7-01l5nbWlbqI8WXjxrwgYhdFwe0MF9AUVO9lb9XD9JQ2Ku-TjaCYawm8_np5i1w2pmP9qSdKH5rttzT12SxPlSXOs3xXe0U6N6BnD2jNsSSlK1ffBnwirm-se3_a7NcLsk-e-_g-lCqznq98vtH9MPoOI=
\ No newline at end of file diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped_expired.json b/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped_expired.json deleted file mode 100644 index 04ec9f30..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped_expired.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "access": { - "token": { - "expires": "2010-06-02T14:47:34Z", - "id": "placeholder", - "tenant": { - "id": "tenant_id1", - "enabled": true, - "description": null, - "name": "tenant_name1" - } - }, - "serviceCatalog": [ - { - "endpoints_links": [], - "endpoints": [ - { - "adminURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", - "region": "regionOne", - "internalURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", - "publicURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a" - } - ], - "type": "volume", - "name": "volume" - }, - { - "endpoints_links": [], - "endpoints": [ - { - "adminURL": "http://127.0.0.1:9292/v1", - "region": "regionOne", - "internalURL": "http://127.0.0.1:9292/v1", - "publicURL": "http://127.0.0.1:9292/v1" - } - ], - "type": "image", - "name": "glance" - }, - { - "endpoints_links": [], - "endpoints": [ - { - "adminURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", - "region": "regionOne", - "internalURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", - "publicURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a" - } - ], - "type": "compute", - "name": "nova" - }, - { - "endpoints_links": [], - "endpoints": [ - { - "adminURL": "http://127.0.0.1:35357/v2.0", - "region": "RegionOne", - "internalURL": "http://127.0.0.1:35357/v2.0", - "publicURL": "http://127.0.0.1:5000/v2.0" - } - ], - "type": "identity", - "name": "keystone" - } - ], - "user": { - "username": "user_name1", - "roles_links": [ - "role1", - "role2" - ], - "id": "user_id1", - "roles": [ - { - "name": "role1" - }, - { - "name": "role2" - } - ], - "name": "user_name1" - } - } -} diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped_expired.pem b/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped_expired.pem deleted file mode 100644 index c3de8bbe..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped_expired.pem +++ /dev/null @@ -1,75 +0,0 @@ ------BEGIN CMS----- -MIINhwYJKoZIhvcNAQcCoIINeDCCDXQCAQExCTAHBgUrDgMCGjCCC5QGCSqGSIb3 -DQEHAaCCC4UEgguBew0KICAgICJhY2Nlc3MiOiB7DQogICAgICAgICJ0b2tlbiI6 -IHsNCiAgICAgICAgICAgICJleHBpcmVzIjogIjIwMTAtMDYtMDJUMTQ6NDc6MzRa -IiwNCiAgICAgICAgICAgICJpZCI6ICJwbGFjZWhvbGRlciIsDQogICAgICAgICAg -ICAidGVuYW50Ijogew0KICAgICAgICAgICAgICAgICJpZCI6ICJ0ZW5hbnRfaWQx -IiwNCiAgICAgICAgICAgICAgICAiZW5hYmxlZCI6IHRydWUsDQogICAgICAgICAg -ICAgICAgImRlc2NyaXB0aW9uIjogbnVsbCwNCiAgICAgICAgICAgICAgICAibmFt -ZSI6ICJ0ZW5hbnRfbmFtZTEiDQogICAgICAgICAgICB9DQogICAgICAgIH0sDQog -ICAgICAgICJzZXJ2aWNlQ2F0YWxvZyI6IFsNCiAgICAgICAgICAgIHsNCiAgICAg -ICAgICAgICAgICAiZW5kcG9pbnRzX2xpbmtzIjogW10sDQogICAgICAgICAgICAg -ICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAg -ICAgICAgICAgICAgICAgICAgImFkbWluVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6 -ODc3Ni92MS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIsDQogICAg -ICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSIsDQogICAg -ICAgICAgICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4w -LjAuMTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwN -CiAgICAgICAgICAgICAgICAgICAgICAgICJwdWJsaWNVUkwiOiAiaHR0cDovLzEy -Ny4wLjAuMTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdh -Ig0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgXSwNCiAg -ICAgICAgICAgICAgICAidHlwZSI6ICJ2b2x1bWUiLA0KICAgICAgICAgICAgICAg -ICJuYW1lIjogInZvbHVtZSINCiAgICAgICAgICAgIH0sDQogICAgICAgICAgICB7 -DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtdLA0KICAgICAg -ICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAgIHsN -CiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJodHRwOi8vMTI3 -LjAuMC4xOjkyOTIvdjEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lv -biI6ICJyZWdpb25PbmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVy -bmFsVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5Mi92MSIsDQogICAgICAgICAg -ICAgICAgICAgICAgICAicHVibGljVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5 -Mi92MSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIF0s -DQogICAgICAgICAgICAgICAgInR5cGUiOiAiaW1hZ2UiLA0KICAgICAgICAgICAg -ICAgICJuYW1lIjogImdsYW5jZSINCiAgICAgICAgICAgIH0sDQogICAgICAgICAg -ICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtdLA0KICAg -ICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAg -IHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJodHRwOi8v -MTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2 -NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lv -bk9uZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAi -aHR0cDovLzEyNy4wLjAuMTo4Nzc0L3YxLjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBm -Y2Y4OWJiNjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInB1YmxpY1VS -TCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVl -OGE2MGZjZjg5YmI2NjE3YSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAg -ICAgICAgICAgIF0sDQogICAgICAgICAgICAgICAgInR5cGUiOiAiY29tcHV0ZSIs -DQogICAgICAgICAgICAgICAgIm5hbWUiOiAibm92YSINCiAgICAgICAgICAgIH0s -DQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5r -cyI6IFtdLA0KICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAg -ICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVS -TCI6ICJodHRwOi8vMTI3LjAuMC4xOjM1MzU3L3YyLjAiLA0KICAgICAgICAgICAg -ICAgICAgICAgICAgInJlZ2lvbiI6ICJSZWdpb25PbmUiLA0KICAgICAgICAgICAg -ICAgICAgICAgICAgImludGVybmFsVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6MzUz -NTcvdjIuMCIsDQogICAgICAgICAgICAgICAgICAgICAgICAicHVibGljVVJMIjog -Imh0dHA6Ly8xMjcuMC4wLjE6NTAwMC92Mi4wIg0KICAgICAgICAgICAgICAgICAg -ICB9DQogICAgICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICAgICAidHlwZSI6 -ICJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAia2V5c3RvbmUi -DQogICAgICAgICAgICB9DQogICAgICAgIF0sDQogICAgICAgICJ1c2VyIjogew0K -ICAgICAgICAgICAgInVzZXJuYW1lIjogInVzZXJfbmFtZTEiLA0KICAgICAgICAg -ICAgInJvbGVzX2xpbmtzIjogWw0KICAgICAgICAgICAgICAgICJyb2xlMSIsDQog -ICAgICAgICAgICAgICAgInJvbGUyIg0KICAgICAgICAgICAgXSwNCiAgICAgICAg -ICAgICJpZCI6ICJ1c2VyX2lkMSIsDQogICAgICAgICAgICAicm9sZXMiOiBbDQog -ICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJy -b2xlMSINCiAgICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgIHsNCiAg -ICAgICAgICAgICAgICAgICAgIm5hbWUiOiAicm9sZTIiDQogICAgICAgICAgICAg -ICAgfQ0KICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICJuYW1lIjogInVzZXJf -bmFtZTEiDQogICAgICAgIH0NCiAgICB9DQp9DQoxggHKMIIBxgIBATCBpDCBnjEK -MAgGA1UEBRMBNTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlT -dW5ueXZhbGUxEjAQBgNVBAoTCU9wZW5TdGFjazERMA8GA1UECxMIS2V5c3RvbmUx -JTAjBgkqhkiG9w0BCQEWFmtleXN0b25lQG9wZW5zdGFjay5vcmcxFDASBgNVBAMT -C1NlbGYgU2lnbmVkAgERMAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIBALYxBjRE -hecjo98fUdki3cwcpGU8zY8XHQa4x15WGkPxkI1HwSYaId/WjrOWP2CxmT3vVe7Z -lqV2a0YmdPx9zdDm09VmoiZr3HxYaNzXztT817dECYINCgz33EnansIyPHG2hjOR -4Gt7R26MXf+AIRiCNuCFZPnHI1pfCbwuky9/iBokvE9mThA+bVrUPZd/2+jp4s3B -n3+fbC+FCoZ5t522wGgEtVyMNvC90Wvvuf2mx7baXNo4/0ZG8C86lT+qmMe22zlf -+DxmJl149p419zdv6rzTU7p2OeTBnkdw1GsEqKyvtHYxzAjLYjiJo6jyaERXBaLm -/J7ZRSBmhHoLuWk= ------END CMS----- diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped_expired.pkiz b/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped_expired.pkiz deleted file mode 100644 index 766b4cdd..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_token_scoped_expired.pkiz +++ /dev/null @@ -1 +0,0 @@ -PKIZ_eJylVtlyozgUfddXzHuqK2xOzCObMdiSzW7pzUCMwchLbNavH4GT6kmnM5OZcZWrQEhH555z75V-_GA_1TAt9IcGveHlB4CWNW8cbC9OxNrXCVKcRDuxsWuhaeqTpCmO0Wq-Mlez4FXPoGYO44lkat7F9KxYBLpjzJUtG4ynRpZFzy-dvccCKhMR5qtcfbaO7PlIzlgIdbxx97EpH63ilEXiNY_p7AaIZz1Zmi3EQsvHUZAvNSUn0eSQmPI5Prr9-2QcubdtNAmDQ8OAlXw7d7lEP9Vg2Rsd6qRmWSgV9E8S6hNhKeJ22WMOF4RCgeRYgDzsnR5FgYR93BCK6Eovc1xgAUA_3Vt5k1lHuyRCWcf5yKgjUXqOhck6pndWbHeObOwKR-0HFmCg8X9YgIHGTxYqj2l7xnzo-drI5JTO3WaVT2voW-K4gSa1qyITUY_rtDBqgAo3RxT3hNoF7oMe6ZAn_n6PCpViAUuryM5RgVskGPku5K4MlHvZqOUgrnUkNYjn4Y05MXwoY-o2sVBW6RztYrOstncr482GLZzfbXtz7RibswoLQQ7-rW2_6DUBsDh0g2D_1QnwFfJH4K_FBR_VPXQr3xrU_SwYLW84SssRkIYVmav1wAgkvHxlD69Jx5Bnt3TnNRmrB0aTf1s4qVNqfJni4JtiDcnFjcnFvP-r9eCfvB92Tmh43EZydff-TeiDXA32AxbnQKlM6GQfz76Tgc6gUQW9qYBMSwCkYGQoKpAPOdiH5co0BGiSghTZBFNLQIUh4nuiNWlkM73Qt4rpt_H-Llzwt7lOUR1vVD41PzeajdCeY3rrwWgHz8tLjbWvQQfWlUZ6QjhJRLd-z8Kv0h18w8Ke6cOjThZgLjW_pvzggvfd7vM7cPAZ_btNJWigrtQgLSw2YMsbb1jsThLzTYPILVm853R--FLAQQswCPi2uGbCjdnGaqF8matnloHjJKuwGugrN6hj9rcD6DtPSE-eYO9uwZ02243OqnSgzDoP223PwijJ-O52aRQM9v4ssPf5M7kCwyC8Z9qBbFCR0LJJzbemYk742GyGb2dy14MbwFkYu23ktNaRu9fC28eG9bmCRPs6Nllt5LY8xJ5u2NGW35klVL6yTT70S8A8ZQuC95Y2PHdWyf1COeyZrbuxqfrvFTqAwRwMKB8ayDvg8VMn7tj5WcL83bER9K7BV7uwOEdLxzBK-Ux0Vi8bXobYUjt2zCsJ1gA7_5ts6zQZkVqtUCw1Q6GqBL7iB63WK_b9HftKGfrQuTaag_XQcSyjsXXHNzwAVcVU-MBQW2gHYljFx1JgKVxC12oMZZy8MJpynZhhFYguuztcW8NX1nfgqw8041a-bBDHaoHZGTRW89fbykGd7ckr2ZR9arIWFqj1AJTcgapYtI8Auk5jZONOutHcfBK11JqhM2GAhEVkfLjeKEjNDpf9ITflhlNZ-DOgKB67B2niTXTXpH1IYeWIT09VZWNhm5pu_7LFotenk40hKN5tMWmeLuGz5F_p9Lw8CZct2Exj5Vhc1ig3oPTgy6G0cGOnnYclRPPLjp6a5elZauAxWJk7U3pep74japd2cbW6ykoJIP5aWuX7hwdztjNlszcnrfuwmnC8LJSzZ11Osktpha621jm0Jdw6epycXy3yWK5odqWiC66rXBCk-CJeBffxOaJazV2mNJhOt4l2eFXI3o0Wt2oBV3SWRiePSlr56B_UY9dRTz2YEvCb9bK-zFdQrRHO5cuZqx5fIiHT1CZ3-SQq7Cpz7MNRvjxORbSpQnmy7B7YRZI_16hsr-B6Pb2IF9vVHjxzkSbJLjhEi9h4DOIVBeNd1ED6z3vpnxbOkgI=
\ No newline at end of file diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_token_unscoped.json b/keystonemiddleware-moon/examples/pki/cms/auth_token_unscoped.json deleted file mode 100644 index 41566888..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_token_unscoped.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "access": { - "token": { - "expires": "2112-08-17T15:35:34Z", - "id": "01e032c996ef4406b144335915a41e79" - }, - "serviceCatalog": {}, - "user": { - "username": "user_name1", - "roles_links": [], - "id": "c9c89e3be3ee453fbf00c7966f6d3fbd", - "roles": [ - { - "name": "role1" - }, - { - "name": "role2" - } - ], - "name": "user_name1" - } - } -} diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_token_unscoped.pem b/keystonemiddleware-moon/examples/pki/cms/auth_token_unscoped.pem deleted file mode 100644 index 6855221f..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_token_unscoped.pem +++ /dev/null @@ -1,25 +0,0 @@ ------BEGIN CMS----- -MIIERgYJKoZIhvcNAQcCoIIENzCCBDMCAQExCTAHBgUrDgMCGjCCAlMGCSqGSIb3 -DQEHAaCCAkQEggJAew0KICAgICJhY2Nlc3MiOiB7DQogICAgICAgICJ0b2tlbiI6 -IHsNCiAgICAgICAgICAgICJleHBpcmVzIjogIjIxMTItMDgtMTdUMTU6MzU6MzRa -IiwNCiAgICAgICAgICAgICJpZCI6ICIwMWUwMzJjOTk2ZWY0NDA2YjE0NDMzNTkx -NWE0MWU3OSINCiAgICAgICAgfSwNCiAgICAgICAgInNlcnZpY2VDYXRhbG9nIjog -e30sDQogICAgICAgICJ1c2VyIjogew0KICAgICAgICAgICAgInVzZXJuYW1lIjog -InVzZXJfbmFtZTEiLA0KICAgICAgICAgICAgInJvbGVzX2xpbmtzIjogW10sDQog -ICAgICAgICAgICAiaWQiOiAiYzljODllM2JlM2VlNDUzZmJmMDBjNzk2NmY2ZDNm -YmQiLA0KICAgICAgICAgICAgInJvbGVzIjogWw0KICAgICAgICAgICAgICAgIHsN -CiAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiAicm9sZTEiDQogICAgICAgICAg -ICAgICAgfSwNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAg -ICJuYW1lIjogInJvbGUyIg0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAg -IF0sDQogICAgICAgICAgICAibmFtZSI6ICJ1c2VyX25hbWUxIg0KICAgICAgICB9 -DQogICAgfQ0KfQ0KMYIByjCCAcYCAQEwgaQwgZ4xCjAIBgNVBAUTATUxCzAJBgNV -BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQK -EwlPcGVuU3RhY2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZr -ZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZAIBETAH -BgUrDgMCGjANBgkqhkiG9w0BAQEFAASCAQAXNWXYv3q2EcEjigKDJEOvnKBGTHeV -o9iwYmtdJ2kKtbuZiSGOcWymxNtv//IPMmNDWZ/uwDZt37YdPwCMRJa79h6dastD -5slEZGMxgFekm/1yqpV2F7xGqGIED2rNTeBlVnYS6ZOL8hCqekPb1OqXZ3vDaHtQ -rrBzNP8RbWS4MyUoVZtSEYANjJVp/zou/pYASml9iNPPKrl2xRgYuzaAirVIiTZt -QZY4LQYnHdVBLTZ0fQQugohTba789ix0U79ReQrIOqnBD3OnmN0uRovu5s1HYyre -c67FixOpNgA4IBFsqYG2feP6ZF1zCmAaRYX4LpprZLGzg/aPHxqjXGsT ------END CMS----- diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_token_unscoped.pkiz b/keystonemiddleware-moon/examples/pki/cms/auth_token_unscoped.pkiz deleted file mode 100644 index 13c5e40c..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_token_unscoped.pkiz +++ /dev/null @@ -1 +0,0 @@ -PKIZ_eJx9VMmSozgQvfMVfa-oMAbbVRzmIAlZCFvQGLHewAs72MaY5esHuzt65tSKUEiZkS_z5RL5-TkfiAk1fiBmv4RPgVGq7kCg75qQps-jAawjamYd4QiBwUHAwgPiQIOJc1cThkg-67lDkH0jNo1lQbWwBqJZaQc4SXB2HvU0kIzyKLPMzOAXred_HV4DyVUD_5DGRKlp3iRnWWwp0kUhlh5lnNEN1dos9NM-8vXyOM4yoiPjeNxzsNpzLLsqXpo5e13Ry-gLfA0R3QizYc88p2eTnpu8kEIvEA0VSEGO55dNBi8Gw8PibCObtq7sEchO_szqd1DhWClt6BuXmJRd9It27Nt9Qqt1GnvOLP8GlEoXeMuS2e_oYywNb6YC3T6-_m_8dshxdpmdzPV4g14501p_xsQZab08_WEx44S_RHnnOL-56bGV6TlTUDlT6DmiwY0qqIKeESYLJg-kMA8LJoVZiHTl4otDkmi7ub1wSCgEHMGrimCd4x0DCQFLB8MDgwbHewYKIrwVKUOuywY0AR0mhgtBwkFhQHagPQaB6lqWhvuSn7x1d_bDuZXOgHNgvWwFCBqOHKUPvTU_kW0eTfjAwPc7EhoYtSV3fZQPz7hyBp2DHCbFLS0yovQiRBb2hG31KM--IcbSurTI29H0djSun8fqOGxVYP9ixThaGmVMgsSRyjqu3AIk-CAwcCTQbk3Q04gB8c-IzhMKgeUAONcCbO8atS73i3mAGF0iWEaZWKcHN11FAj1_r8a1F5ZGKDWGyD468ZlOstqwRb1jnp5-5fK-M-cJvXSTbE6Vxqs4Sg9dUQdNcSuE_Cfc3JzH-fqxLruP-wpoqpNGV9iP8lMuzsmGtUkY1PCeUyJHQ7Nl2vfJslSkKOoJWpOw21fD1JDztsjbyx27Hw95icVWut-JOC6a_SUK-k1AmpUrNtpjm3T5osNNEn608g1lsSOgZBVvppgUhx2vm-5ate56rZynjSgam_tr6J7awn9y4n5Lth48bJRdy6Wx8m52ju7IE1Z-G92-ldZegIXrbm6gHJuBT63Ss1g3be9i5-ZTVotYxMm5WNrPXaB2_PpzsPt_hPdKwYb633r5FzKfcIU=
\ No newline at end of file diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_revoked.json b/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_revoked.json deleted file mode 100644 index c5dc01a9..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_revoked.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "token": { - "catalog": [ - { - "endpoints": [ - { - "adminURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", - "region": "regionOne", - "internalURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", - "publicURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a" - } - ], - "endpoints_links": [], - "type": "volume", - "name": "volume" - }, - { - "endpoints": [ - { - "adminURL": "http://127.0.0.1:9292/v1", - "region": "regionOne", - "internalURL": "http://127.0.0.1:9292/v1", - "publicURL": "http://127.0.0.1:9292/v1" - } - ], - "endpoints_links": [], - "type": "image", - "name": "glance" - }, - { - "endpoints": [ - { - "adminURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", - "region": "regionOne", - "internalURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", - "publicURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a" - } - ], - "endpoints_links": [], - "type": "compute", - "name": "nova" - }, - { - "endpoints": [ - { - "adminURL": "http://127.0.0.1:35357/v3", - "region": "RegionOne", - "internalURL": "http://127.0.0.1:35357/v3", - "publicURL": "http://127.0.0.1:5000/v3" - } - ], - "endpoints_links": [], - "type": "identity", - "name": "keystone" - } - ], - "expires_at": "2038-01-18T21:14:07Z", - "project": { - "enabled": true, - "description": null, - "name": "tenant_name1", - "id": "tenant_id1", - "domain": { - "id": "domain_id1", - "name": "domain_name1" - } - }, - "user": { - "name": "revoked_username1", - "id": "revoked_user_id1", - "domain": { - "id": "domain_id1", - "name": "domain_name1" - } - }, - "roles": [ - { - "name": "role1" - }, - { - "name": "role2" - } - ], - "methods": [ - "password" - ] - } -} diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_revoked.pem b/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_revoked.pem deleted file mode 100644 index 94a077ba..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_revoked.pem +++ /dev/null @@ -1,76 +0,0 @@ ------BEGIN CMS----- -MIINrQYJKoZIhvcNAQcCoIINnjCCDZoCAQExCTAHBgUrDgMCGjCCC7oGCSqGSIb3 -DQEHAaCCC6sEggunew0KICAgICJ0b2tlbiI6IHsNCiAgICAgICAgImNhdGFsb2ci -OiBbDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50cyI6 -IFsNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAg -ICAgImFkbWluVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3Ni92MS82NGI2ZjNm -YmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIsDQogICAgICAgICAgICAgICAgICAg -ICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSIsDQogICAgICAgICAgICAgICAgICAg -ICAgICAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc2L3YxLzY0 -YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwNCiAgICAgICAgICAgICAg -ICAgICAgICAgICJwdWJsaWNVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc2L3Yx -LzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIg0KICAgICAgICAgICAg -ICAgICAgICB9DQogICAgICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICAgICAi -ZW5kcG9pbnRzX2xpbmtzIjogW10sDQogICAgICAgICAgICAgICAgInR5cGUiOiAi -dm9sdW1lIiwNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJ2b2x1bWUiDQogICAg -ICAgICAgICB9LA0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICJlbmRw -b2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAg -ICAgICAgICAgICJhZG1pblVSTCI6ICJodHRwOi8vMTI3LjAuMC4xOjkyOTIvdjEi -LA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJyZWdpb25PbmUi -LA0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVybmFsVVJMIjogImh0dHA6 -Ly8xMjcuMC4wLjE6OTI5Mi92MSIsDQogICAgICAgICAgICAgICAgICAgICAgICAi -cHVibGljVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5Mi92MSINCiAgICAgICAg -ICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIF0sDQogICAgICAgICAgICAg -ICAgImVuZHBvaW50c19saW5rcyI6IFtdLA0KICAgICAgICAgICAgICAgICJ0eXBl -IjogImltYWdlIiwNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJnbGFuY2UiDQog -ICAgICAgICAgICB9LA0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICJl -bmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAg -ICAgICAgICAgICAgICJhZG1pblVSTCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3NzQv -djEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIsDQogICAgICAg -ICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSIsDQogICAgICAg -ICAgICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4wLjAu -MTo4Nzc0L3YxLjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJiNjYxN2EiLA0K -ICAgICAgICAgICAgICAgICAgICAgICAgInB1YmxpY1VSTCI6ICJodHRwOi8vMTI3 -LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3 -YSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIF0sDQog -ICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtdLA0KICAgICAgICAg -ICAgICAgICJ0eXBlIjogImNvbXB1dGUiLA0KICAgICAgICAgICAgICAgICJuYW1l -IjogIm5vdmEiDQogICAgICAgICAgICB9LA0KICAgICAgICAgICAgew0KICAgICAg -ICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAgIHsN -CiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJodHRwOi8vMTI3 -LjAuMC4xOjM1MzU3L3YzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJyZWdp -b24iOiAiUmVnaW9uT25lIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJpbnRl -cm5hbFVSTCI6ICJodHRwOi8vMTI3LjAuMC4xOjM1MzU3L3YzIiwNCiAgICAgICAg -ICAgICAgICAgICAgICAgICJwdWJsaWNVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo1 -MDAwL3YzIg0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAg -XSwNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzX2xpbmtzIjogW10sDQogICAg -ICAgICAgICAgICAgInR5cGUiOiAiaWRlbnRpdHkiLA0KICAgICAgICAgICAgICAg -ICJuYW1lIjogImtleXN0b25lIg0KICAgICAgICAgICAgfQ0KICAgICAgICBdLA0K -ICAgICAgICAiZXhwaXJlc19hdCI6ICIyMDM4LTAxLTE4VDIxOjE0OjA3WiIsDQog -ICAgICAgICJwcm9qZWN0Ijogew0KICAgICAgICAgICAgImVuYWJsZWQiOiB0cnVl -LA0KICAgICAgICAgICAgImRlc2NyaXB0aW9uIjogbnVsbCwNCiAgICAgICAgICAg -ICJuYW1lIjogInRlbmFudF9uYW1lMSIsDQogICAgICAgICAgICAiaWQiOiAidGVu -YW50X2lkMSIsDQogICAgICAgICAgICAiZG9tYWluIjogew0KICAgICAgICAgICAg -ICAgICJpZCI6ICJkb21haW5faWQxIiwNCiAgICAgICAgICAgICAgICAibmFtZSI6 -ICJkb21haW5fbmFtZTEiDQogICAgICAgICAgICB9DQogICAgICAgIH0sDQogICAg -ICAgICJ1c2VyIjogew0KICAgICAgICAgICAgIm5hbWUiOiAicmV2b2tlZF91c2Vy -bmFtZTEiLA0KICAgICAgICAgICAgImlkIjogInJldm9rZWRfdXNlcl9pZDEiLA0K -ICAgICAgICAgICAgImRvbWFpbiI6IHsNCiAgICAgICAgICAgICAgICAiaWQiOiAi -ZG9tYWluX2lkMSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAiZG9tYWluX25h -bWUxIg0KICAgICAgICAgICAgfQ0KICAgICAgICB9LA0KICAgICAgICAicm9sZXMi -OiBbDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgIm5hbWUiOiAicm9s -ZTEiDQogICAgICAgICAgICB9LA0KICAgICAgICAgICAgew0KICAgICAgICAgICAg -ICAgICJuYW1lIjogInJvbGUyIg0KICAgICAgICAgICAgfQ0KICAgICAgICBdLA0K -ICAgICAgICAibWV0aG9kcyI6IFsNCiAgICAgICAgICAgICJwYXNzd29yZCINCiAg -ICAgICAgXQ0KICAgIH0NCn0NCjGCAcowggHGAgEBMIGkMIGeMQowCAYDVQQFEwE1 -MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVN1bm55dmFsZTES -MBAGA1UEChMJT3BlblN0YWNrMREwDwYDVQQLEwhLZXlzdG9uZTElMCMGCSqGSIb3 -DQEJARYWa2V5c3RvbmVAb3BlbnN0YWNrLm9yZzEUMBIGA1UEAxMLU2VsZiBTaWdu -ZWQCAREwBwYFKw4DAhowDQYJKoZIhvcNAQEBBQAEggEAwFCjl3GSGrlil3cLwS11 -1gtc6K3gBSMbc7LviIFk4KDRBvHWEHT1fs/Q4T0Y12P97Uaxh47f2sNgdbsDKSE8 -K/KCeMy+0I7Eo3iDoXKcIRPux1sXFhOX36qLPpY4eWd3Q77MiUPng+78qA3AMPPl -wEcfb2OaYsWmVi9jGsDfAvksF/WO5dg+G9m2l+zcboIJswsKbBJnM5bn8EDHk7bg -YuMnOzqZsoymr6sehOPQ8QTV6kIj1w/gmtkaIH2QtBo78hCqjZ+cFeYy4zDk2HJg -Mf7PDm0hx1G0hJMVxdNzkWoFvLreTzRselsrXrx8Gejof92JyKuBjZq0kBpphOHG -6w== ------END CMS----- diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_revoked.pkiz b/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_revoked.pkiz deleted file mode 100644 index 67823fd3..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_revoked.pkiz +++ /dev/null @@ -1 +0,0 @@ -PKIZ_eJylVsmSozgQvesr5l7R0Symyhz6wG5oS5jFgLixtDEY7PLC-vUjYXd31Sw1PTOOcNgIZerle7no0yfykTXDRL8p0KMPnwA0zdWywNbXU2zuuwxJTqacyNpiUhRZXCqSow2KL63kYntRC6gYFVnfLQ3FOxuemfJAdbSVlNBFSSuK6PpttJiUu9VpaT6bq2uZrawuaYIqV-7PcSjscTPU8fzsjiAPt1dTsQ4px-6TcFHapfxiNsI-Dbfkv1TGhnjDYd1G3Lw2mGVfmE19MKsT-XU7kIb6a1qLr7GqlTuPvvxpnBtBi0OBeW_s1hmHxiSSmSQUW0A9pcfgmipvPB_dOm30NtffOkb73NCvKZdRlCkJlThna3A3iLt0Fdxiz6ThEGO3T7m6zVfw--Z9bLAEaeD5NHbFOuUrt7fLZQegb_LrSmqhshjsquDRhLu80jpUuSVq8BQ3VoWn7YRUyMb-fo8qucEcXtihVaIKDwBxWrlWpDJrgiON6Y7IqmOu7tKD2D5QvaYkrIzyo79HASiM_4MCUBg_UKyCMjXqKggseJdpz-Qr6Xk9LgdYZfSAfl1pz7aa8agUOegtOYAMk4srck6DKuRDBk5BbRsaB424iqtCwI3JoUrjsWeJEVXj6AqZ8ZC5Ea8kkdj6rm_Qxiu5S4juGSteye8lG0ms-i2nMn6X7Y4sv5L8qCg_4N_K9p6vwwhs36SE_WclwN95fuf4A3LBO3Z9U4Azu38mLAnZfcxtZ4ekIg-ZIVJEE4i44TVtbhP1HLKsuFbeV2PaiBz-IMXBr5FFk8uhIbVU-7fSg4-1n08e4zB_TbnFjOg70T4nzPIDUsItqfuRlO_1lzJQoRwthvWEGVzFDYBcXGIOsnByJhRuF9jHfdygxlbrElfkjZ_v50Q7yixpZa-Y_aVi-ut4_ypc8FGuY068kRxg_txo0I7kRZvwsARUjihirrTjEh5oV6LwLnFUT7nxIwv_Nt3BP0tI-dnyax5Pdy4eKV7ONh64SyRs0uaeZbQa44hW3hBsD_09C1cuk6mnbj1pIxqpIsS5f5oIJyxAI5FlnGH2eWiRMkb_ZMhCVepnREc2B_TUfFX3j9hfYzILcqNmvn1A3J03Nqe2ZLAETGKIh3vzIKPM0KeMz7usccpZlSZYZEY9xhHa4ciZkcFKmmyF6aHHDMDWnZHAGpB66hF7evQF8RpH8N0AefSILjXIhDr-VA08oI8pN9Sw_J4LwRRH5mNOut08_h7D9o3U8zwFhPXdvOhrDxWcPwzV-kD7A333xpiEFHcJFxxAxNPT7jDho3XFyvtNjz074pzAZ8WdbyhSduqLYmUAqdBkaBoH8v0GnVOvSFgNHEfXeo2FzrVXnPnZ0Hor2E7aGkoHQ2K3miJDxWG0AWiV5MgFCmQp85UAsWkjCDkpbRKSB2XpvnkPLZ-X67RGDA7RBbpar_az4zXQ-v36R977Wg0V-OP6Qm4vluTikIQhZDwhswmklDo63h2tG3EE8aRtoWzOJ0kDXG-54BqXsp-EeRuHjiKR0-Qe61_7hSrtT73qvL1PaTKQHXo30qTi8A1d3G3mrSX5pubCKREZlaxEeZF0qnqe3Gq0mmcvvB763tW0W69v-s-RDqpRgZnLY1x4BMViY3G8gDiW3cTRsolW2uc0MOVLyz_fal5dtTiSq7TstR2f2eNmoWKwQVmIxW25t-zzywnrqrEbO_VsuJd1bWtQ1vTyKWg3ngtbQfl80c8Xd0wydeAbqJRPVxcMHty3SBcuQd0vfX_h9ofRwuYUcmWwGJJ8SL7mJRwCzcebvLt5SqHwT_LGzgaxZ3aFBBzm5Ww_7faNib7K_nR4sXH7ujkdrPPlZSva8pNYtf1zPY0o6XtJv52T6LwNfIlbdkJvSQxA-XNVOzJ7Vlipvh6Dk_2UC0vmcxS3tiN9-QLmC62G1J-X298BCSOhiw==
\ No newline at end of file diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_scoped.json b/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_scoped.json deleted file mode 100644 index 90207457..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_scoped.json +++ /dev/null @@ -1,123 +0,0 @@ -{ - "token": { - "audit_ids": [ - "SLIXlXQUQZWUi9VJrqdXqA" - ], - "methods": [ - "password" - ], - "roles": [ - { - "name": "role1" - }, - { - "name": "role2" - } - ], - "expires_at": "2038-01-18T21:14:07Z", - "project": { - "id": "tenant_id1", - "domain": { - "id": "domain_id1", - "name": "domain_name1" - }, - "enabled": true, - "description": null, - "name": "tenant_name1" - }, - "catalog": [ - { - "endpoints": [ - { - "interface": "admin", - "url": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", - "region": "regionOne" - }, - { - "interface": "internal", - "url": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", - "region": "regionOne" - }, - { - "interface": "public", - "url": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", - "region": "regionOne" - } - ], - "type": "volume", - "name": "volume" - }, - { - "endpoints": [ - { - "interface": "admin", - "url": "http://127.0.0.1:9292/v1", - "region": "regionOne" - }, - { - "interface": "internal", - "url": "http://127.0.0.1:9292/v1", - "region": "regionOne" - }, - { - "interface": "public", - "url": "http://127.0.0.1:9292/v1", - "region": "regionOne" - } - ], - "type": "image", - "name": "glance" - }, - { - "endpoints": [ - { - "interface": "admin", - "url": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", - "region": "regionOne" - }, - { - "interface": "internal", - "url": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", - "region": "regionOne" - }, - { - "interface": "public", - "url": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", - "region": "regionOne" - } - ], - "type": "compute", - "name": "nova" - }, - { - "endpoints": [ - { - "interface": "admin", - "url": "http://127.0.0.1:35357/v3", - "region": "RegionOne" - }, - { - "interface": "internal", - "url": "http://127.0.0.1:35357/v3", - "region": "RegionOne" - }, - { - "interface": "public", - "url": "http://127.0.0.1:5000/v3", - "region": "RegionOne" - } - ], - "type": "identity", - "name": "keystone" - } - ], - "user": { - "domain": { - "id": "domain_id1", - "name": "domain_name1" - }, - "name": "user_name1", - "id": "user_id1" - } - } -} diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_scoped.pem b/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_scoped.pem deleted file mode 100644 index e83e7a09..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_scoped.pem +++ /dev/null @@ -1,100 +0,0 @@ ------BEGIN CMS----- -MIISOAYJKoZIhvcNAQcCoIISKTCCEiUCAQExDTALBglghkgBZQMEAgEwghA9Bgkq -hkiG9w0BBwGgghAuBIIQKnsNCiAgICAidG9rZW4iOiB7DQogICAgICAgICJhdWRp -dF9pZHMiOiBbDQogICAgICAgICAgICAiU0xJWGxYUVVRWldVaTlWSnJxZFhxQSIN -CiAgICAgICAgXSwNCiAgICAgICAgIm1ldGhvZHMiOiBbDQogICAgICAgICAgICAi -cGFzc3dvcmQiDQogICAgICAgIF0sDQogICAgICAgICJyb2xlcyI6IFsNCiAgICAg -ICAgICAgIHsNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJyb2xlMSINCiAgICAg -ICAgICAgIH0sDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgIm5hbWUi -OiAicm9sZTIiDQogICAgICAgICAgICB9DQogICAgICAgIF0sDQogICAgICAgICJl -eHBpcmVzX2F0IjogIjIwMzgtMDEtMThUMjE6MTQ6MDdaIiwNCiAgICAgICAgInBy -b2plY3QiOiB7DQogICAgICAgICAgICAiaWQiOiAidGVuYW50X2lkMSIsDQogICAg -ICAgICAgICAiZG9tYWluIjogew0KICAgICAgICAgICAgICAgICJpZCI6ICJkb21h -aW5faWQxIiwNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJkb21haW5fbmFtZTEi -DQogICAgICAgICAgICB9LA0KICAgICAgICAgICAgImVuYWJsZWQiOiB0cnVlLA0K -ICAgICAgICAgICAgImRlc2NyaXB0aW9uIjogbnVsbCwNCiAgICAgICAgICAgICJu -YW1lIjogInRlbmFudF9uYW1lMSINCiAgICAgICAgfSwNCiAgICAgICAgImNhdGFs -b2ciOiBbDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50 -cyI6IFsNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAg -ICAgICAgImludGVyZmFjZSI6ICJhZG1pbiIsDQogICAgICAgICAgICAgICAgICAg -ICAgICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3Ni92MS82NGI2ZjNmYmNj -NTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAg -ICAicmVnaW9uIjogInJlZ2lvbk9uZSINCiAgICAgICAgICAgICAgICAgICAgfSwN -CiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAg -ImludGVyZmFjZSI6ICJpbnRlcm5hbCIsDQogICAgICAgICAgICAgICAgICAgICAg -ICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3Ni92MS82NGI2ZjNmYmNjNTM0 -MzVlOGE2MGZjZjg5YmI2NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAi -cmVnaW9uIjogInJlZ2lvbk9uZSINCiAgICAgICAgICAgICAgICAgICAgfSwNCiAg -ICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgImlu -dGVyZmFjZSI6ICJwdWJsaWMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInVy -bCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3NzYvdjEvNjRiNmYzZmJjYzUzNDM1ZThh -NjBmY2Y4OWJiNjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lv -biI6ICJyZWdpb25PbmUiDQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAg -ICAgICAgICBdLA0KICAgICAgICAgICAgICAgICJ0eXBlIjogInZvbHVtZSIsDQog -ICAgICAgICAgICAgICAgIm5hbWUiOiAidm9sdW1lIg0KICAgICAgICAgICAgfSwN -CiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzIjogWw0K -ICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAi -aW50ZXJmYWNlIjogImFkbWluIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1 -cmwiOiAiaHR0cDovLzEyNy4wLjAuMTo5MjkyL3YxIiwNCiAgICAgICAgICAgICAg -ICAgICAgICAgICJyZWdpb24iOiAicmVnaW9uT25lIg0KICAgICAgICAgICAgICAg -ICAgICB9LA0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAg -ICAgICAgICAiaW50ZXJmYWNlIjogImludGVybmFsIiwNCiAgICAgICAgICAgICAg -ICAgICAgICAgICJ1cmwiOiAiaHR0cDovLzEyNy4wLjAuMTo5MjkyL3YxIiwNCiAg -ICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVnaW9uT25lIg0KICAg -ICAgICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgICAgICB7DQogICAg -ICAgICAgICAgICAgICAgICAgICAiaW50ZXJmYWNlIjogInB1YmxpYyIsDQogICAg -ICAgICAgICAgICAgICAgICAgICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5 -Mi92MSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lv -bk9uZSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIF0s -DQogICAgICAgICAgICAgICAgInR5cGUiOiAiaW1hZ2UiLA0KICAgICAgICAgICAg -ICAgICJuYW1lIjogImdsYW5jZSINCiAgICAgICAgICAgIH0sDQogICAgICAgICAg -ICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAg -ICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVyZmFjZSI6 -ICJhZG1pbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAidXJsIjogImh0dHA6 -Ly8xMjcuMC4wLjE6ODc3NC92MS4xLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODli -YjY2MTdhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVn -aW9uT25lIg0KICAgICAgICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAg -ICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJmYWNlIjogImlu -dGVybmFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1cmwiOiAiaHR0cDov -LzEyNy4wLjAuMTo4Nzc0L3YxLjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJi -NjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJyZWdp -b25PbmUiDQogICAgICAgICAgICAgICAgICAgIH0sDQogICAgICAgICAgICAgICAg -ICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJpbnRlcmZhY2UiOiAicHVi -bGljIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1cmwiOiAiaHR0cDovLzEy -Ny4wLjAuMTo4Nzc0L3YxLjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJiNjYx -N2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJyZWdpb25P -bmUiDQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBdLA0K -ICAgICAgICAgICAgICAgICJ0eXBlIjogImNvbXB1dGUiLA0KICAgICAgICAgICAg -ICAgICJuYW1lIjogIm5vdmEiDQogICAgICAgICAgICB9LA0KICAgICAgICAgICAg -ew0KICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAg -ICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJpbnRlcmZhY2UiOiAi -YWRtaW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgInVybCI6ICJodHRwOi8v -MTI3LjAuMC4xOjM1MzU3L3YzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJy -ZWdpb24iOiAiUmVnaW9uT25lIg0KICAgICAgICAgICAgICAgICAgICB9LA0KICAg -ICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAiaW50 -ZXJmYWNlIjogImludGVybmFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1 -cmwiOiAiaHR0cDovLzEyNy4wLjAuMTozNTM1Ny92MyIsDQogICAgICAgICAgICAg -ICAgICAgICAgICAicmVnaW9uIjogIlJlZ2lvbk9uZSINCiAgICAgICAgICAgICAg -ICAgICAgfSwNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAg -ICAgICAgICAgImludGVyZmFjZSI6ICJwdWJsaWMiLA0KICAgICAgICAgICAgICAg -ICAgICAgICAgInVybCI6ICJodHRwOi8vMTI3LjAuMC4xOjUwMDAvdjMiLA0KICAg -ICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJSZWdpb25PbmUiDQogICAg -ICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBdLA0KICAgICAgICAg -ICAgICAgICJ0eXBlIjogImlkZW50aXR5IiwNCiAgICAgICAgICAgICAgICAibmFt -ZSI6ICJrZXlzdG9uZSINCiAgICAgICAgICAgIH0NCiAgICAgICAgXSwNCiAgICAg -ICAgInVzZXIiOiB7DQogICAgICAgICAgICAiZG9tYWluIjogew0KICAgICAgICAg -ICAgICAgICJpZCI6ICJkb21haW5faWQxIiwNCiAgICAgICAgICAgICAgICAibmFt -ZSI6ICJkb21haW5fbmFtZTEiDQogICAgICAgICAgICB9LA0KICAgICAgICAgICAg -Im5hbWUiOiAidXNlcl9uYW1lMSIsDQogICAgICAgICAgICAiaWQiOiAidXNlcl9p -ZDEiDQogICAgICAgIH0NCiAgICB9DQp9DQoxggHOMIIBygIBATCBpDCBnjEKMAgG -A1UEBRMBNTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTdW5u -eXZhbGUxEjAQBgNVBAoTCU9wZW5TdGFjazERMA8GA1UECxMIS2V5c3RvbmUxJTAj -BgkqhkiG9w0BCQEWFmtleXN0b25lQG9wZW5zdGFjay5vcmcxFDASBgNVBAMTC1Nl -bGYgU2lnbmVkAgERMAsGCWCGSAFlAwQCATANBgkqhkiG9w0BAQEFAASCAQBBvzoh -0iSPMQhuRCAtTG3cPhyewvf554MPjbGQnu8mYmmfyxl7gMmWkTAmyckAsSv4mS6/ -4SQj9WCn4T1lFkhUz7WWjCwt6fWWp3mzF8Nl/kMsJKDwlxDGbPzsyewXIUsw11sz -q/Qxs7qGxQ1vYWnaWQ3hC3oZw7cOswKRJicdP439iVPvfqR9CDbK55sPP+ewZRgQ -YJ3Uc/xDizxepudFJj9+VHKceA37/sVK0ataNe2uHLHwVBYPwOppMckP169QBw8x -QYh9h+kcOAyZ5psiUzCpLKnlMiYDrVcTGxnTeiVHxKXxj/MERNhR1Y4lEr0ZHJ+p -Y6p3FBP2VUCefaRh ------END CMS----- diff --git a/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_scoped.pkiz b/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_scoped.pkiz deleted file mode 100644 index 74f8f632..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/auth_v3_token_scoped.pkiz +++ /dev/null @@ -1 +0,0 @@ -PKIZ_eJy9V0tzozoT3etX3H1qKoBNEhbfgpexMJKNjXloZyDmJWwnNs9f_wnsSWYyuXUzc6uuq7yQQN2n-_RpNd--sZ-iGxD_paLNsPgGEISmIwfm4khgWkdYtiP1yPZWjqqqTqHKtt5qjmwpCU3SIlGIjXQ50ZskiddKUryAtMgMqeEUpTEStqkqEM5Xh3MWG9Ir8abZMlMeYcnT2EhrMkfDOoQHJY0meBJOzAJAyp2hanah0NKogw9wdmEHxDT0tuxlOYtK6UwcPdtvmuS5M6vA4ynMjwk8mHVobDsAD3xsqXJG_LTZ-SaNeCmNVWZIhR3S0NRy5NZy9KmrwXaZ69wylydeBgenDTP-AoiHucEis16EAp_u3mDTYvRUruvQm51CKp2IpmeDs7CcXchmcMJCuB4S9-PmDSosXQbVPBPPHoxx0cGlw8HduJZZfobnIucLtABoM8L5IbY1ZcaqeCaNe7fnBfFxHpW0iQ1ahxnzboh8aLQSGCwHwowLvLYmb0l0KzJXaoaMe08srZjnjpSz_AY_JQZ_AuE1IXxUNiO83XzNRdqxtnq9w920sXK5Qs5xivtIsCZBa_UBF-SkRAJhjhEPUG_32NtOAydoSInLpUazIGePnDiFWTPQRYlwg83oJl58CgVxFZbbMV-AZf8UsrijkqSBcOV-gE78IS_NmPXYN89XRlIunssPVvfUojyqkDptgJXrD0uN1VUmCWjzJGADCiTHZVDiHDuIQ71Ll4YuIIPkJE_EoIQCzvVJcE1uB66Qpreqcw87T6ocQaTwwCp0fv6Opgw8fGNJ4YOyPQXdNXfgT5P3PXfgj5Lnjvrhnn2FgissUodzdyjPD0X1fd-ULFX5tD7A3xXIF-tDBCgvuiHGr3D-GeXgdzgfKXegiEbK_yMaxX8KEXxGzTUEegm8mI4Hf2hxRGjTsMRvCFkIYhEZ0pCcfjjoTT6BXc6K0KPVFYXbhWPLM4_xfN2AZfZUIwdORsjqlPW9ZIJ7u45zvfqKNsBHcfxuUt8KibWx82cQ_wkh-F35fkQIfpf3j7SDT-TLjfLN9Rrn64xh60lp5kG_7bGGeOKkKc6VMhCC6dIzM4DzoMXC9cL4nrTb1XUtmkKqBjX6w31xWIuRca2HQJAu0dzlwC8SLsU6Lt_uQnZHrJtQYIm-XawfBQVGa976MlxpXxETGkJxIsYCGt8HP8GmP8O-NpFf-sUNAStvFZ7BF5oG84h43DEJd79SCbZ_IOEfHYJPPPJIkxtGZf-JhDcfmyv4IOGCqZPb-Wvxo4x3gitGEzYrvEufjwS3A_9muBjOgF-Hi3evsY9pRH-aE07kKrTR-23AGOhiteC7BYO-33m3xtKZjqPTIJyla9ed7VzePS1dsogOs8KbzxRIeWnvGCqQoymb-eYLNvspCBoF-z8j-9iocqC5tj3TG51H9rlR7XFt6I3pbnvdQnJhyPxWB6qCVJvTWz2XbSXBriJHjupiPixFMWY9goW2QYo8vqymyHQmCg0pZhMNfkVrvQFaM1q29Ca1iE97NmBW7BBFKjLUzYuxgeFEs3VTXgfeOxOuHA6GDpgDgyWrlDrS61ukwNGT3CJrK7hnkinOzosrNq2pMvOmNoEZQAJlb6spMlSQzBngBy-KbG9lNuoqsl45jyd9AeeC-HheWe3ZcDV83l82hJcKyxTugoXTmR29W7ggfMi9NIj3U057PbLunu_O-6Pf76PznSIHxJRq4e7OOIWL7KTwPgcP9f2rd7_dRKUwebBCDmgngUi2KFhknc5gFhThttK4Je6NbWFO4GIz0T3rsfJW4mql2yo1yqqtlZnzjLO21O874K2f7p-3F08ISRVMDf_iXbz5PD_K8sTuT0er8oTnKn5NWsdHyHVR99DQbfas-vv01XjSVsATVN47Wg1furyTLmYXI0p8ob7Xl6tjv6sXjplX6K40Nz4WV013XF_UIgmX3fSurGfTwwJ0j4vLEa_um-eE7-4VWqYvq8eX-zbZTFYPl2htaOZRdlYzh4P_A-M3io619--V_wMk2UFA
\ No newline at end of file diff --git a/keystonemiddleware-moon/examples/pki/cms/revocation_list.der b/keystonemiddleware-moon/examples/pki/cms/revocation_list.der deleted file mode 100644 index e69de29b..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/revocation_list.der +++ /dev/null diff --git a/keystonemiddleware-moon/examples/pki/cms/revocation_list.json b/keystonemiddleware-moon/examples/pki/cms/revocation_list.json deleted file mode 100644 index 2c239e53..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/revocation_list.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "revoked": [ - { - "expires": "2112-08-14T17:58:48Z", - "id": "dc57ea171d2f93e4ff5fa01fe5711f2a" - }, - { - "expires": "2112-08-14T17:58:48Z", - "id": "4948fb46f88c41af90b65213a48baef7" - }, - { - "expires": "2112-08-14T17:58:48Z", - "id": "dc57ea171d2f93e4ff5fa01fe5711f2a" - }, - { - "expires": "2112-08-14T17:58:48Z", - "id": "4948fb46f88c41af90b65213a48baef7" - } - ] -} diff --git a/keystonemiddleware-moon/examples/pki/cms/revocation_list.pem b/keystonemiddleware-moon/examples/pki/cms/revocation_list.pem deleted file mode 100644 index a86d6d34..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/revocation_list.pem +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN CMS----- -MIIEGAYJKoZIhvcNAQcCoIIECTCCBAUCAQExCTAHBgUrDgMCGjCCAiUGCSqGSIb3 -DQEHAaCCAhYEggISew0KICAgICJyZXZva2VkIjogWw0KICAgICAgICB7DQogICAg -ICAgICAgICAiZXhwaXJlcyI6ICIyMTEyLTA4LTE0VDE3OjU4OjQ4WiIsDQogICAg -ICAgICAgICAiaWQiOiAiZGM1N2VhMTcxZDJmOTNlNGZmNWZhMDFmZTU3MTFmMmEi -DQogICAgICAgIH0sDQogICAgICAgIHsNCiAgICAgICAgICAgICJleHBpcmVzIjog -IjIxMTItMDgtMTRUMTc6NTg6NDhaIiwNCiAgICAgICAgICAgICJpZCI6ICI0OTQ4 -ZmI0NmY4OGM0MWFmOTBiNjUyMTNhNDhiYWVmNyINCiAgICAgICAgfSwNCiAgICAg -ICAgew0KICAgICAgICAgICAgImV4cGlyZXMiOiAiMjExMi0wOC0xNFQxNzo1ODo0 -OFoiLA0KICAgICAgICAgICAgImlkIjogImRjNTdlYTE3MWQyZjkzZTRmZjVmYTAx -ZmU1NzExZjJhIg0KICAgICAgICB9LA0KICAgICAgICB7DQogICAgICAgICAgICAi -ZXhwaXJlcyI6ICIyMTEyLTA4LTE0VDE3OjU4OjQ4WiIsDQogICAgICAgICAgICAi -aWQiOiAiNDk0OGZiNDZmODhjNDFhZjkwYjY1MjEzYTQ4YmFlZjciDQogICAgICAg -IH0NCiAgICBdDQp9DQoxggHKMIIBxgIBATCBpDCBnjEKMAgGA1UEBRMBNTELMAkG -A1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTdW5ueXZhbGUxEjAQBgNV -BAoTCU9wZW5TdGFjazERMA8GA1UECxMIS2V5c3RvbmUxJTAjBgkqhkiG9w0BCQEW -FmtleXN0b25lQG9wZW5zdGFjay5vcmcxFDASBgNVBAMTC1NlbGYgU2lnbmVkAgER -MAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIBAGMtzsHJdosl27LoRWYHGknORRWE -K0E9a7Bm4ZDt0XiGn0opGWpXF3Kj+7q86Ph1qcG9vZy20e2V+8n5696//OgMGCZe -QNbkOv70c0pkICMqczv4RaNF+UPetwDdv+p0WV8nLH5dDVc8Pp8B4T6fN6vXHXA2 -GMWxxn8SpF9bvP8S5VCAt7wsvmhWJpJVYe6bOdYzlhR0yLJzv4GvHtPVP+cBz6nS -uJguvt77MfQU97pOaDbvfmsJRUf/L3Fd93KbgLTzFPEhddTs1oD9pSDckncnZwua -9nIDn2iFNB/NfZrbqy+owM0Nt5j1m4dcPX/qm0J9DAhKGeDUbIu+81yL308= ------END CMS----- diff --git a/keystonemiddleware-moon/examples/pki/cms/revocation_list.pkiz b/keystonemiddleware-moon/examples/pki/cms/revocation_list.pkiz deleted file mode 100644 index 600fce02..00000000 --- a/keystonemiddleware-moon/examples/pki/cms/revocation_list.pkiz +++ /dev/null @@ -1 +0,0 @@ -PKIZ_eJx9VEuPszgQvPMr9h6NQgIhk8N3MMaACTaBmJdvCZMxGMhjkgmPX79kRtq9rNYXq0ul6u7qVr-9Tc9EDqZ_QbJ_BW8KwdhiXe5tLxyXz4KCsICXCQstCMHYQRCiHjLgmiL-sgSBjpzwpHPg_ubs8VFTrBC54DCBsYqEsL3T4A0848_DMqmxvIhUu1c8K7tD5jXFgA0M8UAYGnwGdJ8hVUkspAUy1gMZ6mmF7xh6Vw5fRK_Ox1jjKerpaNekzVdkGau8zRe8RR1JeUNZ0SskzYd87218aK5xm-iF00wVkCqoQEUk6kmldgFUe2qHk9BlEVgXNbAvlQ9BdUjDSnkRqVWrgcOnn7eBVUpq2SWXdZfLfDGJjDkL9by1Gy6L6nPfianN5uSa16JNRuXVJ5a4Jww_iCUehEUxYYVBmTCoVR5w1QncNj9-4DaSlH00OUMaScNhSjIqnEUtl0mbM9DzNl7QEfVceiU-q3fs_r-BL_-U_zYQq8FUNm-xSttcDxyiktRuA2ZWVMaTCC2n6qo8TVqFDt4my9ReCHc77YTZC2wCBs2rBc2zRFsChAMWMTIjYlKGfALq37gkMElIr8AReKagiQkEAzU1SYQ7BHIrCUMXdQ37SFffp4yXRyfukQThL_fCYLzpeLpiyodjy8OIIgLef5RhT_B-mawKLXoe27j3GJCmqG9lXTmbTjVhiKZmHs0po-pxuWqU0PlRGn-EhtWzaIvetsD-NxNhcEGbo5OLeNmcj21SA_FKVjjm_h6ADh8UAtR_9npaaxOEMTAnLwBePp4BLmXIWNlG3VbvrrPtiQexUW7rJVjJVTHLKFesvvOb53c2y3nfroKr_4HPWybJU5LKEN9F1blaEoPLEt9um4GU7jwrV4_30NvPxp29rpSZE9w6fjULI9zSqsSXWt34unwcYvmpzz_XiIe0nEtSfz6-gVaWj2__0JzrPF0PCCzvtnI-rXdREidG9V7NbmsBV_6mymo9HLTrEoxi53yWtrEjc_U6DtJ71MbzfWfCehrqqf-qb0q011N5z0mktafnQvrah6d2TEBxvsEi0o7hw_LnxL3Gxs2AJyPULAcZZR0GOHJPZzRX6GXHb1Y-J5pO3aO8k1ulj14d6C75KgSo8sN8zOaD2Y1P9P2F_yg_dwhR69-b9Dc2l4GQ
\ No newline at end of file diff --git a/keystonemiddleware-moon/examples/pki/gen_cmsz.py b/keystonemiddleware-moon/examples/pki/gen_cmsz.py deleted file mode 100644 index 6840c08e..00000000 --- a/keystonemiddleware-moon/examples/pki/gen_cmsz.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/python - -# 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 json -import os - -from keystoneclient.common import cms -from keystoneclient import utils - -CURRENT_DIR = os.path.abspath(os.path.dirname(__file__)) - - -def make_filename(*args): - return os.path.join(CURRENT_DIR, *args) - - -def generate_revocation_list(): - REVOKED_TOKENS = ['auth_token_revoked', 'auth_v3_token_revoked'] - revoked_list = [] - for token in REVOKED_TOKENS: - with open(make_filename('cms', '%s.pkiz' % name), 'r') as f: - token_data = f.read() - id = utils.hash_signed_token(token_data.encode('utf-8')) - revoked_list.append({ - 'id': id, - "expires": "2112-08-14T17:58:48Z" - }) - with open(make_filename('cms', '%s.pem' % name), 'r') as f: - pem_data = f.read() - token_data = cms.cms_to_token(pem_data).encode('utf-8') - id = utils.hash_signed_token(token_data) - revoked_list.append({ - 'id': id, - "expires": "2112-08-14T17:58:48Z" - }) - revoked_json = json.dumps({"revoked": revoked_list}) - with open(make_filename('cms', 'revocation_list.json'), 'w') as f: - f.write(revoked_json) - encoded = cms.pkiz_sign(revoked_json, - SIGNING_CERT_FILE_NAME, - SIGNING_KEY_FILE_NAME) - with open(make_filename('cms', 'revocation_list.pkiz'), 'w') as f: - f.write(encoded) - - encoded = cms.cms_sign_data(revoked_json, - SIGNING_CERT_FILE_NAME, - SIGNING_KEY_FILE_NAME) - with open(make_filename('cms', 'revocation_list.pem'), 'w') as f: - f.write(encoded) - - -CA_CERT_FILE_NAME = make_filename('certs', 'cacert.pem') -SIGNING_CERT_FILE_NAME = make_filename('certs', 'signing_cert.pem') -SIGNING_KEY_FILE_NAME = make_filename('private', 'signing_key.pem') -EXAMPLE_TOKENS = ['auth_token_revoked', - 'auth_token_unscoped', - 'auth_token_scoped', - 'auth_token_scoped_expired', - 'auth_v3_token_scoped', - 'auth_v3_token_revoked'] - - -# Helper script to generate the sample data for testing -# the signed tokens using the existing JSON data for the -# MII-prefixed tokens. Uses the keys and certificates -# generated in gen_pki.sh. -def generate_der_form(name): - derfile = make_filename('cms', '%s.der' % name) - with open(derfile, 'w') as f: - derform = cms.cms_sign_data(text, - SIGNING_CERT_FILE_NAME, - SIGNING_KEY_FILE_NAME, cms.PKIZ_CMS_FORM) - f.write(derform) - -for name in EXAMPLE_TOKENS: - json_file = make_filename('cms', name + '.json') - pkiz_file = make_filename('cms', name + '.pkiz') - with open(json_file, 'r') as f: - string_data = f.read() - - # validate the JSON - try: - token_data = json.loads(string_data) - except ValueError as v: - raise SystemExit('%s while processing token data from %s: %s' % - (v, json_file, string_data)) - - text = json.dumps(token_data).encode('utf-8') - - # Uncomment to record the token uncompressed, - # useful for debugging - # generate_der_form(name) - - encoded = cms.pkiz_sign(text, - SIGNING_CERT_FILE_NAME, - SIGNING_KEY_FILE_NAME) - - # verify before writing - cms.pkiz_verify(encoded, - SIGNING_CERT_FILE_NAME, - CA_CERT_FILE_NAME) - - with open(pkiz_file, 'w') as f: - f.write(encoded) - - generate_revocation_list() diff --git a/keystonemiddleware-moon/examples/pki/gen_pki.sh b/keystonemiddleware-moon/examples/pki/gen_pki.sh deleted file mode 100755 index b8b28f9d..00000000 --- a/keystonemiddleware-moon/examples/pki/gen_pki.sh +++ /dev/null @@ -1,213 +0,0 @@ -#!/bin/bash - -# Copyright 2012 OpenStack Foundation -# -# 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. - -# These functions generate the certificates and signed tokens for the tests. - -DIR=`dirname "$0"` -CURRENT_DIR=`cd "$DIR" && pwd` -CERTS_DIR=$CURRENT_DIR/certs -PRIVATE_DIR=$CURRENT_DIR/private -CMS_DIR=$CURRENT_DIR/cms - - -function rm_old { - rm -rf $CERTS_DIR/*.pem - rm -rf $PRIVATE_DIR/*.pem -} - -function cleanup { - rm -rf *.conf > /dev/null 2>&1 - rm -rf index* > /dev/null 2>&1 - rm -rf *.crt > /dev/null 2>&1 - rm -rf newcerts > /dev/null 2>&1 - rm -rf *.pem > /dev/null 2>&1 - rm -rf serial* > /dev/null 2>&1 -} - -function generate_ca_conf { - echo ' -[ req ] -default_bits = 2048 -default_keyfile = cakey.pem -default_md = default - -prompt = no -distinguished_name = ca_distinguished_name - -x509_extensions = ca_extensions - -[ ca_distinguished_name ] -serialNumber = 5 -countryName = US -stateOrProvinceName = CA -localityName = Sunnyvale -organizationName = OpenStack -organizationalUnitName = Keystone -emailAddress = keystone@openstack.org -commonName = Self Signed - -[ ca_extensions ] -basicConstraints = critical,CA:true -' > ca.conf -} - -function generate_ssl_req_conf { - echo ' -[ req ] -default_bits = 2048 -default_keyfile = keystonekey.pem -default_md = default - -prompt = no -distinguished_name = distinguished_name - -[ distinguished_name ] -countryName = US -stateOrProvinceName = CA -localityName = Sunnyvale -organizationName = OpenStack -organizationalUnitName = Keystone -commonName = localhost -emailAddress = keystone@openstack.org -' > ssl_req.conf -} - -function generate_cms_signing_req_conf { - echo ' -[ req ] -default_bits = 2048 -default_keyfile = keystonekey.pem -default_md = default - -prompt = no -distinguished_name = distinguished_name - -[ distinguished_name ] -countryName = US -stateOrProvinceName = CA -localityName = Sunnyvale -organizationName = OpenStack -organizationalUnitName = Keystone -commonName = Keystone -emailAddress = keystone@openstack.org -' > cms_signing_req.conf -} - -function generate_signing_conf { - echo ' -[ ca ] -default_ca = signing_ca - -[ signing_ca ] -dir = . -database = $dir/index.txt -new_certs_dir = $dir/newcerts - -certificate = $dir/certs/cacert.pem -serial = $dir/serial -private_key = $dir/private/cakey.pem - -default_days = 21360 -default_crl_days = 30 -default_md = default - -policy = policy_any - -[ policy_any ] -countryName = supplied -stateOrProvinceName = supplied -localityName = optional -organizationName = supplied -organizationalUnitName = supplied -emailAddress = supplied -commonName = supplied -' > signing.conf -} - -function setup { - touch index.txt - echo '10' > serial - generate_ca_conf - mkdir newcerts -} - -function check_error { - if [ $1 != 0 ] ; then - echo "Failed! rc=${1}" - echo 'Bailing ...' - cleanup - exit $1 - else - echo 'Done' - fi -} - -function generate_ca { - echo 'Generating New CA Certificate ...' - openssl req -x509 -newkey rsa:2048 -days 21360 -out $CERTS_DIR/cacert.pem -keyout $PRIVATE_DIR/cakey.pem -outform PEM -config ca.conf -nodes - check_error $? -} - -function ssl_cert_req { - echo 'Generating SSL Certificate Request ...' - generate_ssl_req_conf - openssl req -newkey rsa:2048 -keyout $PRIVATE_DIR/ssl_key.pem -keyform PEM -out ssl_req.pem -outform PEM -config ssl_req.conf -nodes - check_error $? - #openssl req -in req.pem -text -noout -} - -function cms_signing_cert_req { - echo 'Generating CMS Signing Certificate Request ...' - generate_cms_signing_req_conf - openssl req -newkey rsa:2048 -keyout $PRIVATE_DIR/signing_key.pem -keyform PEM -out cms_signing_req.pem -outform PEM -config cms_signing_req.conf -nodes - check_error $? - #openssl req -in req.pem -text -noout -} - -function issue_certs { - generate_signing_conf - echo 'Issuing SSL Certificate ...' - openssl ca -in ssl_req.pem -config signing.conf -batch - check_error $? - openssl x509 -in $CURRENT_DIR/newcerts/10.pem -out $CERTS_DIR/ssl_cert.pem - check_error $? - echo 'Issuing CMS Signing Certificate ...' - openssl ca -in cms_signing_req.pem -config signing.conf -batch - check_error $? - openssl x509 -in $CURRENT_DIR/newcerts/11.pem -out $CERTS_DIR/signing_cert.pem - check_error $? -} - -function create_middleware_cert { - cp $CERTS_DIR/ssl_cert.pem $CERTS_DIR/middleware.pem - cat $PRIVATE_DIR/ssl_key.pem >> $CERTS_DIR/middleware.pem -} - -function check_openssl { - echo 'Checking openssl availability ...' - which openssl - check_error $? -} - -JSON_FILES="${CMS_DIR}/auth_token_revoked.json ${CMS_DIR}/auth_token_unscoped.json ${CMS_DIR}/auth_token_scoped.json ${CMS_DIR}/auth_token_scoped_expired.json ${CMS_DIR}/revocation_list.json ${CMS_DIR}/auth_v3_token_scoped.json ${CMS_DIR}/auth_v3_token_revoked.json" - -function gen_sample_cms { - for json_file in $JSON_FILES - do - openssl cms -sign -in $json_file -nosmimecap -signer $CERTS_DIR/signing_cert.pem -inkey $PRIVATE_DIR/signing_key.pem -outform PEM -nodetach -nocerts -noattr -out ${json_file/.json/.pem} - done -} - diff --git a/keystonemiddleware-moon/examples/pki/private/cakey.pem b/keystonemiddleware-moon/examples/pki/private/cakey.pem deleted file mode 100644 index 1c93ee18..00000000 --- a/keystonemiddleware-moon/examples/pki/private/cakey.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCl8906EaRpibQF -cCBWfxzLi5x/XpZ9iL6UX92NrSJxcDbaGws7s+GtjgDy8UOEonesRWTeqQEZtHpC -3/UHHOnsA8F6ha/pq9LioqT7RehCnZCLBJwh5Ct+lclpWs15SkjJD2LTDkjox0eA -9nOBx+XDlWyU/GAyqx5Wsvg/Kxr0iod9/4IcJdnSdUjq4v0Cxg/zNk08XPJX+F0b -UDhgdUf7JrAmmS5LA8wphRnbIgtVsf6VN9HrbqtHAJDxh8gEfuwdhEW1df1fBtZ+ -6WMIF3IRSbIsZELFB6sqcyRj7HhMoWMkdEyPb2f8mq61MzTgE6lJGIyTRvEoFie7 -qtGADIofAgMBAAECggEBAJ47X3y2xaU7f0KQHsVafgI2JAnuDl+zusOOhJlJs8Wl -0Sc1EgjjAxOQiqcaE96rap//qqYDTuFLjCenkuItV32KNzizr3+GLZWaruRHS6X4 -xpFG2/gUrsQL3fdudOxpP+01lmzW+f25xRvZ4VilWRabquSDntWxA0R3cOwKFbGD -uuwbTw3pBrRfCk/2IdpQtRrvvkVIFiYT6b/zeCQzhp4RETbC0oxqcEEOIUGmimAV -9cbwafinxCo54cOfX4JAh3j7Mp3eQUymoFk5gnmIeVe0QmpH2VkN7eItrhEvHKOk -On7a5xvQ8s3wqPV5ZawHQcqar/p3QnGkiT6a+8LkIMECgYEA2iJ2DprTGZFRN0M7 -Yj4WLsSC3/GKK8eYsKG3TvMrmPqUDaiWLIvBoc1Le59x9eoF7Mha+WX+cAFL+GTg -1sB+PUZZStpf1R1tGvMldvpQ+5GplUBpuQe4J0n5rCG6+5jkvSr7xO+G1B+C3GFq -KR3iltiW5WJRVwh2k8yGvx3agyUCgYEAwsKFX82F7O+9IVud1JSQWmZMiyEK+DEX -JRnwx4HBuWr+AZqbb0grRRb6x8JTUOD4T7DZGxTaAdfzzRjKU2sBAO8VCgaj2Auv -5nsbvfXvrmDDCqwoaD2PMy+kgFvE0QTh65tzuGXl1IgpIYSC1JwnP6kOeUDbqE+k -UXzfVZzDdvMCgYByk9dfJIPt0h7O4Em4+NO+DQqRhtYE2PqjDM60cZZc7IIICp2X -GHHFA4i6jq3Vde9WyIbAqYpUWtoExzgylTm6BdGxN7NOxf4hQcZUEHepLIHfG85s -mlloibrTZ4RH06+SjZlhgE9Z7JNYHvMcVc5HXc0k/9ep15AxYiUFDjFQ4QKBgG7i -k089U4/X2wWgBNdgkmN1tQTNllJCmNvdzhG41dQ8j0vYe8C7BS+76qJLCGaW/6lX -lfRuRcUg78UI5UDjPloKxR7FMwmxdb+yvdPEr2bH3qQ36nWW/u30pSMTnJYownwD -MLp/AYCk2U4lBNwJ3+rF1ODCRY2pcnOWtg0nSL5zAoGAWRoOinogEnOodJzO7eB3 -TmL6M9QMyrAPBDsCnduJ8yW5mMUNod139YbSDxZPYwTLhK/GiHP/7OvLV5hg0s4s -QKnNaMeEowX7dyEO4ehnbfzysxXPKLRVhWhN6MCUc71NMxqr7QkuCXAjJS6/G21+ -Im3+Xb3Scq+UZghR+jiEZF0= ------END PRIVATE KEY----- diff --git a/keystonemiddleware-moon/examples/pki/private/signing_key.pem b/keystonemiddleware-moon/examples/pki/private/signing_key.pem deleted file mode 100644 index 758c0ffe..00000000 --- a/keystonemiddleware-moon/examples/pki/private/signing_key.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDM+VrILLl962VH -S8EKWVzdkaOy0OoxGZ63gajM7VTm8AbgtVnYibIOnVZQuz1XbftIGNXPFhYNUypr -LnMXrEEsnxgD4PvU/4bETG+stdricX6d1oKqsNFNR7F7zImiR/OzGhp7dONwccxf -kfX4QHA5Ogso+XMfSdC72SRDszeCeGUcjuo/w2WSLW95SuVvcZLqE/pk3Q2TkCZ1 -8hvNfLoln43QpC469a7srUXATqOJ2mPNvL6E/wOyPefmAoCoG44lFoR3k2jZjBEI -hstJxmH7XgvqErBzpcWd29dms8xz5PNwYdns9CIfb3GaHvQ6r5RTl37/avDrGHOW -KOoD01xLAgMBAAECggEAaIi22qWsh+JYCW9B6NRAPyN6V8Sh2x6UykOO4cwb45b/ -+vOh+YPn0fo9vfhvxTnq0A8SY4WBA5SpanYK7kTEDEyqw7em1y7l/RB6V5t7IMb+ -6uIuS3zXkVEB3AApJSEK0Ql7/gBTydHPh+H5jnzWfujyLhhhtNBBarvH+drZcWio -lWx8RERN4cH+3DZD/xxjH2Ff+X1XMvb8Xcup7MlWi2FtREg7LttLNWNK25iWjciP -QwfWQIrURRJrD2IrOr9V2nuIEvRqRRBoO+pxJT2sC48NJ3hiKV2GtSQe2nRpQJ47 -f9MEsF5KVQOOn+aQ60EKOI0MpNPmpiCZ5hFvBrNuOQKBgQD6vueEdI9eJgz5YN+t -XWdpNippv35RTD8R4bQcE6GqIUXOmtQFS2wPJLn7nisZUsGMNEs36Yl0T9iow63r -5GNAfgzpqN1XZqaSMwAdxKmlBNYpAkVXHhv+1jN+9diDYmoj9T+3Q6Zvk5e/Liyp -6i+TsDppwmmr2utWajhyJ7owFwKBgQDRROncTztGDYLfRcrIoYsPo79KQ8tqwd2a -07Usch2kplTqojCUmmhMMFgV2eZPPiCjnEy2bAYh9I/oj7xG6EwApXTshZdCpivC -rbUV64MakRTUP8IvM6PdI+apkJRsRUi/bSyIbcRlvEoCMNZhfj/5VY6w/jlwrPJj -oBOCXBlB7QKBgQDGEbEeX1i03UfYYh6uep7qbEAaooqsu5cCkBDPMO6+TmQvLPyY -Zhio6bEEQs/2w/lhwBk+xHqw5zXVMiWbtiB03F1k4eBeXxbrW+AWo7gCQ4zMfh+6 -Dm284wVwn9D1D/OaDevT31uEvcjb2ySq3/PPLSEnU8xXVaoa6/NEsX8Q5wKBgQCm -2smULWBXZKJ6n00mVxdnqun0rsVcI6Mrta14+KwGAdEnG5achdivFsTE924YtLKV -gSPxN4RUQokTprc52jHvOf1WMNYAADpYCOSfy55G6nKvIP8VX5lB00Qw4uRUx5FP -gB7H0K2NaGmiAYqNRXqAtOUG3kyyOFMzeAjWIdTJqQKBgQCHzY1c7sS1vv7mPEkr -6CpwoaEbZeFnWoHBA8Rd82psqfYsVJIRwk5Id8zgDSEmoEi8hQ9UrYbrFpLK77xq -EYSxLQHTNlM0G3lyEsv/gJhwYYhdTYiW3Cx3F6Y++jyn9O/+hFMyQvuesAL7DUYE -ptEfvzFprpQUpByXkIpuJub6fg== ------END PRIVATE KEY----- diff --git a/keystonemiddleware-moon/examples/pki/private/ssl_key.pem b/keystonemiddleware-moon/examples/pki/private/ssl_key.pem deleted file mode 100644 index 363ce94b..00000000 --- a/keystonemiddleware-moon/examples/pki/private/ssl_key.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDL06AaJROwHPgJ -9tcySSBepzJ81jYars2sMvLjyuvdiIBbhWvbS/a9Tw3WgL8H6OALkHiOU/f0A6Rp -v8dGDIDsxZQVjT/4SLaQUOeDM+9bfkKHpSd9G3CsdSSZgOH08n+MyZ7slPHfUHLY -Wso0SJD0vAi1gmGDlSM/mmhhHTpCDGo6Wbwqare6JNeTCGJTJYwrxtoMCh/W1Zrs -lPC5lFvlHD7KBBf6IU2A8Xh/dUa3p5pmQeHPW8Em90DzIB1qH0DRXl3KANc24xYR -R45pPCVkk6vFsy6P0JwwpnkszB+LcK6CEsJhLsOYvQFsiQfSZ8m7YGhgrMLxtop4 -YEPirGGrAgMBAAECggEATwvbY0hNwlb5uqOIAXBqpUqiQdexU9fG26lGmSDxKBDv -9o5frcRgBDrMWwvDCgY+HT4CAvB9kJx4/qnpVjkzJp/ZNiJ5VIiehIlbv348rXbh -xkk+bz5dDATCFOXuu1fwL2FhyM5anwhMAav0DyK1VLQ3jGzr9GO6L8hqAn+bQFFu -6ngiODwfhBMl5aRoL9UOBEhccK07znrH0JGRz+3+5Cdz59Xw91Bv210LhNNDL58+ -0JD0N+YztVOQd2bgwo0bQbOEijzmYq+0mjoqAnJh1/++y7PlIPs0AnPgqSnFPx9+ -6FsQEVRgk5Uq3kvPLaP4nT2y6MDZSp+ujYldvJhyQQKBgQDuX2pZIJMZ4aFnkG+K -TmJ5wsLa/u9an0TmvAL9RLtBpVpQNKD8cQ+y8PUZavXDbAIt5NWqZVnTbCR79Dnd -mZKblwcHhtsyA5f89el5KcxY2BREWdHdTnJpNd7XRlUECmzvX1zGj77lA982PhII -yflRBRV3vqLkgC8vfoYgRyRElwKBgQDa5jnLdx/RahfYMOgn1HE5o4hMzLR4Y0Dd -+gELshcUbPqouoP5zOb8WOagVJIgZVOSN+/VqbilVYrqRiNTn2rnoxs+HHRdaJNN -3eXllD4J2HfC2BIj1xSpIdyh2XewAJqw9IToHNB29QUhxOtgwseHciPG6JaKH2ik -kqGKH/EKDQKBgFFAftygiOPCkCTgC9UmANUmOQsy6N2H+pF3tsEj43xt44oBVnqW -A1boYXNnjRwuvdNs9BPf9i1l6E3EItFRXrLgWQoMwryakv0ryYh+YeRKyyW9RBbe -fYs1TJ8unx4Ae79gTxxztQsVNcmkgLs0NWKTjAzEE3w14V+cDhYEie1DAoGBAJdI -V5cLrBzBstsB6eBlDR9lqrRRIUS2a8U9m+1mVlcSfiWQSdehSd4K3tDdwePLw3ch -W4qR8n+pYAlLEe0gFvUhn5lMdwt7U5qUCeehjUKmrRYm2FqWsbu2IFJnBjXIJSC4 -zQXRrC0aZ0KQYpAL7XPpaVp1slyhGmPqxuO78Y0dAoGBAMHo3EIMwu9rfuGwFodr -GFsOZhfJqgo5GDNxxf89Q9WWpMDTCdX+wdBTrN/wsMbBuwIDHrUuRnk6D5CWRjSk -/ikCgHN3kOtrbL8zzqRomGAIIWKYGFEIGe1GHVGo5r//HXHdPxFXygvruQ/xbOA4 -RGvmDiji8vVDq7Shho8I6KuT ------END PRIVATE KEY----- diff --git a/keystonemiddleware-moon/examples/pki/run_all.sh b/keystonemiddleware-moon/examples/pki/run_all.sh deleted file mode 100755 index ba2f0b6e..00000000 --- a/keystonemiddleware-moon/examples/pki/run_all.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -x - -# Copyright 2012 OpenStack Foundation -# -# 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. - -# This script generates the crypto necessary for the SSL tests. - -. gen_pki.sh - -check_openssl -rm_old -cleanup -setup -generate_ca -ssl_cert_req -cms_signing_cert_req -issue_certs -create_middleware_cert -gen_sample_cms -cleanup diff --git a/keystonemiddleware-moon/keystonemiddleware.egg-info/dependency_links.txt b/keystonemiddleware-moon/keystonemiddleware.egg-info/dependency_links.txt deleted file mode 100644 index 8b137891..00000000 --- a/keystonemiddleware-moon/keystonemiddleware.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/keystonemiddleware-moon/keystonemiddleware.egg-info/entry_points.txt b/keystonemiddleware-moon/keystonemiddleware.egg-info/entry_points.txt deleted file mode 100644 index 8bc83366..00000000 --- a/keystonemiddleware-moon/keystonemiddleware.egg-info/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[oslo.config.opts] -keystonemiddleware.auth_token = keystonemiddleware.opts:list_auth_token_opts - diff --git a/keystonemiddleware-moon/keystonemiddleware.egg-info/not-zip-safe b/keystonemiddleware-moon/keystonemiddleware.egg-info/not-zip-safe deleted file mode 100644 index 8b137891..00000000 --- a/keystonemiddleware-moon/keystonemiddleware.egg-info/not-zip-safe +++ /dev/null @@ -1 +0,0 @@ - diff --git a/keystonemiddleware-moon/keystonemiddleware.egg-info/top_level.txt b/keystonemiddleware-moon/keystonemiddleware.egg-info/top_level.txt deleted file mode 100644 index 0622f2ef..00000000 --- a/keystonemiddleware-moon/keystonemiddleware.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -keystonemiddleware diff --git a/keystonemiddleware-moon/keystonemiddleware/__init__.py b/keystonemiddleware-moon/keystonemiddleware/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/__init__.py +++ /dev/null diff --git a/keystonemiddleware-moon/keystonemiddleware/audit.py b/keystonemiddleware-moon/keystonemiddleware/audit.py deleted file mode 100644 index e3536092..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/audit.py +++ /dev/null @@ -1,449 +0,0 @@ -# -# 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. - -""" -Build open standard audit information based on incoming requests - -AuditMiddleware filter should be placed after keystonemiddleware.auth_token -in the pipeline so that it can utilise the information the Identity server -provides. -""" - -import ast -import collections -import functools -import logging -import os.path -import re -import sys - -from oslo_config import cfg -from oslo_context import context -try: - import oslo_messaging - messaging = True -except ImportError: - messaging = False -from pycadf import cadftaxonomy as taxonomy -from pycadf import cadftype -from pycadf import credential -from pycadf import endpoint -from pycadf import eventfactory as factory -from pycadf import host -from pycadf import identifier -from pycadf import reason -from pycadf import reporterstep -from pycadf import resource -from pycadf import tag -from pycadf import timestamp -import six -from six.moves import configparser -from six.moves.urllib import parse as urlparse -import webob.dec - -from keystonemiddleware.i18n import _LE, _LI - - -_LOG = None - - -def _log_and_ignore_error(fn): - @functools.wraps(fn) - def wrapper(*args, **kwargs): - try: - return fn(*args, **kwargs) - except Exception as e: - _LOG.exception(_LE('An exception occurred processing ' - 'the API call: %s '), e) - return wrapper - - -Service = collections.namedtuple('Service', - ['id', 'name', 'type', 'admin_endp', - 'public_endp', 'private_endp']) - - -AuditMap = collections.namedtuple('AuditMap', - ['path_kw', - 'custom_actions', - 'service_endpoints', - 'default_target_endpoint_type']) - - -# NOTE(blk-u): Compatibility for Python 2. SafeConfigParser and -# SafeConfigParser.readfp are deprecated in Python 3. Remove this when we drop -# support for Python 2. -if six.PY2: - class _ConfigParser(configparser.SafeConfigParser): - read_file = configparser.SafeConfigParser.readfp -else: - _ConfigParser = configparser.ConfigParser - - -class OpenStackAuditApi(object): - - def __init__(self, cfg_file): - """Configure to recognize and map known api paths.""" - path_kw = {} - custom_actions = {} - endpoints = {} - default_target_endpoint_type = None - - if cfg_file: - try: - map_conf = _ConfigParser() - map_conf.read_file(open(cfg_file)) - - try: - default_target_endpoint_type = map_conf.get( - 'DEFAULT', 'target_endpoint_type') - except configparser.NoOptionError: - pass - - try: - custom_actions = dict(map_conf.items('custom_actions')) - except configparser.Error: - pass - - try: - path_kw = dict(map_conf.items('path_keywords')) - except configparser.Error: - pass - - try: - endpoints = dict(map_conf.items('service_endpoints')) - except configparser.Error: - pass - except configparser.ParsingError as err: - raise PycadfAuditApiConfigError( - 'Error parsing audit map file: %s' % err) - self._MAP = AuditMap( - path_kw=path_kw, custom_actions=custom_actions, - service_endpoints=endpoints, - default_target_endpoint_type=default_target_endpoint_type) - - @staticmethod - def _clean_path(value): - """Clean path if path has json suffix.""" - return value[:-5] if value.endswith('.json') else value - - def get_action(self, req): - """Take a given Request, parse url path to calculate action type. - - Depending on req.method: - - if POST: - - - path ends with 'action', read the body and use as action; - - path ends with known custom_action, take action from config; - - request ends with known path, assume is create action; - - request ends with unknown path, assume is update action. - - if GET: - - - request ends with known path, assume is list action; - - request ends with unknown path, assume is read action. - - if PUT, assume update action. - if DELETE, assume delete action. - if HEAD, assume read action. - - """ - path = req.path[:-1] if req.path.endswith('/') else req.path - url_ending = self._clean_path(path[path.rfind('/') + 1:]) - method = req.method - - if url_ending + '/' + method.lower() in self._MAP.custom_actions: - action = self._MAP.custom_actions[url_ending + '/' + - method.lower()] - elif url_ending in self._MAP.custom_actions: - action = self._MAP.custom_actions[url_ending] - elif method == 'POST': - if url_ending == 'action': - try: - if req.json: - body_action = list(req.json.keys())[0] - action = taxonomy.ACTION_UPDATE + '/' + body_action - else: - action = taxonomy.ACTION_CREATE - except ValueError: - action = taxonomy.ACTION_CREATE - elif url_ending not in self._MAP.path_kw: - action = taxonomy.ACTION_UPDATE - else: - action = taxonomy.ACTION_CREATE - elif method == 'GET': - if url_ending in self._MAP.path_kw: - action = taxonomy.ACTION_LIST - else: - action = taxonomy.ACTION_READ - elif method == 'PUT' or method == 'PATCH': - action = taxonomy.ACTION_UPDATE - elif method == 'DELETE': - action = taxonomy.ACTION_DELETE - elif method == 'HEAD': - action = taxonomy.ACTION_READ - else: - action = taxonomy.UNKNOWN - - return action - - def _get_service_info(self, endp): - service = Service( - type=self._MAP.service_endpoints.get( - endp['type'], - taxonomy.UNKNOWN), - name=endp['name'], - id=identifier.norm_ns(endp['endpoints'][0].get('id', - endp['name'])), - admin_endp=endpoint.Endpoint( - name='admin', - url=endp['endpoints'][0].get('adminURL', taxonomy.UNKNOWN)), - private_endp=endpoint.Endpoint( - name='private', - url=endp['endpoints'][0].get('internalURL', taxonomy.UNKNOWN)), - public_endp=endpoint.Endpoint( - name='public', - url=endp['endpoints'][0].get('publicURL', taxonomy.UNKNOWN))) - - return service - - def _build_typeURI(self, req, service_type): - """Build typeURI of target - - Combines service type and corresponding path for greater detail. - """ - type_uri = '' - prev_key = None - for key in re.split('/', req.path): - key = self._clean_path(key) - if key in self._MAP.path_kw: - type_uri += '/' + key - elif prev_key in self._MAP.path_kw: - type_uri += '/' + self._MAP.path_kw[prev_key] - prev_key = key - return service_type + type_uri - - def _build_target(self, req, service): - """Build target resource.""" - target_typeURI = ( - self._build_typeURI(req, service.type) - if service.type != taxonomy.UNKNOWN else service.type) - target = resource.Resource(typeURI=target_typeURI, - id=service.id, name=service.name) - if service.admin_endp: - target.add_address(service.admin_endp) - if service.private_endp: - target.add_address(service.private_endp) - if service.public_endp: - target.add_address(service.public_endp) - return target - - def get_target_resource(self, req): - """Retrieve target information - - If discovery is enabled, target will attempt to retrieve information - from service catalog. If not, the information will be taken from - given config file. - """ - service_info = Service(type=taxonomy.UNKNOWN, name=taxonomy.UNKNOWN, - id=taxonomy.UNKNOWN, admin_endp=None, - private_endp=None, public_endp=None) - try: - catalog = ast.literal_eval( - req.environ['HTTP_X_SERVICE_CATALOG']) - except KeyError: - raise PycadfAuditApiConfigError( - 'Service catalog is missing. ' - 'Cannot discover target information') - - default_endpoint = None - for endp in catalog: - endpoint_urls = endp['endpoints'][0] - admin_urlparse = urlparse.urlparse( - endpoint_urls.get('adminURL', '')) - public_urlparse = urlparse.urlparse( - endpoint_urls.get('publicURL', '')) - req_url = urlparse.urlparse(req.host_url) - if (req_url.netloc == admin_urlparse.netloc - or req_url.netloc == public_urlparse.netloc): - service_info = self._get_service_info(endp) - break - elif (self._MAP.default_target_endpoint_type and - endp['type'] == self._MAP.default_target_endpoint_type): - default_endpoint = endp - else: - if default_endpoint: - service_info = self._get_service_info(default_endpoint) - return self._build_target(req, service_info) - - -class ClientResource(resource.Resource): - def __init__(self, project_id=None, **kwargs): - super(ClientResource, self).__init__(**kwargs) - if project_id is not None: - self.project_id = project_id - - -class KeystoneCredential(credential.Credential): - def __init__(self, identity_status=None, **kwargs): - super(KeystoneCredential, self).__init__(**kwargs) - if identity_status is not None: - self.identity_status = identity_status - - -class PycadfAuditApiConfigError(Exception): - """Error raised when pyCADF fails to configure correctly.""" - - -class AuditMiddleware(object): - """Create an audit event based on request/response. - - The audit middleware takes in various configuration options such as the - ability to skip audit of certain requests. The full list of options can - be discovered here: - http://docs.openstack.org/developer/keystonemiddleware/audit.html - """ - - @staticmethod - def _get_aliases(proj): - aliases = {} - if proj: - # Aliases to support backward compatibility - aliases = { - '%s.openstack.common.rpc.impl_kombu' % proj: 'rabbit', - '%s.openstack.common.rpc.impl_qpid' % proj: 'qpid', - '%s.openstack.common.rpc.impl_zmq' % proj: 'zmq', - '%s.rpc.impl_kombu' % proj: 'rabbit', - '%s.rpc.impl_qpid' % proj: 'qpid', - '%s.rpc.impl_zmq' % proj: 'zmq', - } - return aliases - - def __init__(self, app, **conf): - self._application = app - global _LOG - _LOG = logging.getLogger(conf.get('log_name', __name__)) - self._service_name = conf.get('service_name') - self._ignore_req_list = [x.upper().strip() for x in - conf.get('ignore_req_list', '').split(',')] - self._cadf_audit = OpenStackAuditApi(conf.get('audit_map_file')) - - transport_aliases = self._get_aliases(cfg.CONF.project) - if messaging: - self._notifier = oslo_messaging.Notifier( - oslo_messaging.get_transport(cfg.CONF, - aliases=transport_aliases), - os.path.basename(sys.argv[0])) - - def _emit_audit(self, context, event_type, payload): - """Emit audit notification - - if oslo.messaging enabled, send notification. if not, log event. - """ - - if messaging: - self._notifier.info(context, event_type, payload) - else: - _LOG.info(_LI('Event type: %(event_type)s, Context: %(context)s, ' - 'Payload: %(payload)s'), {'context': context, - 'event_type': event_type, - 'payload': payload}) - - def _create_event(self, req): - correlation_id = identifier.generate_uuid() - action = self._cadf_audit.get_action(req) - - initiator = ClientResource( - typeURI=taxonomy.ACCOUNT_USER, - id=identifier.norm_ns(str(req.environ['HTTP_X_USER_ID'])), - name=req.environ['HTTP_X_USER_NAME'], - host=host.Host(address=req.client_addr, agent=req.user_agent), - credential=KeystoneCredential( - token=req.environ['HTTP_X_AUTH_TOKEN'], - identity_status=req.environ['HTTP_X_IDENTITY_STATUS']), - project_id=identifier.norm_ns(req.environ['HTTP_X_PROJECT_ID'])) - target = self._cadf_audit.get_target_resource(req) - - event = factory.EventFactory().new_event( - eventType=cadftype.EVENTTYPE_ACTIVITY, - outcome=taxonomy.OUTCOME_PENDING, - action=action, - initiator=initiator, - target=target, - observer=resource.Resource(id='target')) - event.requestPath = req.path_qs - event.add_tag(tag.generate_name_value_tag('correlation_id', - correlation_id)) - # cache model in request to allow tracking of transistive steps. - req.environ['cadf_event'] = event - return event - - @_log_and_ignore_error - def _process_request(self, request): - event = self._create_event(request) - - self._emit_audit(context.get_admin_context().to_dict(), - 'audit.http.request', event.as_dict()) - - @_log_and_ignore_error - def _process_response(self, request, response=None): - # NOTE(gordc): handle case where error processing request - if 'cadf_event' not in request.environ: - self._create_event(request) - event = request.environ['cadf_event'] - - if response: - if response.status_int >= 200 and response.status_int < 400: - result = taxonomy.OUTCOME_SUCCESS - else: - result = taxonomy.OUTCOME_FAILURE - event.reason = reason.Reason( - reasonType='HTTP', reasonCode=str(response.status_int)) - else: - result = taxonomy.UNKNOWN - - event.outcome = result - event.add_reporterstep( - reporterstep.Reporterstep( - role=cadftype.REPORTER_ROLE_MODIFIER, - reporter=resource.Resource(id='target'), - reporterTime=timestamp.get_utc_now())) - - self._emit_audit(context.get_admin_context().to_dict(), - 'audit.http.response', event.as_dict()) - - @webob.dec.wsgify - def __call__(self, req): - if req.method in self._ignore_req_list: - return req.get_response(self._application) - - self._process_request(req) - try: - response = req.get_response(self._application) - except Exception: - self._process_response(req) - raise - else: - self._process_response(req, response) - return response - - -def filter_factory(global_conf, **local_conf): - """Returns a WSGI filter app for use with paste.deploy.""" - conf = global_conf.copy() - conf.update(local_conf) - - def audit_filter(app): - return AuditMiddleware(app, **conf) - return audit_filter diff --git a/keystonemiddleware-moon/keystonemiddleware/auth_token/__init__.py b/keystonemiddleware-moon/keystonemiddleware/auth_token/__init__.py deleted file mode 100644 index be268da3..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/auth_token/__init__.py +++ /dev/null @@ -1,1129 +0,0 @@ -# Copyright 2010-2012 OpenStack Foundation -# -# 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. - -""" -Token-based Authentication Middleware - -This WSGI component: - -* Verifies that incoming client requests have valid tokens by validating - tokens with the auth service. -* Rejects unauthenticated requests unless the auth_token middleware is in - ``delay_auth_decision`` mode, which means the final decision is delegated to - the downstream WSGI component (usually the OpenStack service). -* Collects and forwards identity information based on a valid token - such as user name, domain, project, etc. - -Refer to: http://docs.openstack.org/developer/keystonemiddleware/\ -middlewarearchitecture.html - - -Headers -------- - -The auth_token middleware uses headers sent in by the client on the request -and sets headers and environment variables for the downstream WSGI component. - -Coming in from initial call from client or customer -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -HTTP_X_AUTH_TOKEN - The client token being passed in. - -HTTP_X_SERVICE_TOKEN - A service token being passed in. - -Used for communication between components -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -WWW-Authenticate - HTTP header returned to a user indicating which endpoint to use - to retrieve a new token. - -What auth_token adds to the request for use by the OpenStack service -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -When using composite authentication (a user and service token are -present) additional service headers relating to the service user -will be added. They take the same form as the standard headers but add -``_SERVICE_``. These headers will not exist in the environment if no -service token is present. - -HTTP_X_IDENTITY_STATUS, HTTP_X_SERVICE_IDENTITY_STATUS - Will be set to either ``Confirmed`` or ``Invalid``. - - The underlying service will only see a value of 'Invalid' if the middleware - is configured to run in ``delay_auth_decision`` mode. As with all such - headers, ``HTTP_X_SERVICE_IDENTITY_STATUS`` will only exist in the - environment if a service token is presented. This is different than - ``HTTP_X_IDENTITY_STATUS`` which is always set even if no user token is - presented. This allows the underlying service to determine if a - denial should use ``401 Unauthenticated`` or ``403 Forbidden``. - -HTTP_X_DOMAIN_ID, HTTP_X_SERVICE_DOMAIN_ID - Identity service managed unique identifier, string. Only present if - this is a domain-scoped token. - -HTTP_X_DOMAIN_NAME, HTTP_X_SERVICE_DOMAIN_NAME - Unique domain name, string. Only present if this is a domain-scoped - token. - -HTTP_X_PROJECT_ID, HTTP_X_SERVICE_PROJECT_ID - Identity service managed unique identifier, string. Only present if - this is a project-scoped token. - -HTTP_X_PROJECT_NAME, HTTP_X_SERVICE_PROJECT_NAME - Project name, unique within owning domain, string. Only present if - this is a project-scoped token. - -HTTP_X_PROJECT_DOMAIN_ID, HTTP_X_SERVICE_PROJECT_DOMAIN_ID - Identity service managed unique identifier of owning domain of - project, string. Only present if this is a project-scoped v3 token. If - this variable is set, this indicates that the PROJECT_NAME can only - be assumed to be unique within this domain. - -HTTP_X_PROJECT_DOMAIN_NAME, HTTP_X_SERVICE_PROJECT_DOMAIN_NAME - Name of owning domain of project, string. Only present if this is a - project-scoped v3 token. If this variable is set, this indicates that - the PROJECT_NAME can only be assumed to be unique within this domain. - -HTTP_X_USER_ID, HTTP_X_SERVICE_USER_ID - Identity-service managed unique identifier, string. - -HTTP_X_USER_NAME, HTTP_X_SERVICE_USER_NAME - User identifier, unique within owning domain, string. - -HTTP_X_USER_DOMAIN_ID, HTTP_X_SERVICE_USER_DOMAIN_ID - Identity service managed unique identifier of owning domain of - user, string. If this variable is set, this indicates that the USER_NAME - can only be assumed to be unique within this domain. - -HTTP_X_USER_DOMAIN_NAME, HTTP_X_SERVICE_USER_DOMAIN_NAME - Name of owning domain of user, string. If this variable is set, this - indicates that the USER_NAME can only be assumed to be unique within - this domain. - -HTTP_X_ROLES, HTTP_X_SERVICE_ROLES - Comma delimited list of case-sensitive role names. - -HTTP_X_SERVICE_CATALOG - service catalog (optional, JSON string). - - For compatibility reasons this catalog will always be in the V2 catalog - format even if it is a v3 token. - - .. note:: This is an exception in that it contains 'SERVICE' but relates to - a user token, not a service token. The existing user's catalog can be - very large; it was decided not to present a catalog relating to the - service token to avoid using more HTTP header space. - -HTTP_X_TENANT_ID - *Deprecated* in favor of HTTP_X_PROJECT_ID. - - Identity service managed unique identifier, string. For v3 tokens, this - will be set to the same value as HTTP_X_PROJECT_ID. - -HTTP_X_TENANT_NAME - *Deprecated* in favor of HTTP_X_PROJECT_NAME. - - Project identifier, unique within owning domain, string. For v3 tokens, - this will be set to the same value as HTTP_X_PROJECT_NAME. - -HTTP_X_TENANT - *Deprecated* in favor of HTTP_X_TENANT_ID and HTTP_X_TENANT_NAME. - - Identity server-assigned unique identifier, string. For v3 tokens, this - will be set to the same value as HTTP_X_PROJECT_ID. - -HTTP_X_USER - *Deprecated* in favor of HTTP_X_USER_ID and HTTP_X_USER_NAME. - - User name, unique within owning domain, string. - -HTTP_X_ROLE - *Deprecated* in favor of HTTP_X_ROLES. - - Will contain the same values as HTTP_X_ROLES. - -Environment Variables -^^^^^^^^^^^^^^^^^^^^^ - -These variables are set in the request environment for use by the downstream -WSGI component. - -keystone.token_info - Information about the token discovered in the process of validation. This - may include extended information returned by the token validation call, as - well as basic information about the project and user. - -keystone.token_auth - A keystoneclient auth plugin that may be used with a - :py:class:`keystoneclient.session.Session`. This plugin will load the - authentication data provided to auth_token middleware. - - -Configuration -------------- - -auth_token middleware configuration can be in the main application's -configuration file, e.g. in ``nova.conf``: - -.. code-block:: ini - - [keystone_authtoken] - auth_plugin = password - auth_url = http://keystone:35357/ - username = nova - user_domain_id = default - password = whyarewestillusingpasswords - project_name = service - project_domain_id = default - -Configuration can also be in the ``api-paste.ini`` file with the same options, -but this is discouraged. - -Swift ------ - -When deploy auth_token middleware with Swift, user may elect to use Swift -memcache instead of the local auth_token memcache. Swift memcache is passed in -from the request environment and it's identified by the ``swift.cache`` key. -However it could be different, depending on deployment. To use Swift memcache, -you must set the ``cache`` option to the environment key where the Swift cache -object is stored. - -""" - -import binascii -import datetime -import logging - -from keystoneclient import access -from keystoneclient import adapter -from keystoneclient import auth -from keystoneclient.common import cms -from keystoneclient import discover -from keystoneclient import exceptions -from keystoneclient import session -from oslo_config import cfg -from oslo_serialization import jsonutils -import pkg_resources -import six -import webob.dec - -from keystonemiddleware.auth_token import _auth -from keystonemiddleware.auth_token import _base -from keystonemiddleware.auth_token import _cache -from keystonemiddleware.auth_token import _exceptions as exc -from keystonemiddleware.auth_token import _identity -from keystonemiddleware.auth_token import _request -from keystonemiddleware.auth_token import _revocations -from keystonemiddleware.auth_token import _signing_dir -from keystonemiddleware.auth_token import _user_plugin -from keystonemiddleware.i18n import _, _LC, _LE, _LI, _LW - - -# NOTE(jamielennox): A number of options below are deprecated however are left -# in the list and only mentioned as deprecated in the help string. This is -# because we have to provide the same deprecation functionality for arguments -# passed in via the conf in __init__ (from paste) and there is no way to test -# that the default value was set or not in CONF. -# Also if we were to remove the options from the CONF list (as typical CONF -# deprecation works) then other projects will not be able to override the -# options via CONF. - -_OPTS = [ - cfg.StrOpt('auth_uri', - default=None, - # FIXME(dolph): should be default='http://127.0.0.1:5000/v2.0/', - # or (depending on client support) an unversioned, publicly - # accessible identity endpoint (see bug 1207517) - help='Complete public Identity API endpoint.'), - cfg.StrOpt('auth_version', - default=None, - help='API version of the admin Identity API endpoint.'), - cfg.BoolOpt('delay_auth_decision', - default=False, - help='Do not handle authorization requests within the' - ' middleware, but delegate the authorization decision to' - ' downstream WSGI components.'), - cfg.IntOpt('http_connect_timeout', - default=None, - help='Request timeout value for communicating with Identity' - ' API server.'), - cfg.IntOpt('http_request_max_retries', - default=3, - help='How many times are we trying to reconnect when' - ' communicating with Identity API Server.'), - cfg.StrOpt('cache', - default=None, - help='Env key for the swift cache.'), - cfg.StrOpt('certfile', - help='Required if identity server requires client certificate'), - cfg.StrOpt('keyfile', - help='Required if identity server requires client certificate'), - cfg.StrOpt('cafile', default=None, - help='A PEM encoded Certificate Authority to use when ' - 'verifying HTTPs connections. Defaults to system CAs.'), - cfg.BoolOpt('insecure', default=False, help='Verify HTTPS connections.'), - cfg.StrOpt('region_name', default=None, - help='The region in which the identity server can be found.'), - cfg.StrOpt('signing_dir', - help='Directory used to cache files related to PKI tokens.'), - cfg.ListOpt('memcached_servers', - deprecated_name='memcache_servers', - help='Optionally specify a list of memcached server(s) to' - ' use for caching. If left undefined, tokens will instead be' - ' cached in-process.'), - cfg.IntOpt('token_cache_time', - default=300, - help='In order to prevent excessive effort spent validating' - ' tokens, the middleware caches previously-seen tokens for a' - ' configurable duration (in seconds). Set to -1 to disable' - ' caching completely.'), - cfg.IntOpt('revocation_cache_time', - default=10, - help='Determines the frequency at which the list of revoked' - ' tokens is retrieved from the Identity service (in seconds). A' - ' high number of revocation events combined with a low cache' - ' duration may significantly reduce performance.'), - cfg.StrOpt('memcache_security_strategy', - default=None, - help='(Optional) If defined, indicate whether token data' - ' should be authenticated or authenticated and encrypted.' - ' Acceptable values are MAC or ENCRYPT. If MAC, token data is' - ' authenticated (with HMAC) in the cache. If ENCRYPT, token' - ' data is encrypted and authenticated in the cache. If the' - ' value is not one of these options or empty, auth_token will' - ' raise an exception on initialization.'), - cfg.StrOpt('memcache_secret_key', - default=None, - secret=True, - help='(Optional, mandatory if memcache_security_strategy is' - ' defined) This string is used for key derivation.'), - cfg.IntOpt('memcache_pool_dead_retry', - default=5 * 60, - help='(Optional) Number of seconds memcached server is' - ' considered dead before it is tried again.'), - cfg.IntOpt('memcache_pool_maxsize', - default=10, - help='(Optional) Maximum total number of open connections to' - ' every memcached server.'), - cfg.IntOpt('memcache_pool_socket_timeout', - default=3, - help='(Optional) Socket timeout in seconds for communicating ' - 'with a memcached server.'), - cfg.IntOpt('memcache_pool_unused_timeout', - default=60, - help='(Optional) Number of seconds a connection to memcached' - ' is held unused in the pool before it is closed.'), - cfg.IntOpt('memcache_pool_conn_get_timeout', - default=10, - help='(Optional) Number of seconds that an operation will wait ' - 'to get a memcached client connection from the pool.'), - cfg.BoolOpt('memcache_use_advanced_pool', - default=False, - help='(Optional) Use the advanced (eventlet safe) memcached ' - 'client pool. The advanced pool will only work under ' - 'python 2.x.'), - cfg.BoolOpt('include_service_catalog', - default=True, - help='(Optional) Indicate whether to set the X-Service-Catalog' - ' header. If False, middleware will not ask for service' - ' catalog on token validation and will not set the' - ' X-Service-Catalog header.'), - cfg.StrOpt('enforce_token_bind', - default='permissive', - help='Used to control the use and type of token binding. Can' - ' be set to: "disabled" to not check token binding.' - ' "permissive" (default) to validate binding information if the' - ' bind type is of a form known to the server and ignore it if' - ' not. "strict" like "permissive" but if the bind type is' - ' unknown the token will be rejected. "required" any form of' - ' token binding is needed to be allowed. Finally the name of a' - ' binding method that must be present in tokens.'), - cfg.BoolOpt('check_revocations_for_cached', default=False, - help='If true, the revocation list will be checked for cached' - ' tokens. This requires that PKI tokens are configured on the' - ' identity server.'), - cfg.ListOpt('hash_algorithms', default=['md5'], - help='Hash algorithms to use for hashing PKI tokens. This may' - ' be a single algorithm or multiple. The algorithms are those' - ' supported by Python standard hashlib.new(). The hashes will' - ' be tried in the order given, so put the preferred one first' - ' for performance. The result of the first hash will be stored' - ' in the cache. This will typically be set to multiple values' - ' only while migrating from a less secure algorithm to a more' - ' secure one. Once all the old tokens are expired this option' - ' should be set to a single value for better performance.'), -] - -CONF = cfg.CONF -CONF.register_opts(_OPTS, group=_base.AUTHTOKEN_GROUP) - -_LOG = logging.getLogger(__name__) - - -class _BIND_MODE(object): - DISABLED = 'disabled' - PERMISSIVE = 'permissive' - STRICT = 'strict' - REQUIRED = 'required' - KERBEROS = 'kerberos' - - -def _token_is_v2(token_info): - return ('access' in token_info) - - -def _token_is_v3(token_info): - return ('token' in token_info) - - -def _conf_values_type_convert(conf): - """Convert conf values into correct type.""" - if not conf: - return {} - - opt_types = {} - for o in (_OPTS + _auth.AuthTokenPlugin.get_options()): - type_dest = (getattr(o, 'type', str), o.dest) - opt_types[o.dest] = type_dest - # Also add the deprecated name with the same type and dest. - for d_o in o.deprecated_opts: - opt_types[d_o.name] = type_dest - - opts = {} - for k, v in six.iteritems(conf): - dest = k - try: - if v is not None: - type_, dest = opt_types[k] - v = type_(v) - except KeyError: - # This option is not known to auth_token. - pass - except ValueError as e: - raise exc.ConfigurationError( - _('Unable to convert the value of %(key)s option into correct ' - 'type: %(ex)s') % {'key': k, 'ex': e}) - opts[dest] = v - return opts - - -def _get_project_version(project): - return pkg_resources.get_distribution(project).version - - -class _BaseAuthProtocol(object): - """A base class for AuthProtocol token checking implementations. - - :param Callable app: The next application to call after middleware. - :param logging.Logger log: The logging object to use for output. By default - it will use a logger in the - keystonemiddleware.auth_token namespace. - :param str enforce_token_bind: The style of token binding enforcement to - perform. - """ - - def __init__(self, - app, - log=_LOG, - enforce_token_bind=_BIND_MODE.PERMISSIVE): - self.log = log - self._app = app - self._enforce_token_bind = enforce_token_bind - - @webob.dec.wsgify(RequestClass=_request._AuthTokenRequest) - def __call__(self, req): - """Handle incoming request.""" - response = self.process_request(req) - if response: - return response - response = req.get_response(self._app) - return self.process_response(response) - - def process_request(self, request): - """Process request. - - If this method returns a value then that value will be used as the - response. The next application down the stack will not be executed and - process_response will not be called. - - Otherwise, the next application down the stack will be executed and - process_response will be called with the generated response. - - By default this method does not return a value. - - :param request: Incoming request - :type request: _request.AuthTokenRequest - - """ - request.remove_auth_headers() - - user_auth_ref = None - serv_auth_ref = None - - if request.user_token: - self.log.debug('Authenticating user token') - try: - data, user_auth_ref = self._do_fetch_token(request.user_token) - self._validate_token(user_auth_ref) - self._confirm_token_bind(user_auth_ref, request) - except exc.InvalidToken: - self.log.info(_LI('Invalid user token')) - request.user_token_valid = False - else: - request.user_token_valid = True - request.environ['keystone.token_info'] = data - - if request.service_token: - self.log.debug('Authenticating service token') - try: - _, serv_auth_ref = self._do_fetch_token(request.service_token) - self._validate_token(serv_auth_ref) - self._confirm_token_bind(serv_auth_ref, request) - except exc.InvalidToken: - self.log.info(_LI('Invalid service token')) - request.service_token_valid = False - else: - request.service_token_valid = True - - p = _user_plugin.UserAuthPlugin(user_auth_ref, serv_auth_ref) - request.environ['keystone.token_auth'] = p - - def _validate_token(self, auth_ref): - """Perform the validation steps on the token. - - :param auth_ref: The token data - :type auth_ref: keystoneclient.access.AccessInfo - - :raises exc.InvalidToken: if token is rejected - """ - # 0 seconds of validity means is it valid right now. - if auth_ref.will_expire_soon(stale_duration=0): - raise exc.InvalidToken(_('Token authorization failed')) - - def _do_fetch_token(self, token): - """Helper method to fetch a token and convert it into an AccessInfo""" - data = self._fetch_token(token) - - try: - return data, access.AccessInfo.factory(body=data, auth_token=token) - except Exception: - self.log.warning(_LW('Invalid token contents.'), exc_info=True) - raise exc.InvalidToken(_('Token authorization failed')) - - def _fetch_token(self, token): - """Fetch the token data based on the value in the header. - - Retrieve the data associated with the token value that was in the - header. This can be from PKI, contacting the identity server or - whatever is required. - - :param str token: The token present in the request header. - - :raises exc.InvalidToken: if token is invalid. - - :returns: The token data - :rtype: dict - """ - raise NotImplemented() - - def process_response(self, response): - """Do whatever you'd like to the response. - - By default the response is returned unmodified. - - :param response: Response object - :type response: ._request._AuthTokenResponse - """ - return response - - def _invalid_user_token(self, msg=False): - # NOTE(jamielennox): use False as the default so that None is valid - if msg is False: - msg = _('Token authorization failed') - - raise exc.InvalidToken(msg) - - def _confirm_token_bind(self, auth_ref, req): - if self._enforce_token_bind == _BIND_MODE.DISABLED: - return - - try: - if auth_ref.version == 'v2.0': - bind = auth_ref['token']['bind'] - elif auth_ref.version == 'v3': - bind = auth_ref['bind'] - else: - self._invalid_user_token() - except KeyError: - bind = {} - - # permissive and strict modes don't require there to be a bind - permissive = self._enforce_token_bind in (_BIND_MODE.PERMISSIVE, - _BIND_MODE.STRICT) - - if not bind: - if permissive: - # no bind provided and none required - return - else: - self.log.info(_LI('No bind information present in token.')) - self._invalid_user_token() - - # get the named mode if bind_mode is not one of the predefined - if permissive or self._enforce_token_bind == _BIND_MODE.REQUIRED: - name = None - else: - name = self._enforce_token_bind - - if name and name not in bind: - self.log.info(_LI('Named bind mode %s not in bind information'), - name) - self._invalid_user_token() - - for bind_type, identifier in six.iteritems(bind): - if bind_type == _BIND_MODE.KERBEROS: - if req.auth_type != 'negotiate': - self.log.info(_LI('Kerberos credentials required and ' - 'not present.')) - self._invalid_user_token() - - if req.remote_user != identifier: - self.log.info(_LI('Kerberos credentials do not match ' - 'those in bind.')) - self._invalid_user_token() - - self.log.debug('Kerberos bind authentication successful.') - - elif self._enforce_token_bind == _BIND_MODE.PERMISSIVE: - self.log.debug('Ignoring Unknown bind for permissive mode: ' - '%(bind_type)s: %(identifier)s.', - {'bind_type': bind_type, - 'identifier': identifier}) - - else: - self.log.info( - _LI('Couldn`t verify unknown bind: %(bind_type)s: ' - '%(identifier)s.'), - {'bind_type': bind_type, 'identifier': identifier}) - self._invalid_user_token() - - -class AuthProtocol(_BaseAuthProtocol): - """Middleware that handles authenticating client calls.""" - - _SIGNING_CERT_FILE_NAME = 'signing_cert.pem' - _SIGNING_CA_FILE_NAME = 'cacert.pem' - - def __init__(self, app, conf): - log = logging.getLogger(conf.get('log_name', __name__)) - log.info(_LI('Starting Keystone auth_token middleware')) - - # NOTE(wanghong): If options are set in paste file, all the option - # values passed into conf are string type. So, we should convert the - # conf value into correct type. - self._conf = _conf_values_type_convert(conf) - - # NOTE(sileht): If we don't want to use oslo.config global object - # we can set the paste "oslo_config_project" and the middleware - # will load the configuration with a local oslo.config object. - self._local_oslo_config = None - if 'oslo_config_project' in conf: - if 'oslo_config_file' in conf: - default_config_files = [conf['oslo_config_file']] - else: - default_config_files = None - - # For unit tests, support passing in a ConfigOpts in - # oslo_config_config. - self._local_oslo_config = conf.get('oslo_config_config', - cfg.ConfigOpts()) - self._local_oslo_config( - {}, project=conf['oslo_config_project'], - default_config_files=default_config_files, - validate_default_values=True) - - self._local_oslo_config.register_opts( - _OPTS, group=_base.AUTHTOKEN_GROUP) - auth.register_conf_options(self._local_oslo_config, - group=_base.AUTHTOKEN_GROUP) - - super(AuthProtocol, self).__init__( - app, - log=log, - enforce_token_bind=self._conf_get('enforce_token_bind')) - - # delay_auth_decision means we still allow unauthenticated requests - # through and we let the downstream service make the final decision - self._delay_auth_decision = self._conf_get('delay_auth_decision') - self._include_service_catalog = self._conf_get( - 'include_service_catalog') - self._hash_algorithms = self._conf_get('hash_algorithms') - - self._identity_server = self._create_identity_server() - - self._auth_uri = self._conf_get('auth_uri') - if not self._auth_uri: - self.log.warning( - _LW('Configuring auth_uri to point to the public identity ' - 'endpoint is required; clients may not be able to ' - 'authenticate against an admin endpoint')) - - # FIXME(dolph): drop support for this fallback behavior as - # documented in bug 1207517. - - self._auth_uri = self._identity_server.auth_uri - - self._signing_directory = _signing_dir.SigningDirectory( - directory_name=self._conf_get('signing_dir'), log=self.log) - - self._token_cache = self._token_cache_factory() - - revocation_cache_timeout = datetime.timedelta( - seconds=self._conf_get('revocation_cache_time')) - self._revocations = _revocations.Revocations(revocation_cache_timeout, - self._signing_directory, - self._identity_server, - self._cms_verify, - self.log) - - self._check_revocations_for_cached = self._conf_get( - 'check_revocations_for_cached') - - def _conf_get(self, name, group=_base.AUTHTOKEN_GROUP): - # try config from paste-deploy first - if name in self._conf: - return self._conf[name] - elif self._local_oslo_config: - return self._local_oslo_config[group][name] - else: - return CONF[group][name] - - def process_request(self, request): - """Process request. - - Evaluate the headers in a request and attempt to authenticate the - request. If authenticated then additional headers are added to the - request for use by applications. If not authenticated the request will - be rejected or marked unauthenticated depending on configuration. - """ - self._token_cache.initialize(request.environ) - - resp = super(AuthProtocol, self).process_request(request) - if resp: - return resp - - if not request.user_token: - # if no user token is present then that's an invalid request - request.user_token_valid = False - - # NOTE(jamielennox): The service status is allowed to be missing if a - # service token is not passed. If the service status is missing that's - # a valid request. We should find a better way to expose this from the - # request object. - user_status = request.user_token and request.user_token_valid - service_status = request.headers.get('X-Service-Identity-Status', - 'Confirmed') - - if not (user_status and service_status == 'Confirmed'): - if self._delay_auth_decision: - self.log.info(_LI('Deferring reject downstream')) - else: - self.log.info(_LI('Rejecting request')) - self._reject_request() - - if request.user_token_valid: - request.set_user_headers(request.token_auth._user_auth_ref, - self._include_service_catalog) - - if request.service_token and request.service_token_valid: - request.set_service_headers(request.token_auth._serv_auth_ref) - - if self.log.isEnabledFor(logging.DEBUG): - self.log.debug('Received request from %s', - request.token_auth._log_format) - - def process_response(self, response): - """Process Response. - - Add ``WWW-Authenticate`` headers to requests that failed with - ``401 Unauthenticated`` so users know where to authenticate for future - requests. - """ - if response.status_int == 401: - response.headers.extend(self._reject_auth_headers) - - return response - - @property - def _reject_auth_headers(self): - header_val = 'Keystone uri=\'%s\'' % self._auth_uri - return [('WWW-Authenticate', header_val)] - - def _reject_request(self): - """Redirect client to auth server. - - :param env: wsgi request environment - :param start_response: wsgi response callback - :returns: HTTPUnauthorized http response - - """ - raise webob.exc.HTTPUnauthorized(body='Authentication required', - headers=self._reject_auth_headers) - - def _token_hashes(self, token): - """Generate a list of hashes that the current token may be cached as. - - With PKI tokens we have multiple hashing algorithms that we test with - revocations. This generates that whole list. - - The first element of this list is the preferred algorithm and is what - new cache values should be saved as. - - :param str token: The token being presented by a user. - - :returns: list of str token hashes. - """ - if cms.is_asn1_token(token) or cms.is_pkiz(token): - return list(cms.cms_hash_token(token, mode=algo) - for algo in self._hash_algorithms) - else: - return [token] - - def _cache_get_hashes(self, token_hashes): - """Check if the token is cached already. - - Functions takes a list of hashes that might be in the cache and matches - the first one that is present. If nothing is found in the cache it - returns None. - - :returns: token data if found else None. - """ - - for token in token_hashes: - cached = self._token_cache.get(token) - - if cached: - return cached - - def _fetch_token(self, token): - """Retrieve a token from either a PKI bundle or the identity server. - - :param str token: token id - - :raises exc.InvalidToken: if token is rejected - """ - data = None - token_hashes = None - - try: - token_hashes = self._token_hashes(token) - cached = self._cache_get_hashes(token_hashes) - - if cached: - data = cached - - if self._check_revocations_for_cached: - # A token stored in Memcached might have been revoked - # regardless of initial mechanism used to validate it, - # and needs to be checked. - self._revocations.check(token_hashes) - else: - data = self._validate_offline(token, token_hashes) - if not data: - data = self._identity_server.verify_token(token) - - self._token_cache.store(token_hashes[0], data) - - except (exceptions.ConnectionRefused, exceptions.RequestTimeout, - exc.RevocationListError, exc.ServiceError) as e: - self.log.critical(_LC('Unable to validate token: %s'), e) - raise webob.exc.HTTPServiceUnavailable() - except exc.InvalidToken: - self.log.debug('Token validation failure.', exc_info=True) - if token_hashes: - self._token_cache.store_invalid(token_hashes[0]) - self.log.warning(_LW('Authorization failed for token')) - raise - except Exception: - self.log.critical(_LC('Unable to validate token'), exc_info=True) - raise webob.exc.HTTPInternalServerError() - - return data - - def _validate_offline(self, token, token_hashes): - try: - if cms.is_pkiz(token): - verified = self._verify_pkiz_token(token, token_hashes) - elif cms.is_asn1_token(token): - verified = self._verify_signed_token(token, token_hashes) - else: - # Can't do offline validation for this type of token. - return - except exceptions.CertificateConfigError: - self.log.warning(_LW('Fetch certificate config failed, ' - 'fallback to online validation.')) - except exc.RevocationListError: - self.log.warning(_LW('Fetch revocation list failed, ' - 'fallback to online validation.')) - else: - data = jsonutils.loads(verified) - - audit_ids = None - if 'access' in data: - # It's a v2 token. - audit_ids = data['access']['token'].get('audit_ids') - else: - # It's a v3 token - audit_ids = data['token'].get('audit_ids') - - if audit_ids: - self._revocations.check_by_audit_id(audit_ids) - - return data - - def _validate_token(self, auth_ref): - super(AuthProtocol, self)._validate_token(auth_ref) - - if auth_ref.version == 'v2.0' and not auth_ref.project_id: - msg = _('Unable to determine service tenancy.') - raise exc.InvalidToken(msg) - - def _cms_verify(self, data, inform=cms.PKI_ASN1_FORM): - """Verifies the signature of the provided data's IAW CMS syntax. - - If either of the certificate files might be missing, fetch them and - retry. - """ - def verify(): - try: - signing_cert_path = self._signing_directory.calc_path( - self._SIGNING_CERT_FILE_NAME) - signing_ca_path = self._signing_directory.calc_path( - self._SIGNING_CA_FILE_NAME) - return cms.cms_verify(data, signing_cert_path, - signing_ca_path, - inform=inform).decode('utf-8') - except (exceptions.CMSError, - cms.subprocess.CalledProcessError) as err: - self.log.warning(_LW('Verify error: %s'), err) - raise exc.InvalidToken(_('Token authorization failed')) - - try: - return verify() - except exceptions.CertificateConfigError: - # the certs might be missing; unconditionally fetch to avoid racing - self._fetch_signing_cert() - self._fetch_ca_cert() - - try: - # retry with certs in place - return verify() - except exceptions.CertificateConfigError as err: - # if this is still occurring, something else is wrong and we - # need err.output to identify the problem - self.log.error(_LE('CMS Verify output: %s'), err.output) - raise - - def _verify_signed_token(self, signed_text, token_ids): - """Check that the token is unrevoked and has a valid signature.""" - self._revocations.check(token_ids) - formatted = cms.token_to_cms(signed_text) - verified = self._cms_verify(formatted) - return verified - - def _verify_pkiz_token(self, signed_text, token_ids): - self._revocations.check(token_ids) - try: - uncompressed = cms.pkiz_uncompress(signed_text) - verified = self._cms_verify(uncompressed, inform=cms.PKIZ_CMS_FORM) - return verified - # TypeError If the signed_text is not zlib compressed - # binascii.Error if signed_text has incorrect base64 padding (py34) - except (TypeError, binascii.Error): - raise exc.InvalidToken(signed_text) - - def _fetch_signing_cert(self): - self._signing_directory.write_file( - self._SIGNING_CERT_FILE_NAME, - self._identity_server.fetch_signing_cert()) - - def _fetch_ca_cert(self): - self._signing_directory.write_file( - self._SIGNING_CA_FILE_NAME, - self._identity_server.fetch_ca_cert()) - - def _get_auth_plugin(self): - # NOTE(jamielennox): Ideally this would use get_from_conf_options - # however that is not possible because we have to support the override - # pattern we use in _conf_get. There is a somewhat replacement for this - # in keystoneclient in load_from_options_getter which should be used - # when available. Until then this is essentially a copy and paste of - # the ksc load_from_conf_options code because we need to get a fix out - # for this quickly. - - # FIXME(jamielennox): update to use load_from_options_getter when - # https://review.openstack.org/162529 merges. - - # !!! - UNDER NO CIRCUMSTANCES COPY ANY OF THIS CODE - !!! - - group = self._conf_get('auth_section') or _base.AUTHTOKEN_GROUP - plugin_name = self._conf_get('auth_plugin', group=group) - plugin_kwargs = dict() - - if plugin_name: - plugin_class = auth.get_plugin_class(plugin_name) - else: - plugin_class = _auth.AuthTokenPlugin - # logger object is a required parameter of the default plugin - plugin_kwargs['log'] = self.log - - plugin_opts = plugin_class.get_options() - (self._local_oslo_config or CONF).register_opts(plugin_opts, - group=group) - - for opt in plugin_opts: - val = self._conf_get(opt.dest, group=group) - if val is not None: - val = opt.type(val) - plugin_kwargs[opt.dest] = val - - return plugin_class.load_from_options(**plugin_kwargs) - - def _determine_project(self): - """Determine a project name from all available config sources. - - The sources are checked in the following order: - - 1. The paste-deploy config for auth_token middleware - 2. The keystone_authtoken in the project's config - 3. The oslo.config CONF.project property - - """ - try: - return self._conf_get('project') - except cfg.NoSuchOptError: - # Prefer local oslo config object - if self._local_oslo_config: - return self._local_oslo_config.project - try: - # CONF.project will exist only if the service uses - # oslo.config. It will only be set when the project - # calls CONF(...) and when not set oslo.config oddly - # raises a NoSuchOptError exception. - return CONF.project - except cfg.NoSuchOptError: - return '' - - def _build_useragent_string(self): - project = self._determine_project() - if project: - project_version = _get_project_version(project) - project = '{project}/{project_version} '.format( - project=project, - project_version=project_version) - - ua_template = ('{project}' - 'keystonemiddleware.auth_token/{ksm_version}') - return ua_template.format( - project=project, - ksm_version=_get_project_version('keystonemiddleware')) - - def _create_identity_server(self): - # NOTE(jamielennox): Loading Session here should be exactly the - # same as calling Session.load_from_conf_options(CONF, GROUP) - # however we can't do that because we have to use _conf_get to - # support the paste.ini options. - sess = session.Session.construct(dict( - cert=self._conf_get('certfile'), - key=self._conf_get('keyfile'), - cacert=self._conf_get('cafile'), - insecure=self._conf_get('insecure'), - timeout=self._conf_get('http_connect_timeout'), - user_agent=self._build_useragent_string() - )) - - auth_plugin = self._get_auth_plugin() - - adap = adapter.Adapter( - sess, - auth=auth_plugin, - service_type='identity', - interface='admin', - region_name=self._conf_get('region_name'), - connect_retries=self._conf_get('http_request_max_retries')) - - auth_version = self._conf_get('auth_version') - if auth_version is not None: - auth_version = discover.normalize_version_number(auth_version) - return _identity.IdentityServer( - self.log, - adap, - include_service_catalog=self._include_service_catalog, - requested_auth_version=auth_version) - - def _token_cache_factory(self): - security_strategy = self._conf_get('memcache_security_strategy') - - cache_kwargs = dict( - cache_time=int(self._conf_get('token_cache_time')), - env_cache_name=self._conf_get('cache'), - memcached_servers=self._conf_get('memcached_servers'), - use_advanced_pool=self._conf_get('memcache_use_advanced_pool'), - memcache_pool_dead_retry=self._conf_get( - 'memcache_pool_dead_retry'), - memcache_pool_maxsize=self._conf_get('memcache_pool_maxsize'), - memcache_pool_unused_timeout=self._conf_get( - 'memcache_pool_unused_timeout'), - memcache_pool_conn_get_timeout=self._conf_get( - 'memcache_pool_conn_get_timeout'), - memcache_pool_socket_timeout=self._conf_get( - 'memcache_pool_socket_timeout'), - ) - - if security_strategy: - secret_key = self._conf_get('memcache_secret_key') - return _cache.SecureTokenCache(self.log, - security_strategy, - secret_key, - **cache_kwargs) - else: - return _cache.TokenCache(self.log, **cache_kwargs) - - -def filter_factory(global_conf, **local_conf): - """Returns a WSGI filter app for use with paste.deploy.""" - conf = global_conf.copy() - conf.update(local_conf) - - def auth_filter(app): - return AuthProtocol(app, conf) - return auth_filter - - -def app_factory(global_conf, **local_conf): - conf = global_conf.copy() - conf.update(local_conf) - return AuthProtocol(None, conf) - - -# NOTE(jamielennox): Maintained here for public API compatibility. -InvalidToken = exc.InvalidToken -ServiceError = exc.ServiceError -ConfigurationError = exc.ConfigurationError -RevocationListError = exc.RevocationListError diff --git a/keystonemiddleware-moon/keystonemiddleware/auth_token/_auth.py b/keystonemiddleware-moon/keystonemiddleware/auth_token/_auth.py deleted file mode 100644 index cf7ed84d..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/auth_token/_auth.py +++ /dev/null @@ -1,194 +0,0 @@ -# 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 logging - -from keystoneclient import auth -from keystoneclient.auth.identity import v2 -from keystoneclient.auth import token_endpoint -from keystoneclient import discover -from oslo_config import cfg - -from keystonemiddleware.auth_token import _base -from keystonemiddleware.i18n import _, _LW - - -_LOG = logging.getLogger(__name__) - - -class AuthTokenPlugin(auth.BaseAuthPlugin): - - def __init__(self, auth_host, auth_port, auth_protocol, auth_admin_prefix, - admin_user, admin_password, admin_tenant_name, admin_token, - identity_uri, log): - - log.warning(_LW( - "Use of the auth_admin_prefix, auth_host, auth_port, " - "auth_protocol, identity_uri, admin_token, admin_user, " - "admin_password, and admin_tenant_name configuration options is " - "deprecated in favor of auth_plugin and related options and may " - "be removed in a future release.")) - - # NOTE(jamielennox): it does appear here that our default arguments - # are backwards. We need to do it this way so that we can handle the - # same deprecation strategy for CONF and the conf variable. - if not identity_uri: - log.warning(_LW('Configuring admin URI using auth fragments. ' - 'This is deprecated, use \'identity_uri\'' - ' instead.')) - - if ':' in auth_host: - # Note(dzyu) it is an IPv6 address, so it needs to be wrapped - # with '[]' to generate a valid IPv6 URL, based on - # http://www.ietf.org/rfc/rfc2732.txt - auth_host = '[%s]' % auth_host - - identity_uri = '%s://%s:%s' % (auth_protocol, - auth_host, - auth_port) - - if auth_admin_prefix: - identity_uri = '%s/%s' % (identity_uri, - auth_admin_prefix.strip('/')) - - self._identity_uri = identity_uri.rstrip('/') - - # FIXME(jamielennox): Yes. This is wrong. We should be determining the - # plugin to use based on a combination of discovery and inputs. Much - # of this can be changed when we get keystoneclient 0.10. For now this - # hardcoded path is EXACTLY the same as the original auth_token did. - auth_url = '%s/v2.0' % self._identity_uri - - if admin_token: - log.warning(_LW( - "The admin_token option in the auth_token middleware is " - "deprecated and should not be used. The admin_user and " - "admin_password options should be used instead. The " - "admin_token option may be removed in a future release.")) - self._plugin = token_endpoint.Token(auth_url, admin_token) - else: - self._plugin = v2.Password(auth_url, - username=admin_user, - password=admin_password, - tenant_name=admin_tenant_name) - - self._LOG = log - self._discover = None - - def get_token(self, *args, **kwargs): - return self._plugin.get_token(*args, **kwargs) - - def get_endpoint(self, session, interface=None, version=None, **kwargs): - """Return an endpoint for the client. - - There are no required keyword arguments to ``get_endpoint`` as a plugin - implementation should use best effort with the information available to - determine the endpoint. - - :param session: The session object that the auth_plugin belongs to. - :type session: keystoneclient.session.Session - :param version: The version number required for this endpoint. - :type version: tuple or str - :param str interface: what visibility the endpoint should have. - - :returns: The base URL that will be used to talk to the required - service or None if not available. - :rtype: string - """ - if interface == auth.AUTH_INTERFACE: - return self._identity_uri - - if not version: - # NOTE(jamielennox): This plugin can only be used within auth_token - # and auth_token will always provide version= with requests. - return None - - if not self._discover: - self._discover = discover.Discover(session, - auth_url=self._identity_uri, - authenticated=False) - - if not self._discover.url_for(version): - # NOTE(jamielennox): The requested version is not supported by the - # identity server. - return None - - # NOTE(jamielennox): for backwards compatibility here we don't - # actually use the URL from discovery we hack it up instead. :( - # NOTE(blk-u): Normalizing the version is a workaround for bug 1450272. - # This can be removed once that's fixed. Also fix the docstring for the - # version parameter to be just "tuple". - version = discover.normalize_version_number(version) - if discover.version_match((2, 0), version): - return '%s/v2.0' % self._identity_uri - elif discover.version_match((3, 0), version): - return '%s/v3' % self._identity_uri - - # NOTE(jamielennox): This plugin will only get called from auth_token - # middleware. The middleware should never request a version that the - # plugin doesn't know how to handle. - msg = _('Invalid version asked for in auth_token plugin') - raise NotImplementedError(msg) - - def invalidate(self): - return self._plugin.invalidate() - - @classmethod - def get_options(cls): - options = super(AuthTokenPlugin, cls).get_options() - - options.extend([ - cfg.StrOpt('auth_admin_prefix', - default='', - help='Prefix to prepend at the beginning of the path. ' - 'Deprecated, use identity_uri.'), - cfg.StrOpt('auth_host', - default='127.0.0.1', - help='Host providing the admin Identity API endpoint. ' - 'Deprecated, use identity_uri.'), - cfg.IntOpt('auth_port', - default=35357, - help='Port of the admin Identity API endpoint. ' - 'Deprecated, use identity_uri.'), - cfg.StrOpt('auth_protocol', - default='https', - help='Protocol of the admin Identity API endpoint ' - '(http or https). Deprecated, use identity_uri.'), - cfg.StrOpt('identity_uri', - default=None, - help='Complete admin Identity API endpoint. This ' - 'should specify the unversioned root endpoint ' - 'e.g. https://localhost:35357/'), - cfg.StrOpt('admin_token', - secret=True, - help='This option is deprecated and may be removed in ' - 'a future release. Single shared secret with the ' - 'Keystone configuration used for bootstrapping a ' - 'Keystone installation, or otherwise bypassing ' - 'the normal authentication process. This option ' - 'should not be used, use `admin_user` and ' - '`admin_password` instead.'), - cfg.StrOpt('admin_user', - help='Service username.'), - cfg.StrOpt('admin_password', - secret=True, - help='Service user password.'), - cfg.StrOpt('admin_tenant_name', - default='admin', - help='Service tenant name.'), - ]) - - return options - - -auth.register_conf_options(cfg.CONF, _base.AUTHTOKEN_GROUP) -AuthTokenPlugin.register_conf_options(cfg.CONF, _base.AUTHTOKEN_GROUP) diff --git a/keystonemiddleware-moon/keystonemiddleware/auth_token/_base.py b/keystonemiddleware-moon/keystonemiddleware/auth_token/_base.py deleted file mode 100644 index ee4ec13c..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/auth_token/_base.py +++ /dev/null @@ -1,13 +0,0 @@ -# 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. - -AUTHTOKEN_GROUP = 'keystone_authtoken' diff --git a/keystonemiddleware-moon/keystonemiddleware/auth_token/_cache.py b/keystonemiddleware-moon/keystonemiddleware/auth_token/_cache.py deleted file mode 100644 index ce5faf66..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/auth_token/_cache.py +++ /dev/null @@ -1,338 +0,0 @@ -# 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 contextlib -import hashlib - -from oslo_serialization import jsonutils -import six - -from keystonemiddleware.auth_token import _exceptions as exc -from keystonemiddleware.auth_token import _memcache_crypt as memcache_crypt -from keystonemiddleware.i18n import _, _LE -from keystonemiddleware.openstack.common import memorycache - - -def _hash_key(key): - """Turn a set of arguments into a SHA256 hash. - - Using a known-length cache key is important to ensure that memcache - maximum key length is not exceeded causing failures to validate. - """ - if isinstance(key, six.text_type): - # NOTE(morganfainberg): Ensure we are always working with a bytes - # type required for the hasher. In python 2.7 it is possible to - # get a text_type (unicode). In python 3.4 all strings are - # text_type and not bytes by default. This encode coerces the - # text_type to the appropriate bytes values. - key = key.encode('utf-8') - return hashlib.sha256(key).hexdigest() - - -class _CachePool(list): - """A lazy pool of cache references.""" - - def __init__(self, cache, memcached_servers): - self._environment_cache = cache - self._memcached_servers = memcached_servers - - @contextlib.contextmanager - def reserve(self): - """Context manager to manage a pooled cache reference.""" - if self._environment_cache is not None: - # skip pooling and just use the cache from the upstream filter - yield self._environment_cache - return # otherwise the context manager will continue! - - try: - c = self.pop() - except IndexError: - # the pool is empty, so we need to create a new client - c = memorycache.get_client(self._memcached_servers) - - try: - yield c - finally: - self.append(c) - - -class _MemcacheClientPool(object): - """An advanced memcached client pool that is eventlet safe.""" - def __init__(self, memcache_servers, memcache_dead_retry=None, - memcache_pool_maxsize=None, memcache_pool_unused_timeout=None, - memcache_pool_conn_get_timeout=None, - memcache_pool_socket_timeout=None): - # NOTE(morganfainberg): import here to avoid hard dependency on - # python-memcached library. - global _memcache_pool - from keystonemiddleware.auth_token import _memcache_pool - - self._pool = _memcache_pool.MemcacheClientPool( - memcache_servers, - arguments={ - 'dead_retry': memcache_dead_retry, - 'socket_timeout': memcache_pool_socket_timeout, - }, - maxsize=memcache_pool_maxsize, - unused_timeout=memcache_pool_unused_timeout, - conn_get_timeout=memcache_pool_conn_get_timeout, - ) - - @contextlib.contextmanager - def reserve(self): - with self._pool.get() as client: - yield client - - -class TokenCache(object): - """Encapsulates the auth_token token cache functionality. - - auth_token caches tokens that it's seen so that when a token is re-used the - middleware doesn't have to do a more expensive operation (like going to the - identity server) to validate the token. - - initialize() must be called before calling the other methods. - - Store a valid token in the cache using store(); mark a token as invalid in - the cache using store_invalid(). - - Check if a token is in the cache and retrieve it using get(). - - """ - - _CACHE_KEY_TEMPLATE = 'tokens/%s' - _INVALID_INDICATOR = 'invalid' - - def __init__(self, log, cache_time=None, - env_cache_name=None, memcached_servers=None, - use_advanced_pool=False, memcache_pool_dead_retry=None, - memcache_pool_maxsize=None, memcache_pool_unused_timeout=None, - memcache_pool_conn_get_timeout=None, - memcache_pool_socket_timeout=None): - self._LOG = log - self._cache_time = cache_time - self._env_cache_name = env_cache_name - self._memcached_servers = memcached_servers - self._use_advanced_pool = use_advanced_pool - self._memcache_pool_dead_retry = memcache_pool_dead_retry, - self._memcache_pool_maxsize = memcache_pool_maxsize, - self._memcache_pool_unused_timeout = memcache_pool_unused_timeout - self._memcache_pool_conn_get_timeout = memcache_pool_conn_get_timeout - self._memcache_pool_socket_timeout = memcache_pool_socket_timeout - - self._cache_pool = None - self._initialized = False - - def _get_cache_pool(self, cache, memcache_servers, use_advanced_pool=False, - memcache_dead_retry=None, memcache_pool_maxsize=None, - memcache_pool_unused_timeout=None, - memcache_pool_conn_get_timeout=None, - memcache_pool_socket_timeout=None): - if use_advanced_pool is True and memcache_servers and cache is None: - return _MemcacheClientPool( - memcache_servers, - memcache_dead_retry=memcache_dead_retry, - memcache_pool_maxsize=memcache_pool_maxsize, - memcache_pool_unused_timeout=memcache_pool_unused_timeout, - memcache_pool_conn_get_timeout=memcache_pool_conn_get_timeout, - memcache_pool_socket_timeout=memcache_pool_socket_timeout) - else: - return _CachePool(cache, memcache_servers) - - def initialize(self, env): - if self._initialized: - return - - self._cache_pool = self._get_cache_pool( - env.get(self._env_cache_name), - self._memcached_servers, - use_advanced_pool=self._use_advanced_pool, - memcache_dead_retry=self._memcache_pool_dead_retry, - memcache_pool_maxsize=self._memcache_pool_maxsize, - memcache_pool_unused_timeout=self._memcache_pool_unused_timeout, - memcache_pool_conn_get_timeout=self._memcache_pool_conn_get_timeout - ) - - self._initialized = True - - def store(self, token_id, data): - """Put token data into the cache. - """ - self._LOG.debug('Storing token in cache') - self._cache_store(token_id, data) - - def store_invalid(self, token_id): - """Store invalid token in cache.""" - self._LOG.debug('Marking token as unauthorized in cache') - self._cache_store(token_id, self._INVALID_INDICATOR) - - def _get_cache_key(self, token_id): - """Get a unique key for this token id. - - Turn the token_id into something that can uniquely identify that token - in a key value store. - - As this is generally the first function called in a key lookup this - function also returns a context object. This context object is not - modified or used by the Cache object but is passed back on subsequent - functions so that decryption or other data can be shared throughout a - cache lookup. - - :param str token_id: The unique token id. - - :returns: A tuple of a string key and an implementation specific - context object - """ - # NOTE(jamielennox): in the basic implementation there is no need for - # a context so just pass None as it will only get passed back later. - unused_context = None - return self._CACHE_KEY_TEMPLATE % _hash_key(token_id), unused_context - - def _deserialize(self, data, context): - """Deserialize data from the cache back into python objects. - - Take data retrieved from the cache and return an appropriate python - dictionary. - - :param str data: The data retrieved from the cache. - :param object context: The context that was returned from - _get_cache_key. - - :returns: The python object that was saved. - """ - # memory cache will handle deserialization for us - return data - - def _serialize(self, data, context): - """Serialize data so that it can be saved to the cache. - - Take python objects and serialize them so that they can be saved into - the cache. - - :param object data: The data to be cached. - :param object context: The context that was returned from - _get_cache_key. - - :returns: The python object that was saved. - """ - # memory cache will handle serialization for us - return data - - def get(self, token_id): - """Return token information from cache. - - If token is invalid raise exc.InvalidToken - return token only if fresh (not expired). - """ - - if not token_id: - # Nothing to do - return - - key, context = self._get_cache_key(token_id) - - with self._cache_pool.reserve() as cache: - serialized = cache.get(key) - - if serialized is None: - return None - - if isinstance(serialized, six.text_type): - serialized = serialized.encode('utf8') - data = self._deserialize(serialized, context) - - # Note that _INVALID_INDICATOR and (data, expires) are the only - # valid types of serialized cache entries, so there is not - # a collision with jsonutils.loads(serialized) == None. - if not isinstance(data, six.string_types): - data = data.decode('utf-8') - cached = jsonutils.loads(data) - if cached == self._INVALID_INDICATOR: - self._LOG.debug('Cached Token is marked unauthorized') - raise exc.InvalidToken(_('Token authorization failed')) - - # NOTE(jamielennox): Cached values used to be stored as a tuple of data - # and expiry time. They no longer are but we have to allow some time to - # transition the old format so if it's a tuple just return the data. - try: - data, expires = cached - except ValueError: - data = cached - - return data - - def _cache_store(self, token_id, data): - """Store value into memcache. - - data may be _INVALID_INDICATOR or a tuple like (data, expires) - - """ - data = jsonutils.dumps(data) - if isinstance(data, six.text_type): - data = data.encode('utf-8') - - cache_key, context = self._get_cache_key(token_id) - data_to_store = self._serialize(data, context) - - with self._cache_pool.reserve() as cache: - cache.set(cache_key, data_to_store, time=self._cache_time) - - -class SecureTokenCache(TokenCache): - """A token cache that stores tokens encrypted. - - A more secure version of TokenCache that will encrypt tokens before - caching them. - """ - - def __init__(self, log, security_strategy, secret_key, **kwargs): - super(SecureTokenCache, self).__init__(log, **kwargs) - - security_strategy = security_strategy.upper() - - if security_strategy not in ('MAC', 'ENCRYPT'): - msg = _('memcache_security_strategy must be ENCRYPT or MAC') - raise exc.ConfigurationError(msg) - if not secret_key: - msg = _('memcache_secret_key must be defined when a ' - 'memcache_security_strategy is defined') - raise exc.ConfigurationError(msg) - - if isinstance(security_strategy, six.string_types): - security_strategy = security_strategy.encode('utf-8') - if isinstance(secret_key, six.string_types): - secret_key = secret_key.encode('utf-8') - - self._security_strategy = security_strategy - self._secret_key = secret_key - - def _get_cache_key(self, token_id): - context = memcache_crypt.derive_keys(token_id, - self._secret_key, - self._security_strategy) - key = self._CACHE_KEY_TEMPLATE % memcache_crypt.get_cache_key(context) - return key, context - - def _deserialize(self, data, context): - try: - # unprotect_data will return None if raw_cached is None - return memcache_crypt.unprotect_data(context, data) - except Exception: - msg = _LE('Failed to decrypt/verify cache data') - self._LOG.exception(msg) - - # this should have the same effect as data not - # found in cache - return None - - def _serialize(self, data, context): - return memcache_crypt.protect_data(context, data) diff --git a/keystonemiddleware-moon/keystonemiddleware/auth_token/_exceptions.py b/keystonemiddleware-moon/keystonemiddleware/auth_token/_exceptions.py deleted file mode 100644 index be045c96..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/auth_token/_exceptions.py +++ /dev/null @@ -1,27 +0,0 @@ -# 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. - - -class InvalidToken(Exception): - pass - - -class ServiceError(Exception): - pass - - -class ConfigurationError(Exception): - pass - - -class RevocationListError(Exception): - pass diff --git a/keystonemiddleware-moon/keystonemiddleware/auth_token/_identity.py b/keystonemiddleware-moon/keystonemiddleware/auth_token/_identity.py deleted file mode 100644 index 6fbeac27..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/auth_token/_identity.py +++ /dev/null @@ -1,252 +0,0 @@ -# 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 functools - -from keystoneclient import auth -from keystoneclient import discover -from keystoneclient import exceptions -from keystoneclient.v2_0 import client as v2_client -from keystoneclient.v3 import client as v3_client -from six.moves import urllib - -from keystonemiddleware.auth_token import _auth -from keystonemiddleware.auth_token import _exceptions as exc -from keystonemiddleware.i18n import _, _LE, _LI, _LW - - -def _convert_fetch_cert_exception(fetch_cert): - @functools.wraps(fetch_cert) - def wrapper(self): - try: - text = fetch_cert(self) - except exceptions.HTTPError as e: - raise exceptions.CertificateConfigError(e.details) - return text - - return wrapper - - -class _RequestStrategy(object): - - AUTH_VERSION = None - - def __init__(self, adap, include_service_catalog=None): - self._include_service_catalog = include_service_catalog - - def verify_token(self, user_token): - pass - - @_convert_fetch_cert_exception - def fetch_signing_cert(self): - return self._fetch_signing_cert() - - def _fetch_signing_cert(self): - pass - - @_convert_fetch_cert_exception - def fetch_ca_cert(self): - return self._fetch_ca_cert() - - def _fetch_ca_cert(self): - pass - - def fetch_revocation_list(self): - pass - - -class _V2RequestStrategy(_RequestStrategy): - - AUTH_VERSION = (2, 0) - - def __init__(self, adap, **kwargs): - super(_V2RequestStrategy, self).__init__(adap, **kwargs) - self._client = v2_client.Client(session=adap) - - def verify_token(self, token): - auth_ref = self._client.tokens.validate_access_info(token) - - if not auth_ref: - msg = _('Failed to fetch token data from identity server') - raise exc.InvalidToken(msg) - - return {'access': auth_ref} - - def _fetch_signing_cert(self): - return self._client.certificates.get_signing_certificate() - - def _fetch_ca_cert(self): - return self._client.certificates.get_ca_certificate() - - def fetch_revocation_list(self): - return self._client.tokens.get_revoked() - - -class _V3RequestStrategy(_RequestStrategy): - - AUTH_VERSION = (3, 0) - - def __init__(self, adap, **kwargs): - super(_V3RequestStrategy, self).__init__(adap, **kwargs) - self._client = v3_client.Client(session=adap) - - def verify_token(self, token): - auth_ref = self._client.tokens.validate( - token, - include_catalog=self._include_service_catalog) - - if not auth_ref: - msg = _('Failed to fetch token data from identity server') - raise exc.InvalidToken(msg) - - return {'token': auth_ref} - - def _fetch_signing_cert(self): - return self._client.simple_cert.get_certificates() - - def _fetch_ca_cert(self): - return self._client.simple_cert.get_ca_certificates() - - def fetch_revocation_list(self): - return self._client.tokens.get_revoked() - - -_REQUEST_STRATEGIES = [_V3RequestStrategy, _V2RequestStrategy] - - -class IdentityServer(object): - """Base class for operations on the Identity API server. - - The auth_token middleware needs to communicate with the Identity API server - to validate UUID tokens, fetch the revocation list, signing certificates, - etc. This class encapsulates the data and methods to perform these - operations. - - """ - - def __init__(self, log, adap, include_service_catalog=None, - requested_auth_version=None): - self._LOG = log - self._adapter = adap - self._include_service_catalog = include_service_catalog - self._requested_auth_version = requested_auth_version - - # Built on-demand with self._request_strategy. - self._request_strategy_obj = None - - @property - def auth_uri(self): - auth_uri = self._adapter.get_endpoint(interface=auth.AUTH_INTERFACE) - - # NOTE(jamielennox): This weird stripping of the prefix hack is - # only relevant to the legacy case. We urljoin '/' to get just the - # base URI as this is the original behaviour. - if isinstance(self._adapter.auth, _auth.AuthTokenPlugin): - auth_uri = urllib.parse.urljoin(auth_uri, '/').rstrip('/') - - return auth_uri - - @property - def auth_version(self): - return self._request_strategy.AUTH_VERSION - - @property - def _request_strategy(self): - if not self._request_strategy_obj: - strategy_class = self._get_strategy_class() - self._adapter.version = strategy_class.AUTH_VERSION - - self._request_strategy_obj = strategy_class( - self._adapter, - include_service_catalog=self._include_service_catalog) - - return self._request_strategy_obj - - def _get_strategy_class(self): - if self._requested_auth_version: - # A specific version was requested. - if discover.version_match(_V3RequestStrategy.AUTH_VERSION, - self._requested_auth_version): - return _V3RequestStrategy - - # The version isn't v3 so we don't know what to do. Just assume V2. - return _V2RequestStrategy - - # Specific version was not requested then we fall through to - # discovering available versions from the server - for klass in _REQUEST_STRATEGIES: - if self._adapter.get_endpoint(version=klass.AUTH_VERSION): - msg = _LI('Auth Token confirmed use of %s apis') - self._LOG.info(msg, self._requested_auth_version) - return klass - - versions = ['v%d.%d' % s.AUTH_VERSION for s in _REQUEST_STRATEGIES] - self._LOG.error(_LE('No attempted versions [%s] supported by server'), - ', '.join(versions)) - - msg = _('No compatible apis supported by server') - raise exc.ServiceError(msg) - - def verify_token(self, user_token, retry=True): - """Authenticate user token with identity server. - - :param user_token: user's token id - :param retry: flag that forces the middleware to retry - user authentication when an indeterminate - response is received. Optional. - :returns: access info received from identity server on success - :rtype: :py:class:`keystoneclient.access.AccessInfo` - :raises exc.InvalidToken: if token is rejected - :raises exc.ServiceError: if unable to authenticate token - - """ - try: - auth_ref = self._request_strategy.verify_token(user_token) - except exceptions.NotFound as e: - self._LOG.warning(_LW('Authorization failed for token')) - self._LOG.warning(_LW('Identity response: %s'), e.response.text) - raise exc.InvalidToken(_('Token authorization failed')) - except exceptions.Unauthorized as e: - self._LOG.info(_LI('Identity server rejected authorization')) - self._LOG.warning(_LW('Identity response: %s'), e.response.text) - if retry: - self._LOG.info(_LI('Retrying validation')) - return self.verify_token(user_token, False) - msg = _('Identity server rejected authorization necessary to ' - 'fetch token data') - raise exc.ServiceError(msg) - except exceptions.HttpError as e: - self._LOG.error( - _LE('Bad response code while validating token: %s'), - e.http_status) - self._LOG.warning(_LW('Identity response: %s'), e.response.text) - msg = _('Failed to fetch token data from identity server') - raise exc.ServiceError(msg) - else: - return auth_ref - - def fetch_revocation_list(self): - try: - data = self._request_strategy.fetch_revocation_list() - except exceptions.HTTPError as e: - msg = _('Failed to fetch token revocation list: %d') - raise exc.RevocationListError(msg % e.http_status) - if 'signed' not in data: - msg = _('Revocation list improperly formatted.') - raise exc.RevocationListError(msg) - return data['signed'] - - def fetch_signing_cert(self): - return self._request_strategy.fetch_signing_cert() - - def fetch_ca_cert(self): - return self._request_strategy.fetch_ca_cert() diff --git a/keystonemiddleware-moon/keystonemiddleware/auth_token/_memcache_crypt.py b/keystonemiddleware-moon/keystonemiddleware/auth_token/_memcache_crypt.py deleted file mode 100644 index 2e45571f..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/auth_token/_memcache_crypt.py +++ /dev/null @@ -1,210 +0,0 @@ -# Copyright 2010-2013 OpenStack Foundation -# -# 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. - -""" -Utilities for memcache encryption and integrity check. - -Data should be serialized before entering these functions. Encryption -has a dependency on the pycrypto. If pycrypto is not available, -CryptoUnavailableError will be raised. - -This module will not be called unless signing or encryption is enabled -in the config. It will always validate signatures, and will decrypt -data if encryption is enabled. It is not valid to mix protection -modes. - -""" - -import base64 -import functools -import hashlib -import hmac -import math -import os -import six -import sys - -from keystonemiddleware.i18n import _ - -# make sure pycrypto is available -try: - from Crypto.Cipher import AES -except ImportError: - AES = None - -HASH_FUNCTION = hashlib.sha384 -DIGEST_LENGTH = HASH_FUNCTION().digest_size -DIGEST_SPLIT = DIGEST_LENGTH // 3 -DIGEST_LENGTH_B64 = 4 * int(math.ceil(DIGEST_LENGTH / 3.0)) - - -class InvalidMacError(Exception): - """raise when unable to verify MACed data. - - This usually indicates that data had been expectedly modified in memcache. - - """ - pass - - -class DecryptError(Exception): - """raise when unable to decrypt encrypted data. - - """ - pass - - -class CryptoUnavailableError(Exception): - """raise when Python Crypto module is not available. - - """ - pass - - -def assert_crypto_availability(f): - """Ensure Crypto module is available.""" - - @functools.wraps(f) - def wrapper(*args, **kwds): - if AES is None: - raise CryptoUnavailableError() - return f(*args, **kwds) - return wrapper - - -if sys.version_info >= (3, 3): - constant_time_compare = hmac.compare_digest -else: - def constant_time_compare(first, second): - """Returns True if both string inputs are equal, otherwise False. - - This function should take a constant amount of time regardless of - how many characters in the strings match. - - """ - if len(first) != len(second): - return False - result = 0 - if six.PY3 and isinstance(first, bytes) and isinstance(second, bytes): - for x, y in zip(first, second): - result |= x ^ y - else: - for x, y in zip(first, second): - result |= ord(x) ^ ord(y) - return result == 0 - - -def derive_keys(token, secret, strategy): - """Derives keys for MAC and ENCRYPTION from the user-provided - secret. The resulting keys should be passed to the protect and - unprotect functions. - - As suggested by NIST Special Publication 800-108, this uses the - first 128 bits from the sha384 KDF for the obscured cache key - value, the second 128 bits for the message authentication key and - the remaining 128 bits for the encryption key. - - This approach is faster than computing a separate hmac as the KDF - for each desired key. - """ - digest = hmac.new(secret, token + strategy, HASH_FUNCTION).digest() - return {'CACHE_KEY': digest[:DIGEST_SPLIT], - 'MAC': digest[DIGEST_SPLIT: 2 * DIGEST_SPLIT], - 'ENCRYPTION': digest[2 * DIGEST_SPLIT:], - 'strategy': strategy} - - -def sign_data(key, data): - """Sign the data using the defined function and the derived key.""" - mac = hmac.new(key, data, HASH_FUNCTION).digest() - return base64.b64encode(mac) - - -@assert_crypto_availability -def encrypt_data(key, data): - """Encrypt the data with the given secret key. - - Padding is n bytes of the value n, where 1 <= n <= blocksize. - """ - iv = os.urandom(16) - cipher = AES.new(key, AES.MODE_CBC, iv) - padding = 16 - len(data) % 16 - return iv + cipher.encrypt(data + six.int2byte(padding) * padding) - - -@assert_crypto_availability -def decrypt_data(key, data): - """Decrypt the data with the given secret key.""" - iv = data[:16] - cipher = AES.new(key, AES.MODE_CBC, iv) - try: - result = cipher.decrypt(data[16:]) - except Exception: - raise DecryptError(_('Encrypted data appears to be corrupted.')) - - # Strip the last n padding bytes where n is the last value in - # the plaintext - return result[:-1 * six.byte2int([result[-1]])] - - -def protect_data(keys, data): - """Given keys and serialized data, returns an appropriately - protected string suitable for storage in the cache. - - """ - if keys['strategy'] == b'ENCRYPT': - data = encrypt_data(keys['ENCRYPTION'], data) - - encoded_data = base64.b64encode(data) - - signature = sign_data(keys['MAC'], encoded_data) - return signature + encoded_data - - -def unprotect_data(keys, signed_data): - """Given keys and cached string data, verifies the signature, - decrypts if necessary, and returns the original serialized data. - - """ - # cache backends return None when no data is found. We don't mind - # that this particular special value is unsigned. - if signed_data is None: - return None - - # First we calculate the signature - provided_mac = signed_data[:DIGEST_LENGTH_B64] - calculated_mac = sign_data( - keys['MAC'], - signed_data[DIGEST_LENGTH_B64:]) - - # Then verify that it matches the provided value - if not constant_time_compare(provided_mac, calculated_mac): - raise InvalidMacError(_('Invalid MAC; data appears to be corrupted.')) - - data = base64.b64decode(signed_data[DIGEST_LENGTH_B64:]) - - # then if necessary decrypt the data - if keys['strategy'] == b'ENCRYPT': - data = decrypt_data(keys['ENCRYPTION'], data) - - return data - - -def get_cache_key(keys): - """Given keys generated by derive_keys(), returns a base64 - encoded value suitable for use as a cache key in memcached. - - """ - return base64.b64encode(keys['CACHE_KEY']) diff --git a/keystonemiddleware-moon/keystonemiddleware/auth_token/_memcache_pool.py b/keystonemiddleware-moon/keystonemiddleware/auth_token/_memcache_pool.py deleted file mode 100644 index 77652868..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/auth_token/_memcache_pool.py +++ /dev/null @@ -1,184 +0,0 @@ -# Copyright 2014 Mirantis 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. - -"""Thread-safe connection pool for python-memcached.""" - -# NOTE(yorik-sar): this file is copied between keystone and keystonemiddleware -# and should be kept in sync until we can use external library for this. - -import collections -import contextlib -import itertools -import logging -import time - -from six.moves import queue - -from keystonemiddleware.i18n import _LC - - -_PoolItem = collections.namedtuple('_PoolItem', ['ttl', 'connection']) - - -class ConnectionGetTimeoutException(Exception): - pass - - -class ConnectionPool(queue.Queue): - """Base connection pool class - - This class implements the basic connection pool logic as an abstract base - class. - """ - def __init__(self, maxsize, unused_timeout, conn_get_timeout=None): - """Initialize the connection pool. - - :param maxsize: maximum number of client connections for the pool - :type maxsize: int - :param unused_timeout: idle time to live for unused clients (in - seconds). If a client connection object has been - in the pool and idle for longer than the - unused_timeout, it will be reaped. This is to - ensure resources are released as utilization - goes down. - :type unused_timeout: int - :param conn_get_timeout: maximum time in seconds to wait for a - connection. If set to `None` timeout is - indefinite. - :type conn_get_timeout: int - """ - queue.Queue.__init__(self, maxsize) - self._unused_timeout = unused_timeout - self._connection_get_timeout = conn_get_timeout - self._acquired = 0 - self._LOG = logging.getLogger(__name__) - - def _create_connection(self): - raise NotImplementedError - - def _destroy_connection(self, conn): - raise NotImplementedError - - @contextlib.contextmanager - def acquire(self): - try: - conn = self.get(timeout=self._connection_get_timeout) - except queue.Empty: - self._LOG.critical(_LC('Unable to get a connection from pool id ' - '%(id)s after %(seconds)s seconds.'), - {'id': id(self), - 'seconds': self._connection_get_timeout}) - raise ConnectionGetTimeoutException() - try: - yield conn - finally: - self.put(conn) - - def _qsize(self): - return self.maxsize - self._acquired - - if not hasattr(queue.Queue, '_qsize'): - qsize = _qsize - - def _get(self): - if self.queue: - conn = self.queue.pop().connection - else: - conn = self._create_connection() - self._acquired += 1 - return conn - - def _put(self, conn): - self.queue.append(_PoolItem( - ttl=time.time() + self._unused_timeout, - connection=conn, - )) - self._acquired -= 1 - # Drop all expired connections from the right end of the queue - now = time.time() - while self.queue and self.queue[0].ttl < now: - conn = self.queue.popleft().connection - self._destroy_connection(conn) - - -class MemcacheClientPool(ConnectionPool): - def __init__(self, urls, arguments, **kwargs): - ConnectionPool.__init__(self, **kwargs) - self._urls = urls - self._arguments = arguments - # NOTE(morganfainberg): The host objects expect an int for the - # deaduntil value. Initialize this at 0 for each host with 0 indicating - # the host is not dead. - self._hosts_deaduntil = [0] * len(urls) - - # NOTE(morganfainberg): Lazy import to allow middleware to work with - # python 3k even if memcache will not due to python 3k - # incompatibilities within the python-memcache library. - global memcache - import memcache - - # This 'class' is taken from http://stackoverflow.com/a/22520633/238308 - # Don't inherit client from threading.local so that we can reuse - # clients in different threads - MemcacheClient = type('_MemcacheClient', (object,), - dict(memcache.Client.__dict__)) - - self._memcache_client_class = MemcacheClient - - def _create_connection(self): - return self._memcache_client_class(self._urls, **self._arguments) - - def _destroy_connection(self, conn): - conn.disconnect_all() - - def _get(self): - conn = ConnectionPool._get(self) - try: - # Propagate host state known to us to this client's list - now = time.time() - for deaduntil, host in zip(self._hosts_deaduntil, conn.servers): - if deaduntil > now and host.deaduntil <= now: - host.mark_dead('propagating death mark from the pool') - host.deaduntil = deaduntil - except Exception: - # We need to be sure that connection doesn't leak from the pool. - # This code runs before we enter context manager's try-finally - # block, so we need to explicitly release it here - ConnectionPool._put(self, conn) - raise - return conn - - def _put(self, conn): - try: - # If this client found that one of the hosts is dead, mark it as - # such in our internal list - now = time.time() - for i, deaduntil, host in zip(itertools.count(), - self._hosts_deaduntil, - conn.servers): - # Do nothing if we already know this host is dead - if deaduntil <= now: - if host.deaduntil > now: - self._hosts_deaduntil[i] = host.deaduntil - else: - self._hosts_deaduntil[i] = 0 - # If all hosts are dead we should forget that they're dead. This - # way we won't get completely shut off until dead_retry seconds - # pass, but will be checking servers as frequent as we can (over - # way smaller socket_timeout) - if all(deaduntil > now for deaduntil in self._hosts_deaduntil): - self._hosts_deaduntil[:] = [0] * len(self._hosts_deaduntil) - finally: - ConnectionPool._put(self, conn) diff --git a/keystonemiddleware-moon/keystonemiddleware/auth_token/_request.py b/keystonemiddleware-moon/keystonemiddleware/auth_token/_request.py deleted file mode 100644 index 72fd5380..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/auth_token/_request.py +++ /dev/null @@ -1,224 +0,0 @@ -# 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 itertools - -from oslo_serialization import jsonutils -import six -import webob - - -def _v3_to_v2_catalog(catalog): - """Convert a catalog to v2 format. - - X_SERVICE_CATALOG must be specified in v2 format. If you get a token - that is in v3 convert it. - """ - v2_services = [] - for v3_service in catalog: - # first copy over the entries we allow for the service - v2_service = {'type': v3_service['type']} - try: - v2_service['name'] = v3_service['name'] - except KeyError: - pass - - # now convert the endpoints. Because in v3 we specify region per - # URL not per group we have to collect all the entries of the same - # region together before adding it to the new service. - regions = {} - for v3_endpoint in v3_service.get('endpoints', []): - region_name = v3_endpoint.get('region') - try: - region = regions[region_name] - except KeyError: - region = {'region': region_name} if region_name else {} - regions[region_name] = region - - interface_name = v3_endpoint['interface'].lower() + 'URL' - region[interface_name] = v3_endpoint['url'] - - v2_service['endpoints'] = list(regions.values()) - v2_services.append(v2_service) - - return v2_services - - -# NOTE(jamielennox): this should probably be moved into its own file, but at -# the moment there's no real logic here so just keep it locally. -class _AuthTokenResponse(webob.Response): - - default_content_type = None # prevents webob assigning a content type - - -class _AuthTokenRequest(webob.Request): - - ResponseClass = _AuthTokenResponse - - _HEADER_TEMPLATE = { - 'X%s-Domain-Id': 'domain_id', - 'X%s-Domain-Name': 'domain_name', - 'X%s-Project-Id': 'project_id', - 'X%s-Project-Name': 'project_name', - 'X%s-Project-Domain-Id': 'project_domain_id', - 'X%s-Project-Domain-Name': 'project_domain_name', - 'X%s-User-Id': 'user_id', - 'X%s-User-Name': 'username', - 'X%s-User-Domain-Id': 'user_domain_id', - 'X%s-User-Domain-Name': 'user_domain_name', - } - - _ROLES_TEMPLATE = 'X%s-Roles' - - _USER_HEADER_PREFIX = '' - _SERVICE_HEADER_PREFIX = '-Service' - - _USER_STATUS_HEADER = 'X-Identity-Status' - _SERVICE_STATUS_HEADER = 'X-Service-Identity-Status' - - _SERVICE_CATALOG_HEADER = 'X-Service-Catalog' - _TOKEN_AUTH = 'keystone.token_auth' - - _CONFIRMED = 'Confirmed' - _INVALID = 'Invalid' - - # header names that have been deprecated in favour of something else. - _DEPRECATED_HEADER_MAP = { - 'X-Role': 'X-Roles', - 'X-User': 'X-User-Name', - 'X-Tenant-Id': 'X-Project-Id', - 'X-Tenant-Name': 'X-Project-Name', - 'X-Tenant': 'X-Project-Name', - } - - def _confirmed(cls, value): - return cls._CONFIRMED if value else cls._INVALID - - @property - def user_token_valid(self): - """User token is marked as valid. - - :returns: True if the X-Identity-Status header is set to Confirmed. - :rtype: bool - """ - return self.headers[self._USER_STATUS_HEADER] == self._CONFIRMED - - @user_token_valid.setter - def user_token_valid(self, value): - self.headers[self._USER_STATUS_HEADER] = self._confirmed(value) - - @property - def user_token(self): - return self.headers.get('X-Auth-Token', - self.headers.get('X-Storage-Token')) - - @property - def service_token_valid(self): - """Service token is marked as valid. - - :returns: True if the X-Service-Identity-Status header - is set to Confirmed. - :rtype: bool - """ - return self.headers[self._SERVICE_STATUS_HEADER] == self._CONFIRMED - - @service_token_valid.setter - def service_token_valid(self, value): - self.headers[self._SERVICE_STATUS_HEADER] = self._confirmed(value) - - @property - def service_token(self): - return self.headers.get('X-Service-Token') - - def _set_auth_headers(self, auth_ref, prefix): - names = ','.join(auth_ref.role_names) - self.headers[self._ROLES_TEMPLATE % prefix] = names - - for header_tmplt, attr in six.iteritems(self._HEADER_TEMPLATE): - self.headers[header_tmplt % prefix] = getattr(auth_ref, attr) - - def set_user_headers(self, auth_ref, include_service_catalog): - """Convert token object into headers. - - Build headers that represent authenticated user - see main - doc info at start of __init__ file for details of headers to be defined - """ - self._set_auth_headers(auth_ref, self._USER_HEADER_PREFIX) - - for k, v in six.iteritems(self._DEPRECATED_HEADER_MAP): - self.headers[k] = self.headers[v] - - if include_service_catalog and auth_ref.has_service_catalog(): - catalog = auth_ref.service_catalog.get_data() - if auth_ref.version == 'v3': - catalog = _v3_to_v2_catalog(catalog) - - c = jsonutils.dumps(catalog) - self.headers[self._SERVICE_CATALOG_HEADER] = c - - self.user_token_valid = True - - def set_service_headers(self, auth_ref): - """Convert token object into service headers. - - Build headers that represent authenticated user - see main - doc info at start of __init__ file for details of headers to be defined - """ - self._set_auth_headers(auth_ref, self._SERVICE_HEADER_PREFIX) - self.service_token_valid = True - - def _all_auth_headers(self): - """All the authentication headers that can be set on the request""" - yield self._SERVICE_CATALOG_HEADER - yield self._USER_STATUS_HEADER - yield self._SERVICE_STATUS_HEADER - - for header in self._DEPRECATED_HEADER_MAP: - yield header - - prefixes = (self._USER_HEADER_PREFIX, self._SERVICE_HEADER_PREFIX) - - for tmpl, prefix in itertools.product(self._HEADER_TEMPLATE, prefixes): - yield tmpl % prefix - - for prefix in prefixes: - yield self._ROLES_TEMPLATE % prefix - - def remove_auth_headers(self): - """Remove headers so a user can't fake authentication.""" - for header in self._all_auth_headers(): - self.headers.pop(header, None) - - @property - def auth_type(self): - """The authentication type that was performed by the web server. - - The returned string value is always lower case. - - :returns: The AUTH_TYPE environ string or None if not present. - :rtype: str or None - """ - try: - auth_type = self.environ['AUTH_TYPE'] - except KeyError: - return None - else: - return auth_type.lower() - - @property - def token_auth(self): - """The auth plugin that will be associated with this request""" - return self.environ.get(self._TOKEN_AUTH) - - @token_auth.setter - def token_auth(self, v): - self.environ[self._TOKEN_AUTH] = v diff --git a/keystonemiddleware-moon/keystonemiddleware/auth_token/_revocations.py b/keystonemiddleware-moon/keystonemiddleware/auth_token/_revocations.py deleted file mode 100644 index a68356a8..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/auth_token/_revocations.py +++ /dev/null @@ -1,128 +0,0 @@ -# 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 datetime -import logging -import os - -from oslo_serialization import jsonutils -from oslo_utils import timeutils - -from keystonemiddleware.auth_token import _exceptions as exc -from keystonemiddleware.i18n import _ - -_LOG = logging.getLogger(__name__) - - -class Revocations(object): - _FILE_NAME = 'revoked.pem' - - def __init__(self, timeout, signing_directory, identity_server, - cms_verify, log=_LOG): - self._cache_timeout = timeout - self._signing_directory = signing_directory - self._identity_server = identity_server - self._cms_verify = cms_verify - self._log = log - - self._fetched_time_prop = None - self._list_prop = None - - @property - def _fetched_time(self): - if not self._fetched_time_prop: - # If the fetched list has been written to disk, use its - # modification time. - file_path = self._signing_directory.calc_path(self._FILE_NAME) - if os.path.exists(file_path): - mtime = os.path.getmtime(file_path) - fetched_time = datetime.datetime.utcfromtimestamp(mtime) - # Otherwise the list will need to be fetched. - else: - fetched_time = datetime.datetime.min - self._fetched_time_prop = fetched_time - return self._fetched_time_prop - - @_fetched_time.setter - def _fetched_time(self, value): - self._fetched_time_prop = value - - def _fetch(self): - revocation_list_data = self._identity_server.fetch_revocation_list() - return self._cms_verify(revocation_list_data) - - @property - def _list(self): - timeout = self._fetched_time + self._cache_timeout - list_is_current = timeutils.utcnow() < timeout - - if list_is_current: - # Load the list from disk if required - if not self._list_prop: - self._list_prop = jsonutils.loads( - self._signing_directory.read_file(self._FILE_NAME)) - else: - self._list = self._fetch() - return self._list_prop - - @_list.setter - def _list(self, value): - """Save a revocation list to memory and to disk. - - :param value: A json-encoded revocation list - - """ - self._list_prop = jsonutils.loads(value) - self._fetched_time = timeutils.utcnow() - self._signing_directory.write_file(self._FILE_NAME, value) - - def _is_revoked(self, token_id): - """Indicate whether the token_id appears in the revocation list.""" - revoked_tokens = self._list.get('revoked', None) - if not revoked_tokens: - return False - - revoked_ids = (x['id'] for x in revoked_tokens) - return token_id in revoked_ids - - def _any_revoked(self, token_ids): - for token_id in token_ids: - if self._is_revoked(token_id): - return True - return False - - def check(self, token_ids): - if self._any_revoked(token_ids): - self._log.debug('Token is marked as having been revoked') - raise exc.InvalidToken(_('Token has been revoked')) - - def check_by_audit_id(self, audit_ids): - """Check whether the audit_id appears in the revocation list. - - :raises keystonemiddleware.auth_token._exceptions.InvalidToken: - if the audit ID(s) appear in the revocation list. - - """ - revoked_tokens = self._list.get('revoked', None) - if not revoked_tokens: - # There's no revoked tokens, so nothing to do. - return - - # The audit_id may not be present in the revocation events because - # earlier versions of the identity server didn't provide them. - revoked_ids = set( - x['audit_id'] for x in revoked_tokens if 'audit_id' in x) - for audit_id in audit_ids: - if audit_id in revoked_ids: - self._log.debug( - 'Token is marked as having been revoked by audit id') - raise exc.InvalidToken(_('Token has been revoked')) diff --git a/keystonemiddleware-moon/keystonemiddleware/auth_token/_signing_dir.py b/keystonemiddleware-moon/keystonemiddleware/auth_token/_signing_dir.py deleted file mode 100644 index f8b1a410..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/auth_token/_signing_dir.py +++ /dev/null @@ -1,83 +0,0 @@ -# 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 logging -import os -import stat -import tempfile - -import six - -from keystonemiddleware.auth_token import _exceptions as exc -from keystonemiddleware.i18n import _, _LI, _LW - -_LOG = logging.getLogger(__name__) - - -class SigningDirectory(object): - - def __init__(self, directory_name=None, log=None): - self._log = log or _LOG - - if directory_name is None: - directory_name = tempfile.mkdtemp(prefix='keystone-signing-') - self._log.info( - _LI('Using %s as cache directory for signing certificate'), - directory_name) - self._directory_name = directory_name - - self._verify_signing_dir() - - def write_file(self, file_name, new_contents): - - # In Python2, encoding is slow so the following check avoids it if it - # is not absolutely necessary. - if isinstance(new_contents, six.text_type): - new_contents = new_contents.encode('utf-8') - - def _atomic_write(): - with tempfile.NamedTemporaryFile(dir=self._directory_name, - delete=False) as f: - f.write(new_contents) - os.rename(f.name, self.calc_path(file_name)) - - try: - _atomic_write() - except (OSError, IOError): - self._verify_signing_dir() - _atomic_write() - - def read_file(self, file_name): - path = self.calc_path(file_name) - open_kwargs = {'encoding': 'utf-8'} if six.PY3 else {} - with open(path, 'r', **open_kwargs) as f: - return f.read() - - def calc_path(self, file_name): - return os.path.join(self._directory_name, file_name) - - def _verify_signing_dir(self): - if os.path.isdir(self._directory_name): - if not os.access(self._directory_name, os.W_OK): - raise exc.ConfigurationError( - _('unable to access signing_dir %s') % - self._directory_name) - uid = os.getuid() - if os.stat(self._directory_name).st_uid != uid: - self._log.warning(_LW('signing_dir is not owned by %s'), uid) - current_mode = stat.S_IMODE(os.stat(self._directory_name).st_mode) - if current_mode != stat.S_IRWXU: - self._log.warning( - _LW('signing_dir mode is %(mode)s instead of %(need)s'), - {'mode': oct(current_mode), 'need': oct(stat.S_IRWXU)}) - else: - os.makedirs(self._directory_name, stat.S_IRWXU) diff --git a/keystonemiddleware-moon/keystonemiddleware/auth_token/_user_plugin.py b/keystonemiddleware-moon/keystonemiddleware/auth_token/_user_plugin.py deleted file mode 100644 index 93075c5c..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/auth_token/_user_plugin.py +++ /dev/null @@ -1,193 +0,0 @@ -# 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 keystoneclient.auth.identity import base as base_identity - - -class _TokenData(object): - """An abstraction to show auth_token consumers some of the token contents. - - This is a simplified and cleaned up keystoneclient.access.AccessInfo object - with which services relying on auth_token middleware can find details of - the current token. - """ - - def __init__(self, auth_ref): - self._stored_auth_ref = auth_ref - - @property - def _is_v2(self): - return self._stored_auth_ref.version == 'v2.0' - - @property - def auth_token(self): - """The token data used to authenticate requests. - - :returns: token data. - :rtype: str - """ - return self._stored_auth_ref.auth_token - - @property - def user_id(self): - """The user id associated with the authentication request. - - :rtype: str - """ - return self._stored_auth_ref.user_id - - @property - def user_domain_id(self): - """Returns the domain id of the user associated with the authentication - request. - - :returns: str - """ - # NOTE(jamielennox): v2 AccessInfo returns 'default' for domain_id - # because it can't know that value. We want to return None instead. - if self._is_v2: - return None - - return self._stored_auth_ref.user_domain_id - - @property - def project_id(self): - """The project ID associated with the authentication. - - :rtype: str - """ - return self._stored_auth_ref.project_id - - @property - def project_domain_id(self): - """The domain id of the project associated with the authentication - request. - - :rtype: str - """ - # NOTE(jamielennox): v2 AccessInfo returns 'default' for domain_id - # because it can't know that value. We want to return None instead. - if self._is_v2: - return None - - return self._stored_auth_ref.project_domain_id - - @property - def trust_id(self): - """Returns the trust id associated with the authentication request.. - - :rtype: str - """ - return self._stored_auth_ref.trust_id - - @property - def role_ids(self): - """Role ids of the user associated with the authentication request. - - :rtype: set(str) - """ - return frozenset(self._stored_auth_ref.role_ids or []) - - @property - def role_names(self): - """Role names of the user associated with the authentication request. - - :rtype: set(str) - """ - return frozenset(self._stored_auth_ref.role_names or []) - - @property - def _log_format(self): - roles = ','.join(self.role_names) - return 'user_id %s, project_id %s, roles %s' % (self.user_id, - self.project_id, - roles) - - -class UserAuthPlugin(base_identity.BaseIdentityPlugin): - """The incoming authentication credentials. - - A plugin that represents the incoming user credentials. This can be - consumed by applications. - - This object is not expected to be constructed directly by users. It is - created and passed by auth_token middleware and then can be used as the - authentication plugin when communicating via a session. - """ - - def __init__(self, user_auth_ref, serv_auth_ref): - super(UserAuthPlugin, self).__init__(reauthenticate=False) - - # NOTE(jamielennox): _user_auth_ref and _serv_auth_ref are private - # because this object ends up in the environ that is passed to the - # service, however they are used within auth_token middleware. - self._user_auth_ref = user_auth_ref - self._serv_auth_ref = serv_auth_ref - - self._user_data = None - self._serv_data = None - - @property - def has_user_token(self): - """Did this authentication request contained a user auth token.""" - return self._user_auth_ref is not None - - @property - def user(self): - """Authentication information about the user token. - - Will return None if a user token was not passed with this request. - """ - if not self.has_user_token: - return None - - if not self._user_data: - self._user_data = _TokenData(self._user_auth_ref) - - return self._user_data - - @property - def has_service_token(self): - """Did this authentication request contained a service token.""" - return self._serv_auth_ref is not None - - @property - def service(self): - """Authentication information about the service token. - - Will return None if a user token was not passed with this request. - """ - if not self.has_service_token: - return None - - if not self._serv_data: - self._serv_data = _TokenData(self._serv_auth_ref) - - return self._serv_data - - def get_auth_ref(self, session, **kwargs): - # NOTE(jamielennox): We will always use the auth_ref that was - # calculated by the middleware. reauthenticate=False in __init__ should - # ensure that this function is only called on the first access. - return self._user_auth_ref - - @property - def _log_format(self): - msg = [] - - if self.has_user_token: - msg.append('user: %s' % self.user._log_format) - - if self.has_service_token: - msg.append('service: %s' % self.service._log_format) - - return ' '.join(msg) diff --git a/keystonemiddleware-moon/keystonemiddleware/auth_token/_utils.py b/keystonemiddleware-moon/keystonemiddleware/auth_token/_utils.py deleted file mode 100644 index daed02dd..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/auth_token/_utils.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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 six.moves import urllib - - -def safe_quote(s): - """URL-encode strings that are not already URL-encoded.""" - return urllib.parse.quote(s) if s == urllib.parse.unquote(s) else s - - -class MiniResp(object): - - def __init__(self, error_message, env, headers=[]): - # The HEAD method is unique: it must never return a body, even if - # it reports an error (RFC-2616 clause 9.4). We relieve callers - # from varying the error responses depending on the method. - if env['REQUEST_METHOD'] == 'HEAD': - self.body = [''] - else: - self.body = [error_message.encode()] - self.headers = list(headers) - self.headers.append(('Content-type', 'text/plain')) diff --git a/keystonemiddleware-moon/keystonemiddleware/authz.py b/keystonemiddleware-moon/keystonemiddleware/authz.py deleted file mode 100644 index 93c0a7da..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/authz.py +++ /dev/null @@ -1,292 +0,0 @@ -# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors -# This software is distributed under the terms and conditions of the 'Apache-2.0' -# license which can be found in the file 'LICENSE' in this package distribution -# or at 'http://www.apache.org/licenses/LICENSE-2.0'. - -import webob -import logging -import json -import six -import requests -import re -import httplib - -from keystone import exception -from cStringIO import StringIO -from oslo_config import cfg -# from keystoneclient import auth -from keystonemiddleware.i18n import _, _LC, _LE, _LI, _LW - - -_OPTS = [ - cfg.StrOpt('auth_uri', - default="http://127.0.0.1:35357/v3", - help='Complete public Identity API endpoint.'), - cfg.StrOpt('auth_version', - default=None, - help='API version of the admin Identity API endpoint.'), - cfg.StrOpt('authz_login', - default="admin", - help='Name of the administrator who will connect to the Keystone Moon backends.'), - cfg.StrOpt('authz_password', - default="nomoresecrete", - help='Password of the administrator who will connect to the Keystone Moon backends.'), - cfg.StrOpt('logfile', - default="/tmp/authz.log", - help='File where logs goes.'), - ] - -_AUTHZ_GROUP = 'keystone_authz' -CONF = cfg.CONF -CONF.register_opts(_OPTS, group=_AUTHZ_GROUP) -CONF.debug = True -# auth.register_conf_options(CONF, _AUTHZ_GROUP) - -# from http://developer.openstack.org/api-ref-objectstorage-v1.html -SWIFT_API = ( - ("^/v1/(?P<account>[\w_-]+)$", "GET", "get_account_details"), - ("^/v1/(?P<account>[\w_-]+)$", "POST", "modify_account"), - ("^/v1/(?P<account>[\w_-]+)$", "HEAD", "get_account"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)$", "GET", "get_container"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)$", "PUT", "create_container"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)$", "POST", "update_container_metadata"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)$", "DELETE", "delete_container"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)$", "HEAD", "get_container_metadata"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "GET", "get_object"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "PUT", "create_object"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "COPY", "copy_object"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "POST", "update_object_metadata"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "DELETE", "delete_object"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "HEAD", "get_object_metadata"), -) - - -class ServiceError(Exception): - pass - - -class AuthZProtocol(object): - """Middleware that handles authenticating client calls.""" - - def __init__(self, app, conf): - self._LOG = logging.getLogger(conf.get('log_name', __name__)) - # FIXME: events are duplicated in log file - authz_fh = logging.FileHandler(CONF.keystone_authz["logfile"]) - self._LOG.setLevel(logging.DEBUG) - self._LOG.addHandler(authz_fh) - self._LOG.info(_LI('Starting Keystone authz middleware')) - self._conf = conf - self._app = app - - # MOON - self.auth_host = conf.get('auth_host', "127.0.0.1") - self.auth_port = int(conf.get('auth_port', 35357)) - auth_protocol = conf.get('auth_protocol', 'http') - self._request_uri = '%s://%s:%s' % (auth_protocol, self.auth_host, - self.auth_port) - - # SSL - insecure = conf.get('insecure', False) - cert_file = conf.get('certfile') - key_file = conf.get('keyfile') - - if insecure: - self._verify = False - elif cert_file and key_file: - self._verify = (cert_file, key_file) - elif cert_file: - self._verify = cert_file - else: - self._verify = None - - def get_url(self, url): - conn = httplib.HTTPConnection(self.auth_host, self.auth_port) - headers = { - "Content-type": "application/x-www-form-urlencoded", - "Accept": "text/plain,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", - } - conn.request('GET', url, headers=headers) - resp = conn.getresponse() - content = resp.read() - conn.close() - try: - return json.loads(content) - except ValueError: - return {"content": content} - - def _deny_request(self, code): - error_table = { - 'AccessDenied': (401, 'Access denied'), - 'InvalidURI': (400, 'Could not parse the specified URI'), - 'NotFound': (404, 'URI not found'), - 'Error': (500, 'Server error'), - } - resp = webob.Response(content_type='text/xml') - resp.status = error_table[code][0] - error_msg = ('<?xml version="1.0" encoding="UTF-8"?>\r\n' - '<Error>\r\n <Code>%s</Code>\r\n ' - '<Message>%s</Message>\r\n</Error>\r\n' % - (code, error_table[code][1])) - if six.PY3: - error_msg = error_msg.encode() - resp.body = error_msg - return resp - - def _get_authz_from_moon(self, tenant_id, subject_id, object_id, action_id): - try: - _url ='{}/v3/OS-MOON/authz/{}/{}/{}/{}'.format( - self._request_uri, - tenant_id, - subject_id, - object_id, - action_id) - self._LOG.info(_url) - response = requests.get(_url,verify=self._verify) - except requests.exceptions.RequestException as e: - self._LOG.error(_LI('HTTP connection exception: %s'), e) - resp = self._deny_request('InvalidURI') - raise ServiceError(resp) - - if response.status_code < 200 or response.status_code >= 300: - self._LOG.debug('Keystone reply error: status=%s reason=%s', - response.status_code, response.reason) - if response.status_code == 404: - resp = self._deny_request('NotFound') - elif response.status_code == 401: - resp = self._deny_request('AccessDenied') - else: - resp = self._deny_request('Error') - raise ServiceError(resp) - - return response - - def _find_openstack_component(self, env): - if "nova.context" in env.keys(): - return "nova" - elif "swift.authorize" in env.keys(): - return "swift" - else: - self._LOG.debug(env.keys()) - return "unknown" - - def _get_action(self, env, component): - """ Find and return the action of the request - Actually, find only Nova (start, destroy, pause, unpause, ...) and swift actions - - :param env: the request - :return: the action or "" - """ - action = "" - self.input = "" - if component == "nova": - length = int(env.get('CONTENT_LENGTH', '0')) - # TODO (dthom): compute for Nova, Cinder, Neutron, ... - action = "" - if length > 0: - try: - sub_action_object = env['wsgi.input'].read(length) - self.input = sub_action_object - action = json.loads(sub_action_object).keys()[0] - body = StringIO(sub_action_object) - env['wsgi.input'] = body - except ValueError: - self._LOG.error("Error in decoding sub-action") - except Exception as e: - self._LOG.error(str(e)) - if not action or len(action) == 0 and "servers/detail" in env["PATH_INFO"]: - return "list" - if component == "swift": - path = env["PATH_INFO"] - method = env["REQUEST_METHOD"] - for api in SWIFT_API: - if re.match(api[0], path) and method == api[1]: - action = api[2] - length = int(env.get('CONTENT_LENGTH', '0')) - # TODO (dthom): compute for Nova, Cinder, Neutron, ... - _action = "" - if length > 0: - try: - sub_action_object = env['wsgi.input'].read(length) - self.input = sub_action_object - _action = json.loads(sub_action_object).keys()[0] - body = StringIO(sub_action_object) - env['wsgi.input'] = body - self._LOG.debug("wsgi.input={}".format(_action)) - except ValueError: - self._LOG.error("Error in decoding sub-action") - except Exception as e: - self._LOG.error(str(e)) - return action - - @staticmethod - def _get_object(env, component): - if component == "nova": - # http://developer.openstack.org/api-ref-compute-v2.1.html - # nova URLs: - # /<tenant_id>/servers/<server_id> - # list details for server_id - # /<tenant_id>/servers/<server_id>/action - # execute action to server_id - # /<tenant_id>/servers/<server_id>/metadata - # show metadata from server_id - # /<tenant_id>/servers/details - # list servers - url = env.get("PATH_INFO").split("/") - if url[-1] == "detail": - return "servers" - try: - return url[3] - except IndexError: - return - elif component == "swift": - # remove the "/v1/" part of the URL - return env.get("PATH_INFO").split("/", 2)[-1].replace("/", "-").replace(".", "-") - return "unknown" - - def __call__(self, env, start_response): - req = webob.Request(env) - - subject_id = env.get("HTTP_X_USER_ID") - if not subject_id: - self._LOG.warning("No subject_id found for {}".format(env.get("PATH_INFO"))) - return self._app(env, start_response) - tenant_id = env.get("HTTP_X_TENANT_ID") - if not tenant_id: - self._LOG.warning("No tenant_id found for {}".format(env.get("PATH_INFO"))) - return self._app(env, start_response) - component = self._find_openstack_component(env) - action_id = self._get_action(env, component) - self._LOG.debug("\033[1m\033[31mrequest={}\033[m".format(env["PATH_INFO"])) - if action_id: - object_id = self._get_object(env, component) - if not object_id: - object_id = "servers" - self._LOG.debug("object_id={}".format(object_id)) - resp = self._get_authz_from_moon(tenant_id, subject_id, object_id, action_id) - if resp.status_code == 200: - answer = json.loads(resp.content) - self._LOG.debug("action_id={}/{}".format(component, action_id)) - self._LOG.debug(answer) - if "authz" in answer and answer["authz"]: - return self._app(env, start_response) - self._LOG.error("You are not authorized to do that! ({})".format(unicode(answer["comment"]))) - raise exception.Unauthorized(message="You are not authorized to do that! ({})".format(unicode(answer["comment"]))) - else: - self._LOG.error("Unable to request Moon ({}: {})".format(resp.status_code, resp.reason)) - else: - self._LOG.debug("No action_id found for {}".format(env.get("PATH_INFO"))) - # If action is not found, we can't raise an exception because a lots of action is missing - # in function self._get_action, it is not possible to get them all. - return self._app(env, start_response) - # raise exception.Unauthorized(message="You are not authorized to do that!") - - -def filter_factory(global_conf, **local_conf): - """Returns a WSGI filter app for use with paste.deploy.""" - conf = global_conf.copy() - conf.update(local_conf) - - def auth_filter(app): - return AuthZProtocol(app, conf) - return auth_filter - diff --git a/keystonemiddleware-moon/keystonemiddleware/ec2_token.py b/keystonemiddleware-moon/keystonemiddleware/ec2_token.py deleted file mode 100644 index df3bb6b0..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/ec2_token.py +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# 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. - -""" -Starting point for routing EC2 requests. - -""" - -from oslo_config import cfg -from oslo_serialization import jsonutils -import requests -import webob.dec -import webob.exc - -keystone_ec2_opts = [ - cfg.StrOpt('url', - default='http://localhost:5000/v2.0/ec2tokens', - help='URL to get token from ec2 request.'), - cfg.StrOpt('keyfile', - help='Required if EC2 server requires client certificate.'), - cfg.StrOpt('certfile', - help='Client certificate key filename. Required if EC2 server ' - 'requires client certificate.'), - cfg.StrOpt('cafile', - help='A PEM encoded certificate authority to use when ' - 'verifying HTTPS connections. Defaults to the system ' - 'CAs.'), - cfg.BoolOpt('insecure', default=False, - help='Disable SSL certificate verification.'), -] - -CONF = cfg.CONF -CONF.register_opts(keystone_ec2_opts, group='keystone_ec2_token') - - -class EC2Token(object): - """Authenticate an EC2 request with keystone and convert to token.""" - - def __init__(self, application): - super(EC2Token, self).__init__() - self._application = application - - @webob.dec.wsgify() - def __call__(self, req): - # Read request signature and access id. - try: - signature = req.params['Signature'] - access = req.params['AWSAccessKeyId'] - except KeyError: - raise webob.exc.HTTPBadRequest() - - # Make a copy of args for authentication and signature verification. - auth_params = dict(req.params) - # Not part of authentication args - auth_params.pop('Signature') - - # Authenticate the request. - creds = { - 'ec2Credentials': { - 'access': access, - 'signature': signature, - 'host': req.host, - 'verb': req.method, - 'path': req.path, - 'params': auth_params, - } - } - creds_json = jsonutils.dumps(creds) - headers = {'Content-Type': 'application/json'} - - verify = True - if CONF.keystone_ec2_token.insecure: - verify = False - elif CONF.keystone_ec2_token.cafile: - verify = CONF.keystone_ec2_token.cafile - - cert = None - if (CONF.keystone_ec2_token.certfile and - CONF.keystone_ec2_token.keyfile): - cert = (CONF.keystone_ec2_certfile, - CONF.keystone_ec2_token.keyfile) - elif CONF.keystone_ec2_token.certfile: - cert = CONF.keystone_ec2_token.certfile - - response = requests.post(CONF.keystone_ec2_token.url, data=creds_json, - headers=headers, verify=verify, cert=cert) - - # NOTE(vish): We could save a call to keystone by - # having keystone return token, tenant, - # user, and roles from this call. - - result = response.json() - try: - token_id = result['access']['token']['id'] - except (AttributeError, KeyError): - raise webob.exc.HTTPBadRequest() - - # Authenticated! - req.headers['X-Auth-Token'] = token_id - return self._application - - -def filter_factory(global_conf, **local_conf): - """Returns a WSGI filter app for use with paste.deploy.""" - conf = global_conf.copy() - conf.update(local_conf) - - def auth_filter(app): - return EC2Token(app, conf) - return auth_filter - - -def app_factory(global_conf, **local_conf): - conf = global_conf.copy() - conf.update(local_conf) - return EC2Token(None, conf) diff --git a/keystonemiddleware-moon/keystonemiddleware/echo/__init__.py b/keystonemiddleware-moon/keystonemiddleware/echo/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/echo/__init__.py +++ /dev/null diff --git a/keystonemiddleware-moon/keystonemiddleware/echo/__main__.py b/keystonemiddleware-moon/keystonemiddleware/echo/__main__.py deleted file mode 100644 index 88332f02..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/echo/__main__.py +++ /dev/null @@ -1,7 +0,0 @@ -from keystonemiddleware.echo import service - - -try: - service.EchoService() -except KeyboardInterrupt: - pass diff --git a/keystonemiddleware-moon/keystonemiddleware/echo/service.py b/keystonemiddleware-moon/keystonemiddleware/echo/service.py deleted file mode 100644 index 277cc027..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/echo/service.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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. - -""" -Run the echo service directly on port 8000 by executing the following:: - - $ python -m keystonemiddleware.echo - -When the ``auth_token`` module authenticates a request, the echo service -will respond with all the environment variables presented to it by this -module. -""" - -from wsgiref import simple_server - -from oslo_serialization import jsonutils -import six - -from keystonemiddleware import auth_token - - -def echo_app(environ, start_response): - """A WSGI application that echoes the CGI environment back to the user.""" - start_response('200 OK', [('Content-Type', 'application/json')]) - environment = dict((k, v) for k, v in six.iteritems(environ) - if k.startswith('HTTP_X_')) - yield jsonutils.dumps(environment) - - -class EchoService(object): - """Runs an instance of the echo app on init.""" - def __init__(self): - # hardcode any non-default configuration here - conf = {'auth_protocol': 'http', 'admin_token': 'ADMIN'} - app = auth_token.AuthProtocol(echo_app, conf) - server = simple_server.make_server('', 8000, app) - print('Serving on port 8000 (Ctrl+C to end)...') - server.serve_forever() diff --git a/keystonemiddleware-moon/keystonemiddleware/i18n.py b/keystonemiddleware-moon/keystonemiddleware/i18n.py deleted file mode 100644 index 0591284d..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/i18n.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2014 IBM Corp. -# -# 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. - -"""oslo.i18n integration module. - -See http://docs.openstack.org/developer/oslo.i18n/usage.html . - -""" - -import oslo_i18n as i18n - - -_translators = i18n.TranslatorFactory(domain='keystonemiddleware') - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# Translators for log levels. -# -# The abbreviated names are meant to reflect the usual use of a short -# name like '_'. The "L" is for "log" and the other letter comes from -# the level. -_LI = _translators.log_info -_LW = _translators.log_warning -_LE = _translators.log_error -_LC = _translators.log_critical diff --git a/keystonemiddleware-moon/keystonemiddleware/moon_agent.py b/keystonemiddleware-moon/keystonemiddleware/moon_agent.py deleted file mode 100644 index fd878fea..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/moon_agent.py +++ /dev/null @@ -1,310 +0,0 @@ -# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors -# This software is distributed under the terms and conditions of the 'Apache-2.0' -# license which can be found in the file 'LICENSE' in this package distribution -# or at 'http://www.apache.org/licenses/LICENSE-2.0'. - -import webob -import logging -import json -import re -import httplib - -from cStringIO import StringIO -from oslo_config import cfg -from keystonemiddleware.i18n import _, _LC, _LE, _LI, _LW - - -_OPTS = [ - cfg.StrOpt('auth_uri', - default="http://127.0.0.1:35357/v3", - help='Complete public Identity API endpoint.'), - cfg.StrOpt('auth_version', - default=None, - help='API version of the admin Identity API endpoint.'), - cfg.StrOpt('authz_login', - default="admin", - help='Name of the administrator who will connect to the Keystone Moon backends.'), - cfg.StrOpt('authz_password', - default="nomoresecrete", - help='Password of the administrator who will connect to the Keystone Moon backends.'), - cfg.StrOpt('logfile', - default="/tmp/authz.log", - help='File where logs goes.'), - ] - -_MOON_KEYSTONEMIDDLEWARE_AGENT_GROUP = 'moon_keystonemiddleware_agent' -CONF = cfg.CONF -CONF.register_opts(_OPTS, group=_MOON_KEYSTONEMIDDLEWARE_AGENT_GROUP) -CONF.debug = True - -# from http://developer.openstack.org/api-ref-objectstorage-v1.html -SWIFT_API = ( - ("^/v1/(?P<account>[\w_-]+)$", "GET", "get_account_details"), - ("^/v1/(?P<account>[\w_-]+)$", "POST", "modify_account"), - ("^/v1/(?P<account>[\w_-]+)$", "HEAD", "get_account"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)$", "GET", "get_container"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)$", "PUT", "create_container"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)$", "POST", "update_container_metadata"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)$", "DELETE", "delete_container"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)$", "HEAD", "get_container_metadata"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "GET", "get_object"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "PUT", "create_object"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "COPY", "copy_object"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "POST", "update_object_metadata"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "DELETE", "delete_object"), - ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "HEAD", "get_object_metadata"), -) - - -class MoonAgentKeystoneMiddleware(object): - """Moon's agent for KeystoneMiddleware to interact calls.""" - - post_data = { - "auth": { - "identity": { - "methods": [ - "password" - ], - "password": { - "user": { - "domain": { - "id": "Default" - }, - "name": "admin", - "password": "nomoresecrete" - } - } - } - } - } - - def __init__(self, app, conf): - self.conf = conf - self._LOG = logging.getLogger(conf.get('log_name', __name__)) - # FIXME: events are duplicated in log file - moon_agent_fh = logging.FileHandler(self.conf.get('logfile', "/tmp/keystonemiddleware.log")) - self._LOG.setLevel(logging.DEBUG) - self._LOG.addHandler(moon_agent_fh) - self._LOG.info(_LI('Starting Moon KeystoneMiddleware Agent')) - self._conf = conf - self._app = app - - # Auth - self.auth_host = conf.get('auth_host', "127.0.0.1") - self.auth_port = int(conf.get('auth_port', 35357)) - auth_protocol = conf.get('auth_protocol', 'http') - self._conf["_request_uri"] = '%s://%s:%s' % (auth_protocol, self.auth_host, # TODO: ??? for auth or authz - self.auth_port) - - # SSL - insecure = conf.get('insecure', False) - cert_file = conf.get('certfile') - key_file = conf.get('keyfile') - - if insecure: - self._conf["_verify"] = False - elif cert_file and key_file: - self._conf["_verify"] = (cert_file, key_file) - elif cert_file: - self._conf["_verify"] = cert_file - else: - self._conf["_verify"] = None - - # Moon registered mgrs - self.local_registered_mgr_dict = dict() # TODO: load from the sql backend - from keystonemiddleware.moon_mgrs.authz_mgr.authz_mgr import AuthzMgr - self.local_registered_mgr_dict["authz_mgr"] = AuthzMgr(self._conf) - - def __set_token(self): - self.post_data["auth"]["identity"]["password"]["user"]["name"] = self.conf.get('authz_login', "admin") - self.post_data["auth"]["identity"]["password"]["user"]["password"] = self.conf.get('authz_password', "nomoresecrete") - data = self.get_url("/v3/auth/tokens", post_data=self.post_data) - if "token" not in data: - raise Exception("Authentication problem ({})".format(data)) - self.token = data["token"] - - def __unset_token(self): - data = self.get_url("/v3/auth/tokens", method="DELETE", authtoken=True) - if "content" in data and len(data["content"]) > 0: - self._LOG.error("Error while unsetting token {}".format(data["content"])) - self.token = None - - def get_url(self, url, post_data=None, delete_data=None, method="GET", authtoken=None): - if post_data: - method = "POST" - if delete_data: - method = "DELETE" - self._LOG.debug("\033[32m{} {}\033[m".format(method, url)) - conn = httplib.HTTPConnection(self.auth_host, self.auth_port) - headers = { - "Content-type": "application/x-www-form-urlencoded", - "Accept": "text/plain,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", - } - if authtoken: - if self.x_subject_token: - if method == "DELETE": - headers["X-Subject-Token"] = self.x_subject_token - headers["X-Auth-Token"] = self.x_subject_token - else: - headers["X-Auth-Token"] = self.x_subject_token - if post_data: - method = "POST" - headers["Content-type"] = "application/json" - post_data = json.dumps(post_data) - conn.request(method, url, post_data, headers=headers) - elif delete_data: - method = "DELETE" - conn.request(method, url, json.dumps(delete_data), headers=headers) - else: - conn.request(method, url, headers=headers) - resp = conn.getresponse() - headers = resp.getheaders() - try: - self.x_subject_token = dict(headers)["x-subject-token"] - except KeyError: - pass - content = resp.read() - conn.close() - try: - return json.loads(content) - except ValueError: - return {"content": content} - - def _find_openstack_component(self, env): - if "nova.context" in env.keys(): - return "nova" - elif "swift.authorize" in env.keys(): - return "swift" - else: - self._LOG.debug(env.keys()) - return "unknown" - - def _get_action(self, env, component): - """ Find and return the action of the request - Actually, find only Nova action (start, destroy, pause, unpause, ...) - - :param env: the request - :return: the action or "" - """ - action = "" - self.input = "" - if component == "nova": - length = int(env.get('CONTENT_LENGTH', '0')) - # TODO (dthom): compute for Nova, Cinder, Neutron, ... - action = "" - if length > 0: - try: - sub_action_object = env['wsgi.input'].read(length) - self.input = sub_action_object - action = json.loads(sub_action_object).keys()[0] - body = StringIO(sub_action_object) - env['wsgi.input'] = body - except ValueError: - self._LOG.error("Error in decoding sub-action") - except Exception as e: - self._LOG.error(str(e)) - if not action or len(action) == 0 and "servers/detail" in env["PATH_INFO"]: - return "list" - if component == "swift": - path = env["PATH_INFO"] - method = env["REQUEST_METHOD"] - for api in SWIFT_API: - if re.match(api[0], path) and method == api[1]: - action = api[2] - length = int(env.get('CONTENT_LENGTH', '0')) - # TODO (dthom): compute for Nova, Cinder, Neutron, ... - _action = "" - if length > 0: - try: - sub_action_object = env['wsgi.input'].read(length) - self.input = sub_action_object - _action = json.loads(sub_action_object).keys()[0] - body = StringIO(sub_action_object) - env['wsgi.input'] = body - self._LOG.debug("wsgi.input={}".format(_action)) - except ValueError: - self._LOG.error("Error in decoding sub-action") - except Exception as e: - self._LOG.error(str(e)) - return action - - @staticmethod - def _get_resource(env, component): - if component == "nova": - # http://developer.openstack.org/api-ref-compute-v2.1.html - # nova URLs: - # /<tenant_id>/servers/<server_id> - # list details for server_id - # /<tenant_id>/servers/<server_id>/action - # execute action to server_id - # /<tenant_id>/servers/<server_id>/metadata - # show metadata from server_id - # /<tenant_id>/servers/details - # list servers - url = env.get("PATH_INFO").split("/") - if url[-1] == "detail": - return "servers" - try: - return url[3] - except IndexError: - return - elif component == "swift": - # remove the "/v1/" part of the URL - return env.get("PATH_INFO").split("/", 2)[-1].replace("/", "-").replace(".", "-") - return "unknown" - - def __call__(self, env, start_response): - req = webob.Request(env) - agent_data = dict() - - agent_data['user_id'] = env.get("HTTP_X_USER_ID") - if not agent_data['user_id']: - self._LOG.warning("No user_id found for {}".format(env.get("PATH_INFO"))) - return self._app(env, start_response) - - agent_data['tenant_id'] = env.get("HTTP_X_TENANT_ID") - if not agent_data['tenant_id']: - self._LOG.warning("No tenant_id found for {}".format(env.get("PATH_INFO"))) - return self._app(env, start_response) - - agent_data['OS_component'] = self._find_openstack_component(env) - - agent_data['action_id'] = self._get_action(env, agent_data['OS_component']) - if not agent_data['action_id']: - self._LOG.warning("No action_id found for {}".format(env.get("PATH_INFO"))) - # If action is not found, we can't raise an exception because a lots of action is missing - # in function self._get_action, it is not possible to get them all. - return self._app(env, start_response) - - agent_data['resource_id'] = self._get_resource(env, agent_data['OS_component']) - if not agent_data['resource_id'] : - self._LOG.warning("No resource_id found for {}".format(env.get("PATH_INFO"))) - return self._app(env, start_response) - else: - self._LOG.debug("resource_id={}".format(agent_data['resource_id'])) - - self.__set_token() - for _mgr in self.local_registered_mgr_dict: # TODO: update from the sql backend - self.local_registered_mgr_dict[_mgr].response_content = \ - json.loads(self.local_registered_mgr_dict[_mgr].treat_request(self.x_subject_token, agent_data).content) - self.__unset_token() - - aggregate_result = 1 - for _mgr in self.local_registered_mgr_dict: - if not self.local_registered_mgr_dict[_mgr].response_content: - aggregate_result = 0 - - if aggregate_result: - return self._app(env, start_response) - - -def filter_factory(global_conf, **local_conf): - """Returns a WSGI filter app for use with paste.deploy.""" - conf = global_conf.copy() - conf.update(local_conf) - - def moon_agent_filter(app): - return MoonAgentKeystoneMiddleware(app, conf) - return moon_agent_filter - - diff --git a/keystonemiddleware-moon/keystonemiddleware/moon_mgrs/__init__.py b/keystonemiddleware-moon/keystonemiddleware/moon_mgrs/__init__.py deleted file mode 100644 index 10d80bc9..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/moon_mgrs/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__author__ = 'wukong' diff --git a/keystonemiddleware-moon/keystonemiddleware/moon_mgrs/abe_mgr/__init__.py b/keystonemiddleware-moon/keystonemiddleware/moon_mgrs/abe_mgr/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/moon_mgrs/abe_mgr/__init__.py +++ /dev/null diff --git a/keystonemiddleware-moon/keystonemiddleware/moon_mgrs/authz_mgr/__init__.py b/keystonemiddleware-moon/keystonemiddleware/moon_mgrs/authz_mgr/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/moon_mgrs/authz_mgr/__init__.py +++ /dev/null diff --git a/keystonemiddleware-moon/keystonemiddleware/moon_mgrs/authz_mgr/authz_mgr.py b/keystonemiddleware-moon/keystonemiddleware/moon_mgrs/authz_mgr/authz_mgr.py deleted file mode 100644 index 9a0a4009..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/moon_mgrs/authz_mgr/authz_mgr.py +++ /dev/null @@ -1,106 +0,0 @@ -import logging -import requests -import six -import webob -import json - -from keystone import exception -from keystonemiddleware.i18n import _, _LC, _LE, _LI, _LW -from oslo_config import cfg - - -_OPTS = [ - cfg.StrOpt('authz_login', - default="admin", - help='Name of the administrator who will connect to the Keystone Moon backends.'), - cfg.StrOpt('authz_password', - default="nomoresecrete", - help='Password of the administrator who will connect to the Keystone Moon backends.'), - cfg.StrOpt('logfile', - default="/tmp/moon_authz_mgr.log", # TODO: update in paste.init - help='File where logs goes.'), - ] - -_MOON_AUTHZ_MGR_GROUP = 'moon_authz_mgr' -CONF = cfg.CONF -CONF.register_opts(_OPTS, group=_MOON_AUTHZ_MGR_GROUP) -CONF.debug = True - - -class ServiceError(Exception): - pass - - -class AuthzMgr(object): - - def __init__(self, conf): - self.conf = conf - self._LOG = logging.getLogger(conf.get('log_name', __name__)) - authz_mgr_fh = logging.FileHandler(self.conf.get('logfile', "/tmp/keystonemiddleware.log")) - self._LOG.setLevel(logging.DEBUG) - self._LOG.addHandler(authz_mgr_fh) - self.response_content = "" - - def _deny_request(self, code): - error_table = { - 'AccessDenied': (401, 'Access denied'), - 'InvalidURI': (400, 'Could not parse the specified URI'), - 'NotFound': (404, 'URI not found'), - 'Error': (500, 'Server error'), - } - resp = webob.Response(content_type='text/xml') - resp.status = error_table[code][0] - error_msg = ('<?xml version="1.0" encoding="UTF-8"?>\r\n' - '<Error>\r\n <Code>%s</Code>\r\n ' - '<Message>%s</Message>\r\n</Error>\r\n' % - (code, error_table[code][1])) - if six.PY3: - error_msg = error_msg.encode() - resp.body = error_msg - return resp - - def treat_request(self, auth_token, agent_data): - if not agent_data['resource_id']: - agent_data['resource_id'] = "servers" - - headers = {'X-Auth-Token': auth_token} - self._LOG.debug('X-Auth-Token={}'.format(auth_token)) - try: - _url = '{}/moon/authz/{}/{}/{}/{}'.format( - self.conf["_request_uri"], - agent_data['tenant_id'], - agent_data['user_id'], - agent_data['resource_id'], - agent_data['action_id']) - self._LOG.info(_url) - response = requests.get(_url, - headers=headers, - verify=self.conf["_verify"]) - except requests.exceptions.RequestException as e: - self._LOG.error(_LI('HTTP connection exception: %s'), e) - resp = self._deny_request('InvalidURI') - raise ServiceError(resp) - - if response.status_code < 200 or response.status_code >= 300: - self._LOG.debug('Keystone reply error: status=%s reason=%s', - response.status_code, response.reason) - if response.status_code == 404: - resp = self._deny_request('NotFound') - elif response.status_code == 401: - resp = self._deny_request('AccessDenied') - else: - resp = self._deny_request('Error') - raise ServiceError(resp) - - elif response.status_code == 200: - answer = json.loads(response.content) - self._LOG.debug("action_id={}/{}".format(agent_data['OS_component'], agent_data['action_id'])) - self._LOG.debug(answer) - if "authz" in answer and answer["authz"]: - return response - self._LOG.error("You are not authorized to do that! ({})".format(unicode(answer["comment"]))) - raise exception.Unauthorized(message="You are not authorized to do that! ({})".format(unicode(answer["comment"]))) - else: - self._LOG.error("Unable to request Moon ({}: {})".format(response.status_code, response.reason)) - - return response diff --git a/keystonemiddleware-moon/keystonemiddleware/openstack/__init__.py b/keystonemiddleware-moon/keystonemiddleware/openstack/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/openstack/__init__.py +++ /dev/null diff --git a/keystonemiddleware-moon/keystonemiddleware/openstack/common/__init__.py b/keystonemiddleware-moon/keystonemiddleware/openstack/common/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/openstack/common/__init__.py +++ /dev/null diff --git a/keystonemiddleware-moon/keystonemiddleware/openstack/common/memorycache.py b/keystonemiddleware-moon/keystonemiddleware/openstack/common/memorycache.py deleted file mode 100644 index e72c26df..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/openstack/common/memorycache.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# 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. - -"""Super simple fake memcache client.""" - -import copy - -from oslo_config import cfg -from oslo_utils import timeutils - -memcache_opts = [ - cfg.ListOpt('memcached_servers', - help='Memcached servers or None for in process cache.'), -] - -CONF = cfg.CONF -CONF.register_opts(memcache_opts) - - -def list_opts(): - """Entry point for oslo-config-generator.""" - return [(None, copy.deepcopy(memcache_opts))] - - -def get_client(memcached_servers=None): - client_cls = Client - - if not memcached_servers: - memcached_servers = CONF.memcached_servers - if memcached_servers: - import memcache - client_cls = memcache.Client - - return client_cls(memcached_servers, debug=0) - - -class Client(object): - """Replicates a tiny subset of memcached client interface.""" - - def __init__(self, *args, **kwargs): - """Ignores the passed in args.""" - self.cache = {} - - def get(self, key): - """Retrieves the value for a key or None. - - This expunges expired keys during each get. - """ - - now = timeutils.utcnow_ts() - for k in list(self.cache): - (timeout, _value) = self.cache[k] - if timeout and now >= timeout: - del self.cache[k] - - return self.cache.get(key, (0, None))[1] - - def set(self, key, value, time=0, min_compress_len=0): - """Sets the value for a key.""" - timeout = 0 - if time != 0: - timeout = timeutils.utcnow_ts() + time - self.cache[key] = (timeout, value) - return True - - def add(self, key, value, time=0, min_compress_len=0): - """Sets the value for a key if it doesn't exist.""" - if self.get(key) is not None: - return False - return self.set(key, value, time, min_compress_len) - - def incr(self, key, delta=1): - """Increments the value for a key.""" - value = self.get(key) - if value is None: - return None - new_value = int(value) + delta - self.cache[key] = (self.cache[key][0], str(new_value)) - return new_value - - def delete(self, key, time=0): - """Deletes the value associated with a key.""" - if key in self.cache: - del self.cache[key] diff --git a/keystonemiddleware-moon/keystonemiddleware/opts.py b/keystonemiddleware-moon/keystonemiddleware/opts.py deleted file mode 100644 index 62a7dabf..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/opts.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright (c) 2014 OpenStack Foundation. -# -# 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. - -__all__ = [ - 'list_auth_token_opts', -] - -import copy - -import keystonemiddleware.auth_token -from keystonemiddleware.auth_token import _auth -from keystonemiddleware.auth_token import _base - -auth_token_opts = [ - (_base.AUTHTOKEN_GROUP, - keystonemiddleware.auth_token._OPTS + - _auth.AuthTokenPlugin.get_options()) -] - - -def list_auth_token_opts(): - """Return a list of oslo_config options available in auth_token middleware. - - The returned list includes all oslo_config options which may be registered - at runtime by the project. - - Each element of the list is a tuple. The first element is the name of the - group under which the list of elements in the second element will be - registered. A group name of None corresponds to the [DEFAULT] group in - config files. - - This function is also discoverable via the entry point - 'keystonemiddleware.auth_token' under the 'oslo.config.opts' - namespace. - - The purpose of this is to allow tools like the Oslo sample config file - generator to discover the options exposed to users by this middleware. - - :returns: a list of (group_name, opts) tuples - """ - return [(g, copy.deepcopy(o)) for g, o in auth_token_opts] diff --git a/keystonemiddleware-moon/keystonemiddleware/s3_token.py b/keystonemiddleware-moon/keystonemiddleware/s3_token.py deleted file mode 100644 index d71ab276..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/s3_token.py +++ /dev/null @@ -1,270 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2011,2012 Akira YOSHIYAMA <akirayoshiyama@gmail.com> -# 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. - -# This source code is based ./auth_token.py and ./ec2_token.py. -# See them for their copyright. - -""" -S3 Token Middleware - -This WSGI component: - -* Gets a request from the swift3 middleware with an S3 Authorization - access key. -* Validates s3 token in Keystone. -* Transforms the account name to AUTH_%(tenant_name). - -""" - -import logging -import webob - -from oslo_serialization import jsonutils -from oslo_utils import strutils -import requests -import six -from six.moves import urllib - -from keystonemiddleware.i18n import _, _LI - - -PROTOCOL_NAME = 'S3 Token Authentication' - - -# TODO(kun): remove it after oslo merge this. -def _split_path(path, minsegs=1, maxsegs=None, rest_with_last=False): - """Validate and split the given HTTP request path. - - **Examples**:: - - ['a'] = _split_path('/a') - ['a', None] = _split_path('/a', 1, 2) - ['a', 'c'] = _split_path('/a/c', 1, 2) - ['a', 'c', 'o/r'] = _split_path('/a/c/o/r', 1, 3, True) - - :param path: HTTP Request path to be split - :param minsegs: Minimum number of segments to be extracted - :param maxsegs: Maximum number of segments to be extracted - :param rest_with_last: If True, trailing data will be returned as part - of last segment. If False, and there is - trailing data, raises ValueError. - :returns: list of segments with a length of maxsegs (non-existent - segments will return as None) - :raises: ValueError if given an invalid path - """ - if not maxsegs: - maxsegs = minsegs - if minsegs > maxsegs: - raise ValueError(_('minsegs > maxsegs: %(min)d > %(max)d)') % - {'min': minsegs, 'max': maxsegs}) - if rest_with_last: - segs = path.split('/', maxsegs) - minsegs += 1 - maxsegs += 1 - count = len(segs) - if (segs[0] or count < minsegs or count > maxsegs or - '' in segs[1:minsegs]): - raise ValueError(_('Invalid path: %s') % urllib.parse.quote(path)) - else: - minsegs += 1 - maxsegs += 1 - segs = path.split('/', maxsegs) - count = len(segs) - if (segs[0] or count < minsegs or count > maxsegs + 1 or - '' in segs[1:minsegs] or - (count == maxsegs + 1 and segs[maxsegs])): - raise ValueError(_('Invalid path: %s') % urllib.parse.quote(path)) - segs = segs[1:maxsegs] - segs.extend([None] * (maxsegs - 1 - len(segs))) - return segs - - -class ServiceError(Exception): - pass - - -class S3Token(object): - """Middleware that handles S3 authentication.""" - - def __init__(self, app, conf): - """Common initialization code.""" - self._app = app - self._logger = logging.getLogger(conf.get('log_name', __name__)) - self._logger.debug('Starting the %s component', PROTOCOL_NAME) - self._reseller_prefix = conf.get('reseller_prefix', 'AUTH_') - # where to find the auth service (we use this to validate tokens) - - auth_host = conf.get('auth_host') - auth_port = int(conf.get('auth_port', 35357)) - auth_protocol = conf.get('auth_protocol', 'https') - - self._request_uri = '%s://%s:%s' % (auth_protocol, auth_host, - auth_port) - - # SSL - insecure = strutils.bool_from_string(conf.get('insecure', False)) - cert_file = conf.get('certfile') - key_file = conf.get('keyfile') - - if insecure: - self._verify = False - elif cert_file and key_file: - self._verify = (cert_file, key_file) - elif cert_file: - self._verify = cert_file - else: - self._verify = None - - def _deny_request(self, code): - error_table = { - 'AccessDenied': (401, 'Access denied'), - 'InvalidURI': (400, 'Could not parse the specified URI'), - } - resp = webob.Response(content_type='text/xml') - resp.status = error_table[code][0] - error_msg = ('<?xml version="1.0" encoding="UTF-8"?>\r\n' - '<Error>\r\n <Code>%s</Code>\r\n ' - '<Message>%s</Message>\r\n</Error>\r\n' % - (code, error_table[code][1])) - if six.PY3: - error_msg = error_msg.encode() - resp.body = error_msg - return resp - - def _json_request(self, creds_json): - headers = {'Content-Type': 'application/json'} - try: - response = requests.post('%s/v2.0/s3tokens' % self._request_uri, - headers=headers, data=creds_json, - verify=self._verify) - except requests.exceptions.RequestException as e: - self._logger.info(_LI('HTTP connection exception: %s'), e) - resp = self._deny_request('InvalidURI') - raise ServiceError(resp) - - if response.status_code < 200 or response.status_code >= 300: - self._logger.debug('Keystone reply error: status=%s reason=%s', - response.status_code, response.reason) - resp = self._deny_request('AccessDenied') - raise ServiceError(resp) - - return response - - def __call__(self, environ, start_response): - """Handle incoming request. authenticate and send downstream.""" - req = webob.Request(environ) - self._logger.debug('Calling S3Token middleware.') - - try: - parts = _split_path(req.path, 1, 4, True) - version, account, container, obj = parts - except ValueError: - msg = 'Not a path query, skipping.' - self._logger.debug(msg) - return self._app(environ, start_response) - - # Read request signature and access id. - if 'Authorization' not in req.headers: - msg = 'No Authorization header. skipping.' - self._logger.debug(msg) - return self._app(environ, start_response) - - token = req.headers.get('X-Auth-Token', - req.headers.get('X-Storage-Token')) - if not token: - msg = 'You did not specify an auth or a storage token. skipping.' - self._logger.debug(msg) - return self._app(environ, start_response) - - auth_header = req.headers['Authorization'] - try: - access, signature = auth_header.split(' ')[-1].rsplit(':', 1) - except ValueError: - msg = 'You have an invalid Authorization header: %s' - self._logger.debug(msg, auth_header) - return self._deny_request('InvalidURI')(environ, start_response) - - # NOTE(chmou): This is to handle the special case with nova - # when we have the option s3_affix_tenant. We will force it to - # connect to another account than the one - # authenticated. Before people start getting worried about - # security, I should point that we are connecting with - # username/token specified by the user but instead of - # connecting to its own account we will force it to go to an - # another account. In a normal scenario if that user don't - # have the reseller right it will just fail but since the - # reseller account can connect to every account it is allowed - # by the swift_auth middleware. - force_tenant = None - if ':' in access: - access, force_tenant = access.split(':') - - # Authenticate request. - creds = {'credentials': {'access': access, - 'token': token, - 'signature': signature}} - creds_json = jsonutils.dumps(creds) - self._logger.debug('Connecting to Keystone sending this JSON: %s', - creds_json) - # NOTE(vish): We could save a call to keystone by having - # keystone return token, tenant, user, and roles - # from this call. - # - # NOTE(chmou): We still have the same problem we would need to - # change token_auth to detect if we already - # identified and not doing a second query and just - # pass it through to swiftauth in this case. - try: - resp = self._json_request(creds_json) - except ServiceError as e: - resp = e.args[0] - msg = 'Received error, exiting middleware with error: %s' - self._logger.debug(msg, resp.status_code) - return resp(environ, start_response) - - self._logger.debug('Keystone Reply: Status: %d, Output: %s', - resp.status_code, resp.content) - - try: - identity_info = resp.json() - token_id = str(identity_info['access']['token']['id']) - tenant = identity_info['access']['token']['tenant'] - except (ValueError, KeyError): - error = 'Error on keystone reply: %d %s' - self._logger.debug(error, resp.status_code, resp.content) - return self._deny_request('InvalidURI')(environ, start_response) - - req.headers['X-Auth-Token'] = token_id - tenant_to_connect = force_tenant or tenant['id'] - if six.PY2 and isinstance(tenant_to_connect, six.text_type): - tenant_to_connect = tenant_to_connect.encode('utf-8') - self._logger.debug('Connecting with tenant: %s', tenant_to_connect) - new_tenant_name = '%s%s' % (self._reseller_prefix, tenant_to_connect) - environ['PATH_INFO'] = environ['PATH_INFO'].replace(account, - new_tenant_name) - return self._app(environ, start_response) - - -def filter_factory(global_conf, **local_conf): - """Returns a WSGI filter app for use with paste.deploy.""" - conf = global_conf.copy() - conf.update(local_conf) - - def auth_filter(app): - return S3Token(app, conf) - return auth_filter diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/__init__.py b/keystonemiddleware-moon/keystonemiddleware/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/__init__.py +++ /dev/null diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/__init__.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/__init__.py +++ /dev/null diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/__init__.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/__init__.py +++ /dev/null diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/base.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/base.py deleted file mode 100644 index d76572a8..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/base.py +++ /dev/null @@ -1,73 +0,0 @@ -# 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 logging - -import fixtures -from oslo_config import cfg -from oslo_config import fixture as cfg_fixture -from requests_mock.contrib import fixture as rm_fixture -import six -import webob.dec - -from keystonemiddleware import auth_token -from keystonemiddleware.tests.unit import utils - - -class BaseAuthTokenTestCase(utils.BaseTestCase): - - def setUp(self): - super(BaseAuthTokenTestCase, self).setUp() - self.requests_mock = self.useFixture(rm_fixture.Fixture()) - self.logger = fixtures.FakeLogger(level=logging.DEBUG) - self.cfg = self.useFixture(cfg_fixture.Config(conf=cfg.ConfigOpts())) - - def create_middleware(self, cb, conf=None, use_global_conf=False): - - @webob.dec.wsgify - def _do_cb(req): - return cb(req) - - if use_global_conf: - opts = conf or {} - else: - opts = { - 'oslo_config_project': 'keystonemiddleware', - 'oslo_config_config': self.cfg.conf, - } - opts.update(conf or {}) - - return auth_token.AuthProtocol(_do_cb, opts) - - def create_simple_middleware(self, - status='200 OK', - body='', - headers=None, - **kwargs): - def cb(req): - resp = webob.Response(body, status) - resp.headers.update(headers or {}) - return resp - - return self.create_middleware(cb, **kwargs) - - @classmethod - def call(cls, middleware, method='GET', path='/', headers=None): - req = webob.Request.blank(path) - req.method = method - - for k, v in six.iteritems(headers or {}): - req.headers[k] = v - - resp = req.get_response(middleware) - resp.request = req - return resp diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_auth.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_auth.py deleted file mode 100644 index d6ebc9a0..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_auth.py +++ /dev/null @@ -1,102 +0,0 @@ -# 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 logging -import uuid - -from keystoneclient import auth -from keystoneclient import fixture -from keystoneclient import session -from requests_mock.contrib import fixture as rm_fixture -import six - -from keystonemiddleware.auth_token import _auth -from keystonemiddleware.tests.unit import utils - - -class DefaultAuthPluginTests(utils.BaseTestCase): - - def new_plugin(self, auth_host=None, auth_port=None, auth_protocol=None, - auth_admin_prefix=None, admin_user=None, - admin_password=None, admin_tenant_name=None, - admin_token=None, identity_uri=None, log=None): - if not log: - log = self.logger - - return _auth.AuthTokenPlugin.load_from_options( - auth_host=auth_host, - auth_port=auth_port, - auth_protocol=auth_protocol, - auth_admin_prefix=auth_admin_prefix, - admin_user=admin_user, - admin_password=admin_password, - admin_tenant_name=admin_tenant_name, - admin_token=admin_token, - identity_uri=identity_uri, - log=log) - - def setUp(self): - super(DefaultAuthPluginTests, self).setUp() - - self.stream = six.StringIO() - self.logger = logging.getLogger(__name__) - self.session = session.Session() - self.requests_mock = self.useFixture(rm_fixture.Fixture()) - - def test_auth_uri_from_fragments(self): - auth_protocol = 'http' - auth_host = 'testhost' - auth_port = 8888 - auth_admin_prefix = 'admin' - - expected = '%s://%s:%d/admin' % (auth_protocol, auth_host, auth_port) - - plugin = self.new_plugin(auth_host=auth_host, - auth_protocol=auth_protocol, - auth_port=auth_port, - auth_admin_prefix=auth_admin_prefix) - - self.assertEqual(expected, - plugin.get_endpoint(self.session, - interface=auth.AUTH_INTERFACE)) - - def test_identity_uri_overrides_fragments(self): - identity_uri = 'http://testhost:8888/admin' - plugin = self.new_plugin(identity_uri=identity_uri, - auth_host='anotherhost', - auth_port=9999, - auth_protocol='ftp') - - self.assertEqual(identity_uri, - plugin.get_endpoint(self.session, - interface=auth.AUTH_INTERFACE)) - - def test_with_admin_token(self): - token = uuid.uuid4().hex - plugin = self.new_plugin(identity_uri='http://testhost:8888/admin', - admin_token=token) - self.assertEqual(token, plugin.get_token(self.session)) - - def test_with_user_pass(self): - base_uri = 'http://testhost:8888/admin' - token = fixture.V2Token() - admin_tenant_name = uuid.uuid4().hex - - self.requests_mock.post(base_uri + '/v2.0/tokens', - json=token) - - plugin = self.new_plugin(identity_uri=base_uri, - admin_user=uuid.uuid4().hex, - admin_password=uuid.uuid4().hex, - admin_tenant_name=admin_tenant_name) - - self.assertEqual(token.token_id, plugin.get_token(self.session)) diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py deleted file mode 100644 index e6a495f4..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py +++ /dev/null @@ -1,2634 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# 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 datetime -import json -import logging -import os -import shutil -import stat -import tempfile -import time -import uuid -import warnings - -import fixtures -from keystoneclient import auth -from keystoneclient.common import cms -from keystoneclient import exceptions -from keystoneclient import fixture -from keystoneclient import session -import mock -from oslo_config import cfg -from oslo_serialization import jsonutils -from oslo_utils import timeutils -from oslotest import createfile -import six -import testresources -import testtools -from testtools import matchers -import webob -import webob.dec - -from keystonemiddleware import auth_token -from keystonemiddleware.auth_token import _base -from keystonemiddleware.auth_token import _exceptions as exc -from keystonemiddleware.auth_token import _revocations -from keystonemiddleware.openstack.common import memorycache -from keystonemiddleware.tests.unit.auth_token import base -from keystonemiddleware.tests.unit import client_fixtures -from keystonemiddleware.tests.unit import utils - - -EXPECTED_V2_DEFAULT_ENV_RESPONSE = { - 'HTTP_X_IDENTITY_STATUS': 'Confirmed', - 'HTTP_X_TENANT_ID': 'tenant_id1', - 'HTTP_X_TENANT_NAME': 'tenant_name1', - 'HTTP_X_USER_ID': 'user_id1', - 'HTTP_X_USER_NAME': 'user_name1', - 'HTTP_X_ROLES': 'role1,role2', - 'HTTP_X_USER': 'user_name1', # deprecated (diablo-compat) - 'HTTP_X_TENANT': 'tenant_name1', # deprecated (diablo-compat) - 'HTTP_X_ROLE': 'role1,role2', # deprecated (diablo-compat) -} - -EXPECTED_V2_DEFAULT_SERVICE_ENV_RESPONSE = { - 'HTTP_X_SERVICE_IDENTITY_STATUS': 'Confirmed', - 'HTTP_X_SERVICE_PROJECT_ID': 'service_project_id1', - 'HTTP_X_SERVICE_PROJECT_NAME': 'service_project_name1', - 'HTTP_X_SERVICE_USER_ID': 'service_user_id1', - 'HTTP_X_SERVICE_USER_NAME': 'service_user_name1', - 'HTTP_X_SERVICE_ROLES': 'service_role1,service_role2', -} - -EXPECTED_V3_DEFAULT_ENV_ADDITIONS = { - 'HTTP_X_PROJECT_DOMAIN_ID': 'domain_id1', - 'HTTP_X_PROJECT_DOMAIN_NAME': 'domain_name1', - 'HTTP_X_USER_DOMAIN_ID': 'domain_id1', - 'HTTP_X_USER_DOMAIN_NAME': 'domain_name1', -} - -EXPECTED_V3_DEFAULT_SERVICE_ENV_ADDITIONS = { - 'HTTP_X_SERVICE_PROJECT_DOMAIN_ID': 'service_domain_id1', - 'HTTP_X_SERVICE_PROJECT_DOMAIN_NAME': 'service_domain_name1', - 'HTTP_X_SERVICE_USER_DOMAIN_ID': 'service_domain_id1', - 'HTTP_X_SERVICE_USER_DOMAIN_NAME': 'service_domain_name1' -} - - -BASE_HOST = 'https://keystone.example.com:1234' -BASE_URI = '%s/testadmin' % BASE_HOST -FAKE_ADMIN_TOKEN_ID = 'admin_token2' -FAKE_ADMIN_TOKEN = jsonutils.dumps( - {'access': {'token': {'id': FAKE_ADMIN_TOKEN_ID, - 'expires': '2022-10-03T16:58:01Z'}}}) - -VERSION_LIST_v3 = fixture.DiscoveryList(href=BASE_URI) -VERSION_LIST_v2 = fixture.DiscoveryList(v3=False, href=BASE_URI) - -ERROR_TOKEN = '7ae290c2a06244c4b41692eb4e9225f2' -MEMCACHED_SERVERS = ['localhost:11211'] -MEMCACHED_AVAILABLE = None - - -def memcached_available(): - """Do a sanity check against memcached. - - Returns ``True`` if the following conditions are met (otherwise, returns - ``False``): - - - ``python-memcached`` is installed - - a usable ``memcached`` instance is available via ``MEMCACHED_SERVERS`` - - the client is able to set and get a key/value pair - - """ - global MEMCACHED_AVAILABLE - - if MEMCACHED_AVAILABLE is None: - try: - import memcache - c = memcache.Client(MEMCACHED_SERVERS) - c.set('ping', 'pong', time=1) - MEMCACHED_AVAILABLE = c.get('ping') == 'pong' - except ImportError: - MEMCACHED_AVAILABLE = False - - return MEMCACHED_AVAILABLE - - -def cleanup_revoked_file(filename): - try: - os.remove(filename) - except OSError: - pass - - -def strtime(at=None): - at = at or timeutils.utcnow() - return at.strftime(timeutils.PERFECT_TIME_FORMAT) - - -class TimezoneFixture(fixtures.Fixture): - @staticmethod - def supported(): - # tzset is only supported on Unix. - return hasattr(time, 'tzset') - - def __init__(self, new_tz): - super(TimezoneFixture, self).__init__() - self.tz = new_tz - self.old_tz = os.environ.get('TZ') - - def setUp(self): - super(TimezoneFixture, self).setUp() - if not self.supported(): - raise NotImplementedError('timezone override is not supported.') - os.environ['TZ'] = self.tz - time.tzset() - self.addCleanup(self.cleanup) - - def cleanup(self): - if self.old_tz is not None: - os.environ['TZ'] = self.old_tz - elif 'TZ' in os.environ: - del os.environ['TZ'] - time.tzset() - - -class TimeFixture(fixtures.Fixture): - - def __init__(self, new_time, normalize=True): - super(TimeFixture, self).__init__() - if isinstance(new_time, six.string_types): - new_time = timeutils.parse_isotime(new_time) - if normalize: - new_time = timeutils.normalize_time(new_time) - self.new_time = new_time - - def setUp(self): - super(TimeFixture, self).setUp() - timeutils.set_time_override(self.new_time) - self.addCleanup(timeutils.clear_time_override) - - -class FakeApp(object): - """This represents a WSGI app protected by the auth_token middleware.""" - - SUCCESS = b'SUCCESS' - FORBIDDEN = b'FORBIDDEN' - expected_env = {} - - def __init__(self, expected_env=None, need_service_token=False): - self.expected_env = dict(EXPECTED_V2_DEFAULT_ENV_RESPONSE) - - if expected_env: - self.expected_env.update(expected_env) - - self.need_service_token = need_service_token - - @webob.dec.wsgify - def __call__(self, req): - for k, v in self.expected_env.items(): - assert req.environ[k] == v, '%s != %s' % (req.environ[k], v) - - resp = webob.Response() - - if (req.environ.get('HTTP_X_IDENTITY_STATUS') == 'Invalid' and - req.environ['HTTP_X_SERVICE_IDENTITY_STATUS'] == 'Invalid'): - # Simulate delayed auth forbidding access with arbitrary status - # code to differentiate checking this code path - resp.status = 419 - resp.body = FakeApp.FORBIDDEN - elif req.environ.get('HTTP_X_SERVICE_IDENTITY_STATUS') == 'Invalid': - # Simulate delayed auth forbidding access with arbitrary status - # code to differentiate checking this code path - resp.status = 420 - resp.body = FakeApp.FORBIDDEN - elif req.environ['HTTP_X_IDENTITY_STATUS'] == 'Invalid': - # Simulate delayed auth forbidding access - resp.status = 403 - resp.body = FakeApp.FORBIDDEN - elif (self.need_service_token is True and - req.environ.get('HTTP_X_SERVICE_TOKEN') is None): - # Simulate requiring composite auth - # Arbitrary value to allow checking this code path - resp.status = 418 - resp.body = FakeApp.FORBIDDEN - else: - resp.body = FakeApp.SUCCESS - - return resp - - -class v3FakeApp(FakeApp): - """This represents a v3 WSGI app protected by the auth_token middleware.""" - - def __init__(self, expected_env=None, need_service_token=False): - - # with v3 additions, these are for the DEFAULT TOKEN - v3_default_env_additions = dict(EXPECTED_V3_DEFAULT_ENV_ADDITIONS) - if expected_env: - v3_default_env_additions.update(expected_env) - super(v3FakeApp, self).__init__(expected_env=v3_default_env_additions, - need_service_token=need_service_token) - - -class CompositeBase(object): - """Base composite auth object with common service token environment.""" - - def __init__(self, expected_env=None): - comp_expected_env = dict(EXPECTED_V2_DEFAULT_SERVICE_ENV_RESPONSE) - - if expected_env: - comp_expected_env.update(expected_env) - - super(CompositeBase, self).__init__( - expected_env=comp_expected_env, need_service_token=True) - - -class CompositeFakeApp(CompositeBase, FakeApp): - """A fake v2 WSGI app protected by composite auth_token middleware.""" - - def __init__(self, expected_env): - super(CompositeFakeApp, self).__init__(expected_env=expected_env) - - -class v3CompositeFakeApp(CompositeBase, v3FakeApp): - """A fake v3 WSGI app protected by composite auth_token middleware.""" - - def __init__(self, expected_env=None): - - # with v3 additions, these are for the DEFAULT SERVICE TOKEN - v3_default_service_env_additions = dict( - EXPECTED_V3_DEFAULT_SERVICE_ENV_ADDITIONS) - - if expected_env: - v3_default_service_env_additions.update(expected_env) - - super(v3CompositeFakeApp, self).__init__( - v3_default_service_env_additions) - - -class BaseAuthTokenMiddlewareTest(base.BaseAuthTokenTestCase): - """Base test class for auth_token middleware. - - All the tests allow for running with auth_token - configured for receiving v2 or v3 tokens, with the - choice being made by passing configuration data into - setUp(). - - The base class will, by default, run all the tests - expecting v2 token formats. Child classes can override - this to specify, for instance, v3 format. - - """ - def setUp(self, expected_env=None, auth_version=None, fake_app=None): - super(BaseAuthTokenMiddlewareTest, self).setUp() - - self.expected_env = expected_env or dict() - self.fake_app = fake_app or FakeApp - self.middleware = None - - signing_dir = self._setup_signing_directory() - - self.conf = { - 'identity_uri': 'https://keystone.example.com:1234/testadmin/', - 'signing_dir': signing_dir, - 'auth_version': auth_version, - 'auth_uri': 'https://keystone.example.com:1234', - 'admin_user': uuid.uuid4().hex, - } - - self.auth_version = auth_version - self.response_status = None - self.response_headers = None - - # NOTE(gyee): For this test suite and for the stable liberty branch - # only, we will ignore deprecated calls that keystonemiddleware makes. - warnings.filterwarnings('ignore', category=DeprecationWarning, - module='^keystonemiddleware\\.') - - def call_middleware(self, **kwargs): - return self.call(self.middleware, **kwargs) - - def _setup_signing_directory(self): - directory_name = self.useFixture(fixtures.TempDir()).path - - # Copy the sample certificate files into the temporary directory. - for filename in ['cacert.pem', 'signing_cert.pem', ]: - shutil.copy2(os.path.join(client_fixtures.CERTDIR, filename), - os.path.join(directory_name, filename)) - - return directory_name - - def set_middleware(self, expected_env=None, conf=None): - """Configure the class ready to call the auth_token middleware. - - Set up the various fake items needed to run the middleware. - Individual tests that need to further refine these can call this - function to override the class defaults. - - """ - if conf: - self.conf.update(conf) - - if expected_env: - self.expected_env.update(expected_env) - - self.middleware = auth_token.AuthProtocol( - self.fake_app(self.expected_env), self.conf) - - self.middleware._revocations._list = jsonutils.dumps( - {"revoked": [], "extra": "success"}) - - def update_expected_env(self, expected_env={}): - self.middleware._app.expected_env.update(expected_env) - - def purge_token_expected_env(self): - for key in six.iterkeys(self.token_expected_env): - del self.middleware._app.expected_env[key] - - def purge_service_token_expected_env(self): - for key in six.iterkeys(self.service_token_expected_env): - del self.middleware._app.expected_env[key] - - def assertLastPath(self, path): - if path: - self.assertEqual(BASE_URI + path, - self.requests_mock.last_request.url) - else: - self.assertIsNone(self.requests_mock.last_request) - - -class DiabloAuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest, - testresources.ResourcedTestCase): - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - """Auth Token middleware should understand Diablo keystone responses.""" - def setUp(self): - # pre-diablo only had Tenant ID, which was also the Name - expected_env = { - 'HTTP_X_TENANT_ID': 'tenant_id1', - 'HTTP_X_TENANT_NAME': 'tenant_id1', - # now deprecated (diablo-compat) - 'HTTP_X_TENANT': 'tenant_id1', - } - - super(DiabloAuthTokenMiddlewareTest, self).setUp( - expected_env=expected_env) - - self.requests_mock.get(BASE_URI, - json=VERSION_LIST_v2, - status_code=300) - - self.requests_mock.post("%s/v2.0/tokens" % BASE_URI, - text=FAKE_ADMIN_TOKEN) - - self.token_id = self.examples.VALID_DIABLO_TOKEN - token_response = self.examples.JSON_TOKEN_RESPONSES[self.token_id] - - url = "%s/v2.0/tokens/%s" % (BASE_URI, self.token_id) - self.requests_mock.get(url, text=token_response) - - self.set_middleware() - - def test_valid_diablo_response(self): - resp = self.call_middleware(headers={'X-Auth-Token': self.token_id}) - self.assertEqual(200, resp.status_int) - self.assertIn('keystone.token_info', resp.request.environ) - - -class NoMemcacheAuthToken(BaseAuthTokenMiddlewareTest): - """These tests will not have the memcache module available.""" - - def setUp(self): - super(NoMemcacheAuthToken, self).setUp() - self.useFixture(utils.DisableModuleFixture('memcache')) - - def test_nomemcache(self): - conf = { - 'admin_token': 'admin_token1', - 'auth_host': 'keystone.example.com', - 'auth_port': '1234', - 'memcached_servers': ','.join(MEMCACHED_SERVERS), - 'auth_uri': 'https://keystone.example.com:1234', - } - - auth_token.AuthProtocol(FakeApp(), conf) - - -class CachePoolTest(BaseAuthTokenMiddlewareTest): - def test_use_cache_from_env(self): - """If `swift.cache` is set in the environment and `cache` is set in the - config then the env cache is used. - """ - env = {'swift.cache': 'CACHE_TEST'} - conf = { - 'cache': 'swift.cache' - } - self.set_middleware(conf=conf) - self.middleware._token_cache.initialize(env) - with self.middleware._token_cache._cache_pool.reserve() as cache: - self.assertEqual(cache, 'CACHE_TEST') - - def test_not_use_cache_from_env(self): - """If `swift.cache` is set in the environment but `cache` isn't set in - the config then the env cache isn't used. - """ - self.set_middleware() - env = {'swift.cache': 'CACHE_TEST'} - self.middleware._token_cache.initialize(env) - with self.middleware._token_cache._cache_pool.reserve() as cache: - self.assertNotEqual(cache, 'CACHE_TEST') - - def test_multiple_context_managers_share_single_client(self): - self.set_middleware() - token_cache = self.middleware._token_cache - env = {} - token_cache.initialize(env) - - caches = [] - - with token_cache._cache_pool.reserve() as cache: - caches.append(cache) - - with token_cache._cache_pool.reserve() as cache: - caches.append(cache) - - self.assertIs(caches[0], caches[1]) - self.assertEqual(set(caches), set(token_cache._cache_pool)) - - def test_nested_context_managers_create_multiple_clients(self): - self.set_middleware() - env = {} - self.middleware._token_cache.initialize(env) - token_cache = self.middleware._token_cache - - with token_cache._cache_pool.reserve() as outer_cache: - with token_cache._cache_pool.reserve() as inner_cache: - self.assertNotEqual(outer_cache, inner_cache) - - self.assertEqual( - set([inner_cache, outer_cache]), - set(token_cache._cache_pool)) - - -class GeneralAuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest, - testresources.ResourcedTestCase): - """These tests are not affected by the token format - (see CommonAuthTokenMiddlewareTest). - """ - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def test_token_is_v2_accepts_v2(self): - token = self.examples.UUID_TOKEN_DEFAULT - token_response = self.examples.TOKEN_RESPONSES[token] - self.assertTrue(auth_token._token_is_v2(token_response)) - - def test_token_is_v2_rejects_v3(self): - token = self.examples.v3_UUID_TOKEN_DEFAULT - token_response = self.examples.TOKEN_RESPONSES[token] - self.assertFalse(auth_token._token_is_v2(token_response)) - - def test_token_is_v3_rejects_v2(self): - token = self.examples.UUID_TOKEN_DEFAULT - token_response = self.examples.TOKEN_RESPONSES[token] - self.assertFalse(auth_token._token_is_v3(token_response)) - - def test_token_is_v3_accepts_v3(self): - token = self.examples.v3_UUID_TOKEN_DEFAULT - token_response = self.examples.TOKEN_RESPONSES[token] - self.assertTrue(auth_token._token_is_v3(token_response)) - - def test_fixed_cache_key_length(self): - self.set_middleware() - short_string = uuid.uuid4().hex - long_string = 8 * uuid.uuid4().hex - - token_cache = self.middleware._token_cache - hashed_short_string_key, context_ = token_cache._get_cache_key( - short_string) - hashed_long_string_key, context_ = token_cache._get_cache_key( - long_string) - - # The hash keys should always match in length - self.assertThat(hashed_short_string_key, - matchers.HasLength(len(hashed_long_string_key))) - - @testtools.skipUnless(memcached_available(), 'memcached not available') - def test_encrypt_cache_data(self): - conf = { - 'memcached_servers': ','.join(MEMCACHED_SERVERS), - 'memcache_security_strategy': 'encrypt', - 'memcache_secret_key': 'mysecret' - } - self.set_middleware(conf=conf) - token = b'my_token' - data = 'this_data' - token_cache = self.middleware._token_cache - token_cache.initialize({}) - token_cache._cache_store(token, data) - self.assertEqual(token_cache.get(token), data) - - @testtools.skipUnless(memcached_available(), 'memcached not available') - def test_sign_cache_data(self): - conf = { - 'memcached_servers': ','.join(MEMCACHED_SERVERS), - 'memcache_security_strategy': 'mac', - 'memcache_secret_key': 'mysecret' - } - self.set_middleware(conf=conf) - token = b'my_token' - data = 'this_data' - token_cache = self.middleware._token_cache - token_cache.initialize({}) - token_cache._cache_store(token, data) - self.assertEqual(token_cache.get(token), data) - - @testtools.skipUnless(memcached_available(), 'memcached not available') - def test_no_memcache_protection(self): - conf = { - 'memcached_servers': ','.join(MEMCACHED_SERVERS), - 'memcache_secret_key': 'mysecret' - } - self.set_middleware(conf=conf) - token = 'my_token' - data = 'this_data' - token_cache = self.middleware._token_cache - token_cache.initialize({}) - token_cache._cache_store(token, data) - self.assertEqual(token_cache.get(token), data) - - def test_assert_valid_memcache_protection_config(self): - # test missing memcache_secret_key - conf = { - 'memcached_servers': ','.join(MEMCACHED_SERVERS), - 'memcache_security_strategy': 'Encrypt' - } - self.assertRaises(exc.ConfigurationError, self.set_middleware, - conf=conf) - # test invalue memcache_security_strategy - conf = { - 'memcached_servers': ','.join(MEMCACHED_SERVERS), - 'memcache_security_strategy': 'whatever' - } - self.assertRaises(exc.ConfigurationError, self.set_middleware, - conf=conf) - # test missing memcache_secret_key - conf = { - 'memcached_servers': ','.join(MEMCACHED_SERVERS), - 'memcache_security_strategy': 'mac' - } - self.assertRaises(exc.ConfigurationError, self.set_middleware, - conf=conf) - conf = { - 'memcached_servers': ','.join(MEMCACHED_SERVERS), - 'memcache_security_strategy': 'Encrypt', - 'memcache_secret_key': '' - } - self.assertRaises(exc.ConfigurationError, self.set_middleware, - conf=conf) - conf = { - 'memcached_servers': ','.join(MEMCACHED_SERVERS), - 'memcache_security_strategy': 'mAc', - 'memcache_secret_key': '' - } - self.assertRaises(exc.ConfigurationError, self.set_middleware, - conf=conf) - - def test_config_revocation_cache_timeout(self): - conf = { - 'revocation_cache_time': '24', - 'auth_uri': 'https://keystone.example.com:1234', - 'admin_user': uuid.uuid4().hex - } - middleware = auth_token.AuthProtocol(self.fake_app, conf) - self.assertEqual(middleware._revocations._cache_timeout, - datetime.timedelta(seconds=24)) - - def test_conf_values_type_convert(self): - conf = { - 'revocation_cache_time': '24', - 'identity_uri': 'https://keystone.example.com:1234', - 'include_service_catalog': '0', - 'nonexsit_option': '0', - } - - middleware = auth_token.AuthProtocol(self.fake_app, conf) - self.assertEqual(datetime.timedelta(seconds=24), - middleware._revocations._cache_timeout) - self.assertEqual(False, middleware._include_service_catalog) - self.assertEqual('0', middleware._conf['nonexsit_option']) - - def test_deprecated_conf_values(self): - conf = { - 'memcache_servers': ','.join(MEMCACHED_SERVERS), - } - - middleware = auth_token.AuthProtocol(self.fake_app, conf) - self.assertEqual(MEMCACHED_SERVERS, - middleware._conf_get('memcached_servers')) - - def test_conf_values_type_convert_with_wrong_value(self): - conf = { - 'include_service_catalog': '123', - } - self.assertRaises(exc.ConfigurationError, - auth_token.AuthProtocol, self.fake_app, conf) - - def test_auth_region_name(self): - token = fixture.V3Token() - - auth_url = 'http://keystone-auth.example.com:5000' - east_url = 'http://keystone-east.example.com:5000' - west_url = 'http://keystone-west.example.com:5000' - - auth_versions = fixture.DiscoveryList(href=auth_url) - east_versions = fixture.DiscoveryList(href=east_url) - west_versions = fixture.DiscoveryList(href=west_url) - - s = token.add_service('identity') - s.add_endpoint(interface='admin', url=east_url, region='east') - s.add_endpoint(interface='admin', url=west_url, region='west') - - self.requests_mock.get(auth_url, json=auth_versions) - self.requests_mock.get(east_url, json=east_versions) - self.requests_mock.get(west_url, json=west_versions) - - self.requests_mock.post( - '%s/v3/auth/tokens' % auth_url, - headers={'X-Subject-Token': uuid.uuid4().hex}, - json=token) - - east_mock = self.requests_mock.get( - '%s/v3/auth/tokens' % east_url, - headers={'X-Subject-Token': uuid.uuid4().hex}, - json=fixture.V3Token()) - - west_mock = self.requests_mock.get( - '%s/v3/auth/tokens' % west_url, - headers={'X-Subject-Token': uuid.uuid4().hex}, - json=fixture.V3Token()) - - conf = {'auth_uri': auth_url, - 'auth_url': auth_url + '/v3', - 'auth_plugin': 'v3password', - 'username': 'user', - 'password': 'pass'} - - self.assertEqual(0, east_mock.call_count) - self.assertEqual(0, west_mock.call_count) - - east_app = self.create_simple_middleware(conf=dict(region_name='east', - **conf)) - self.call(east_app, headers={'X-Auth-Token': uuid.uuid4().hex}) - - self.assertEqual(1, east_mock.call_count) - self.assertEqual(0, west_mock.call_count) - - west_app = self.create_simple_middleware(conf=dict(region_name='west', - **conf)) - - self.call(west_app, headers={'X-Auth-Token': uuid.uuid4().hex}) - - self.assertEqual(1, east_mock.call_count) - self.assertEqual(1, west_mock.call_count) - - -class CommonAuthTokenMiddlewareTest(object): - """These tests are run once using v2 tokens and again using v3 tokens.""" - - def test_init_does_not_call_http(self): - conf = { - 'revocation_cache_time': '1' - } - self.create_simple_middleware(conf=conf) - self.assertLastPath(None) - - def test_auth_with_no_token_does_not_call_http(self): - middleware = self.create_simple_middleware() - resp = self.call(middleware) - self.assertLastPath(None) - self.assertEqual(401, resp.status_int) - - def test_init_by_ipv6Addr_auth_host(self): - del self.conf['identity_uri'] - conf = { - 'auth_host': '2001:2013:1:f101::1', - 'auth_port': '1234', - 'auth_protocol': 'http', - 'auth_uri': None, - 'auth_version': 'v3.0', - } - middleware = self.create_simple_middleware(conf=conf) - self.assertEqual('http://[2001:2013:1:f101::1]:1234', - middleware._auth_uri) - - def assert_valid_request_200(self, token, with_catalog=True): - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(200, resp.status_int) - if with_catalog: - self.assertTrue(resp.request.headers.get('X-Service-Catalog')) - else: - self.assertNotIn('X-Service-Catalog', resp.request.headers) - self.assertEqual(FakeApp.SUCCESS, resp.body) - self.assertIn('keystone.token_info', resp.request.environ) - return resp.request - - def test_valid_uuid_request(self): - for _ in range(2): # Do it twice because first result was cached. - token = self.token_dict['uuid_token_default'] - self.assert_valid_request_200(token) - self.assert_valid_last_url(token) - - def test_valid_uuid_request_with_auth_fragments(self): - del self.conf['identity_uri'] - self.conf['auth_protocol'] = 'https' - self.conf['auth_host'] = 'keystone.example.com' - self.conf['auth_port'] = '1234' - self.conf['auth_admin_prefix'] = '/testadmin' - self.set_middleware() - self.assert_valid_request_200(self.token_dict['uuid_token_default']) - self.assert_valid_last_url(self.token_dict['uuid_token_default']) - - def _test_cache_revoked(self, token, revoked_form=None): - # When the token is cached and revoked, 401 is returned. - self.middleware._check_revocations_for_cached = True - - # Token should be cached as ok after this. - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(200, resp.status_int) - - # Put it in revocation list. - self.middleware._revocations._list = self.get_revocation_list_json( - token_ids=[revoked_form or token]) - - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(401, resp.status_int) - - def test_cached_revoked_error(self): - # When the token is cached and revocation list retrieval fails, - # 503 is returned - token = self.token_dict['uuid_token_default'] - self.middleware._check_revocations_for_cached = True - - # Token should be cached as ok after this. - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(200, resp.status_int) - - # Cause the revocation list to be fetched again next time so we can - # test the case where that retrieval fails - self.middleware._revocations._fetched_time = datetime.datetime.min - with mock.patch.object(self.middleware._revocations, '_fetch', - side_effect=exc.RevocationListError): - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(503, resp.status_int) - - def test_unexpected_exception_in_validate_offline(self): - # When an unexpected exception is hit during _validate_offline, - # 500 is returned - token = self.token_dict['uuid_token_default'] - with mock.patch.object(self.middleware, '_validate_offline', - side_effect=Exception): - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(500, resp.status_int) - - def test_cached_revoked_uuid(self): - # When the UUID token is cached and revoked, 401 is returned. - self._test_cache_revoked(self.token_dict['uuid_token_default']) - - def test_valid_signed_request(self): - for _ in range(2): # Do it twice because first result was cached. - self.assert_valid_request_200( - self.token_dict['signed_token_scoped']) - # ensure that signed requests do not generate HTTP traffic - self.assertLastPath(None) - - def test_valid_signed_compressed_request(self): - self.assert_valid_request_200( - self.token_dict['signed_token_scoped_pkiz']) - # ensure that signed requests do not generate HTTP traffic - self.assertLastPath(None) - - def test_revoked_token_receives_401(self): - self.middleware._revocations._list = ( - self.get_revocation_list_json()) - - token = self.token_dict['revoked_token'] - resp = self.call_middleware(headers={'X-Auth-Token': token}) - - self.assertEqual(401, resp.status_int) - - def test_revoked_token_receives_401_sha256(self): - self.conf['hash_algorithms'] = ','.join(['sha256', 'md5']) - self.set_middleware() - self.middleware._revocations._list = ( - self.get_revocation_list_json(mode='sha256')) - - token = self.token_dict['revoked_token'] - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(401, resp.status_int) - - def test_cached_revoked_pki(self): - # When the PKI token is cached and revoked, 401 is returned. - token = self.token_dict['signed_token_scoped'] - revoked_form = cms.cms_hash_token(token) - self._test_cache_revoked(token, revoked_form) - - def test_cached_revoked_pkiz(self): - # When the PKIZ token is cached and revoked, 401 is returned. - token = self.token_dict['signed_token_scoped_pkiz'] - revoked_form = cms.cms_hash_token(token) - self._test_cache_revoked(token, revoked_form) - - def test_revoked_token_receives_401_md5_secondary(self): - # When hash_algorithms has 'md5' as the secondary hash and the - # revocation list contains the md5 hash for a token, that token is - # considered revoked so returns 401. - self.conf['hash_algorithms'] = ','.join(['sha256', 'md5']) - self.set_middleware() - self.middleware._revocations._list = ( - self.get_revocation_list_json()) - - token = self.token_dict['revoked_token'] - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(401, resp.status_int) - - def _test_revoked_hashed_token(self, token_name): - # If hash_algorithms is set as ['sha256', 'md5'], - # and check_revocations_for_cached is True, - # and a token is in the cache because it was successfully validated - # using the md5 hash, then - # if the token is in the revocation list by md5 hash, it'll be - # rejected and auth_token returns 401. - self.conf['hash_algorithms'] = ','.join(['sha256', 'md5']) - self.conf['check_revocations_for_cached'] = 'true' - self.set_middleware() - - token = self.token_dict[token_name] - - # Put the token in the revocation list. - token_hashed = cms.cms_hash_token(token) - self.middleware._revocations._list = self.get_revocation_list_json( - token_ids=[token_hashed]) - - # First, request is using the hashed token, is valid so goes in - # cache using the given hash. - resp = self.call_middleware(headers={'X-Auth-Token': token_hashed}) - self.assertEqual(200, resp.status_int) - - # This time use the PKI(Z) token - resp = self.call_middleware(headers={'X-Auth-Token': token}) - - # Should find the token in the cache and revocation list. - self.assertEqual(401, resp.status_int) - - def test_revoked_hashed_pki_token(self): - self._test_revoked_hashed_token('signed_token_scoped') - - def test_revoked_hashed_pkiz_token(self): - self._test_revoked_hashed_token('signed_token_scoped_pkiz') - - def test_revoked_pki_token_by_audit_id(self): - # When the audit ID is in the revocation list, the token is invalid. - self.set_middleware() - token = self.token_dict['signed_token_scoped'] - - # Put the token audit ID in the revocation list, - # the entry will have a false token ID so the token ID doesn't match. - fake_token_id = uuid.uuid4().hex - # The audit_id value is in examples/pki/cms/auth_*_token_scoped.json. - audit_id = 'SLIXlXQUQZWUi9VJrqdXqA' - revocation_list_data = { - 'revoked': [ - { - 'id': fake_token_id, - 'audit_id': audit_id - }, - ] - } - self.middleware._revocations._list = jsonutils.dumps( - revocation_list_data) - - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(401, resp.status_int) - - def get_revocation_list_json(self, token_ids=None, mode=None): - if token_ids is None: - key = 'revoked_token_hash' + (('_' + mode) if mode else '') - token_ids = [self.token_dict[key]] - revocation_list = {'revoked': [{'id': x, 'expires': timeutils.utcnow()} - for x in token_ids]} - return jsonutils.dumps(revocation_list) - - def test_is_signed_token_revoked_returns_false(self): - # explicitly setting an empty revocation list here to document intent - self.middleware._revocations._list = jsonutils.dumps( - {"revoked": [], "extra": "success"}) - result = self.middleware._revocations._any_revoked( - [self.token_dict['revoked_token_hash']]) - self.assertFalse(result) - - def test_is_signed_token_revoked_returns_true(self): - self.middleware._revocations._list = ( - self.get_revocation_list_json()) - result = self.middleware._revocations._any_revoked( - [self.token_dict['revoked_token_hash']]) - self.assertTrue(result) - - def test_is_signed_token_revoked_returns_true_sha256(self): - self.conf['hash_algorithms'] = ','.join(['sha256', 'md5']) - self.set_middleware() - self.middleware._revocations._list = ( - self.get_revocation_list_json(mode='sha256')) - result = self.middleware._revocations._any_revoked( - [self.token_dict['revoked_token_hash_sha256']]) - self.assertTrue(result) - - def test_verify_signed_token_raises_exception_for_revoked_token(self): - self.middleware._revocations._list = ( - self.get_revocation_list_json()) - self.assertRaises(exc.InvalidToken, - self.middleware._verify_signed_token, - self.token_dict['revoked_token'], - [self.token_dict['revoked_token_hash']]) - - def test_verify_signed_token_raises_exception_for_revoked_token_s256(self): - self.conf['hash_algorithms'] = ','.join(['sha256', 'md5']) - self.set_middleware() - self.middleware._revocations._list = ( - self.get_revocation_list_json(mode='sha256')) - self.assertRaises(exc.InvalidToken, - self.middleware._verify_signed_token, - self.token_dict['revoked_token'], - [self.token_dict['revoked_token_hash_sha256'], - self.token_dict['revoked_token_hash']]) - - def test_verify_signed_token_raises_exception_for_revoked_pkiz_token(self): - self.middleware._revocations._list = ( - self.examples.REVOKED_TOKEN_PKIZ_LIST_JSON) - self.assertRaises(exc.InvalidToken, - self.middleware._verify_pkiz_token, - self.token_dict['revoked_token_pkiz'], - [self.token_dict['revoked_token_pkiz_hash']]) - - def assertIsValidJSON(self, text): - json.loads(text) - - def test_verify_signed_token_succeeds_for_unrevoked_token(self): - self.middleware._revocations._list = ( - self.get_revocation_list_json()) - text = self.middleware._verify_signed_token( - self.token_dict['signed_token_scoped'], - [self.token_dict['signed_token_scoped_hash']]) - self.assertIsValidJSON(text) - - def test_verify_signed_compressed_token_succeeds_for_unrevoked_token(self): - self.middleware._revocations._list = ( - self.get_revocation_list_json()) - text = self.middleware._verify_pkiz_token( - self.token_dict['signed_token_scoped_pkiz'], - [self.token_dict['signed_token_scoped_hash']]) - self.assertIsValidJSON(text) - - def test_verify_signed_token_succeeds_for_unrevoked_token_sha256(self): - self.conf['hash_algorithms'] = ','.join(['sha256', 'md5']) - self.set_middleware() - self.middleware._revocations._list = ( - self.get_revocation_list_json(mode='sha256')) - text = self.middleware._verify_signed_token( - self.token_dict['signed_token_scoped'], - [self.token_dict['signed_token_scoped_hash_sha256'], - self.token_dict['signed_token_scoped_hash']]) - self.assertIsValidJSON(text) - - def test_get_token_revocation_list_fetched_time_returns_min(self): - self.middleware._revocations._fetched_time = None - - # Get rid of the revoked file - revoked_path = self.middleware._signing_directory.calc_path( - _revocations.Revocations._FILE_NAME) - os.remove(revoked_path) - - self.assertEqual(self.middleware._revocations._fetched_time, - datetime.datetime.min) - - # FIXME(blk-u): move the unit tests into unit/test_auth_token.py - def test_get_token_revocation_list_fetched_time_returns_mtime(self): - self.middleware._revocations._fetched_time = None - revoked_path = self.middleware._signing_directory.calc_path( - _revocations.Revocations._FILE_NAME) - mtime = os.path.getmtime(revoked_path) - fetched_time = datetime.datetime.utcfromtimestamp(mtime) - self.assertEqual(fetched_time, - self.middleware._revocations._fetched_time) - - @testtools.skipUnless(TimezoneFixture.supported(), - 'TimezoneFixture not supported') - def test_get_token_revocation_list_fetched_time_returns_utc(self): - with TimezoneFixture('UTC-1'): - self.middleware._revocations._list = jsonutils.dumps( - self.examples.REVOCATION_LIST) - self.middleware._revocations._fetched_time = None - fetched_time = self.middleware._revocations._fetched_time - self.assertTrue(timeutils.is_soon(fetched_time, 1)) - - def test_get_token_revocation_list_fetched_time_returns_value(self): - expected = self.middleware._revocations._fetched_time - self.assertEqual(self.middleware._revocations._fetched_time, - expected) - - def test_get_revocation_list_returns_fetched_list(self): - # auth_token uses v2 to fetch this, so don't allow the v3 - # tests to override the fake http connection - self.middleware._revocations._fetched_time = None - - # Get rid of the revoked file - revoked_path = self.middleware._signing_directory.calc_path( - _revocations.Revocations._FILE_NAME) - os.remove(revoked_path) - - self.assertEqual(self.middleware._revocations._list, - self.examples.REVOCATION_LIST) - - def test_get_revocation_list_returns_current_list_from_memory(self): - self.assertEqual(self.middleware._revocations._list, - self.middleware._revocations._list_prop) - - def test_get_revocation_list_returns_current_list_from_disk(self): - in_memory_list = self.middleware._revocations._list - self.middleware._revocations._list_prop = None - self.assertEqual(self.middleware._revocations._list, - in_memory_list) - - def test_invalid_revocation_list_raises_error(self): - self.requests_mock.get(self.revocation_url, json={}) - self.assertRaises(exc.RevocationListError, - self.middleware._revocations._fetch) - - def test_fetch_revocation_list(self): - # auth_token uses v2 to fetch this, so don't allow the v3 - # tests to override the fake http connection - fetched = jsonutils.loads(self.middleware._revocations._fetch()) - self.assertEqual(fetched, self.examples.REVOCATION_LIST) - - def test_request_invalid_uuid_token(self): - # remember because we are testing the middleware we stub the connection - # to the keystone server, but this is not what gets returned - invalid_uri = "%s/v2.0/tokens/invalid-token" % BASE_URI - self.requests_mock.get(invalid_uri, status_code=404) - - resp = self.call_middleware(headers={'X-Auth-Token': 'invalid-token'}) - self.assertEqual(401, resp.status_int) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", - resp.headers['WWW-Authenticate']) - - def test_request_invalid_signed_token(self): - token = self.examples.INVALID_SIGNED_TOKEN - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(401, resp.status_int) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", - resp.headers['WWW-Authenticate']) - - def test_request_invalid_signed_pkiz_token(self): - token = self.examples.INVALID_SIGNED_PKIZ_TOKEN - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(401, resp.status_int) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", - resp.headers['WWW-Authenticate']) - - def test_request_no_token(self): - resp = self.call_middleware() - self.assertEqual(401, resp.status_int) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", - resp.headers['WWW-Authenticate']) - - def test_request_no_token_http(self): - resp = self.call_middleware(method='HEAD') - self.assertEqual(401, resp.status_int) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", - resp.headers['WWW-Authenticate']) - - def test_request_blank_token(self): - resp = self.call_middleware(headers={'X-Auth-Token': ''}) - self.assertEqual(401, resp.status_int) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", - resp.headers['WWW-Authenticate']) - - def _get_cached_token(self, token, mode='md5'): - token_id = cms.cms_hash_token(token, mode=mode) - return self.middleware._token_cache.get(token_id) - - def test_memcache(self): - token = self.token_dict['signed_token_scoped'] - self.call_middleware(headers={'X-Auth-Token': token}) - self.assertIsNotNone(self._get_cached_token(token)) - - def test_expired(self): - token = self.token_dict['signed_token_scoped_expired'] - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(401, resp.status_int) - - def test_memcache_set_invalid_uuid(self): - invalid_uri = "%s/v2.0/tokens/invalid-token" % BASE_URI - self.requests_mock.get(invalid_uri, status_code=404) - - token = 'invalid-token' - self.call_middleware(headers={'X-Auth-Token': token}) - self.assertRaises(exc.InvalidToken, self._get_cached_token, token) - - def test_memcache_set_expired(self, extra_conf={}, extra_environ={}): - token_cache_time = 10 - conf = { - 'token_cache_time': '%s' % token_cache_time, - } - conf.update(extra_conf) - self.set_middleware(conf=conf) - - token = self.token_dict['signed_token_scoped'] - self.call_middleware(headers={'X-Auth-Token': token}) - - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = token - req.environ.update(extra_environ) - - now = datetime.datetime.utcnow() - self.useFixture(TimeFixture(now)) - req.get_response(self.middleware) - self.assertIsNotNone(self._get_cached_token(token)) - - timeutils.advance_time_seconds(token_cache_time) - self.assertIsNone(self._get_cached_token(token)) - - def test_swift_memcache_set_expired(self): - extra_conf = {'cache': 'swift.cache'} - extra_environ = {'swift.cache': memorycache.Client()} - self.test_memcache_set_expired(extra_conf, extra_environ) - - def test_http_error_not_cached_token(self): - """Test to don't cache token as invalid on network errors. - - We use UUID tokens since they are the easiest one to reach - get_http_connection. - """ - self.middleware._http_request_max_retries = 0 - self.call_middleware(headers={'X-Auth-Token': ERROR_TOKEN}) - self.assertIsNone(self._get_cached_token(ERROR_TOKEN)) - self.assert_valid_last_url(ERROR_TOKEN) - - def test_http_request_max_retries(self): - times_retry = 10 - - conf = {'http_request_max_retries': '%s' % times_retry} - self.set_middleware(conf=conf) - - with mock.patch('time.sleep') as mock_obj: - self.call_middleware(headers={'X-Auth-Token': ERROR_TOKEN}) - - self.assertEqual(mock_obj.call_count, times_retry) - - def test_nocatalog(self): - conf = { - 'include_service_catalog': 'False' - } - self.set_middleware(conf=conf) - self.assert_valid_request_200(self.token_dict['uuid_token_default'], - with_catalog=False) - - def assert_kerberos_bind(self, token, bind_level, - use_kerberos=True, success=True): - conf = { - 'enforce_token_bind': bind_level, - 'auth_version': self.auth_version, - } - self.set_middleware(conf=conf) - - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = token - - if use_kerberos: - if use_kerberos is True: - req.environ['REMOTE_USER'] = self.examples.KERBEROS_BIND - else: - req.environ['REMOTE_USER'] = use_kerberos - - req.environ['AUTH_TYPE'] = 'Negotiate' - - resp = req.get_response(self.middleware) - - if success: - self.assertEqual(200, resp.status_int) - self.assertEqual(FakeApp.SUCCESS, resp.body) - self.assertIn('keystone.token_info', req.environ) - self.assert_valid_last_url(token) - else: - self.assertEqual(401, resp.status_int) - msg = "Keystone uri='https://keystone.example.com:1234'" - self.assertEqual(msg, resp.headers['WWW-Authenticate']) - - def test_uuid_bind_token_disabled_with_kerb_user(self): - for use_kerberos in [True, False]: - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='disabled', - use_kerberos=use_kerberos, - success=True) - - def test_uuid_bind_token_disabled_with_incorrect_ticket(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='kerberos', - use_kerberos='ronald@MCDONALDS.COM', - success=False) - - def test_uuid_bind_token_permissive_with_kerb_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='permissive', - use_kerberos=True, - success=True) - - def test_uuid_bind_token_permissive_without_kerb_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='permissive', - use_kerberos=False, - success=False) - - def test_uuid_bind_token_permissive_with_unknown_bind(self): - token = self.token_dict['uuid_token_unknown_bind'] - - for use_kerberos in [True, False]: - self.assert_kerberos_bind(token, - bind_level='permissive', - use_kerberos=use_kerberos, - success=True) - - def test_uuid_bind_token_permissive_with_incorrect_ticket(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='kerberos', - use_kerberos='ronald@MCDONALDS.COM', - success=False) - - def test_uuid_bind_token_strict_with_kerb_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='strict', - use_kerberos=True, - success=True) - - def test_uuid_bind_token_strict_with_kerbout_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='strict', - use_kerberos=False, - success=False) - - def test_uuid_bind_token_strict_with_unknown_bind(self): - token = self.token_dict['uuid_token_unknown_bind'] - - for use_kerberos in [True, False]: - self.assert_kerberos_bind(token, - bind_level='strict', - use_kerberos=use_kerberos, - success=False) - - def test_uuid_bind_token_required_with_kerb_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='required', - use_kerberos=True, - success=True) - - def test_uuid_bind_token_required_without_kerb_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='required', - use_kerberos=False, - success=False) - - def test_uuid_bind_token_required_with_unknown_bind(self): - token = self.token_dict['uuid_token_unknown_bind'] - - for use_kerberos in [True, False]: - self.assert_kerberos_bind(token, - bind_level='required', - use_kerberos=use_kerberos, - success=False) - - def test_uuid_bind_token_required_without_bind(self): - for use_kerberos in [True, False]: - self.assert_kerberos_bind(self.token_dict['uuid_token_default'], - bind_level='required', - use_kerberos=use_kerberos, - success=False) - - def test_uuid_bind_token_named_kerberos_with_kerb_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='kerberos', - use_kerberos=True, - success=True) - - def test_uuid_bind_token_named_kerberos_without_kerb_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='kerberos', - use_kerberos=False, - success=False) - - def test_uuid_bind_token_named_kerberos_with_unknown_bind(self): - token = self.token_dict['uuid_token_unknown_bind'] - - for use_kerberos in [True, False]: - self.assert_kerberos_bind(token, - bind_level='kerberos', - use_kerberos=use_kerberos, - success=False) - - def test_uuid_bind_token_named_kerberos_without_bind(self): - for use_kerberos in [True, False]: - self.assert_kerberos_bind(self.token_dict['uuid_token_default'], - bind_level='kerberos', - use_kerberos=use_kerberos, - success=False) - - def test_uuid_bind_token_named_kerberos_with_incorrect_ticket(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='kerberos', - use_kerberos='ronald@MCDONALDS.COM', - success=False) - - def test_uuid_bind_token_with_unknown_named_FOO(self): - token = self.token_dict['uuid_token_bind'] - - for use_kerberos in [True, False]: - self.assert_kerberos_bind(token, - bind_level='FOO', - use_kerberos=use_kerberos, - success=False) - - def test_caching_token_on_verify(self): - # When the token is cached it isn't cached again when it's verified. - - # The token cache has to be initialized with our cache instance. - self.middleware._token_cache._env_cache_name = 'cache' - cache = memorycache.Client() - self.middleware._token_cache.initialize(env={'cache': cache}) - - # Mock cache.set since then the test can verify call_count. - orig_cache_set = cache.set - cache.set = mock.Mock(side_effect=orig_cache_set) - - token = self.token_dict['signed_token_scoped'] - - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(200, resp.status_int) - - self.assertThat(1, matchers.Equals(cache.set.call_count)) - - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(200, resp.status_int) - - # Assert that the token wasn't cached again. - self.assertThat(1, matchers.Equals(cache.set.call_count)) - - def test_auth_plugin(self): - - for service_url in (self.examples.UNVERSIONED_SERVICE_URL, - self.examples.SERVICE_URL): - self.requests_mock.get(service_url, - json=VERSION_LIST_v3, - status_code=300) - - token = self.token_dict['uuid_token_default'] - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(200, resp.status_int) - self.assertEqual(FakeApp.SUCCESS, resp.body) - - token_auth = resp.request.environ['keystone.token_auth'] - endpoint_filter = {'service_type': self.examples.SERVICE_TYPE, - 'version': 3} - - url = token_auth.get_endpoint(session.Session(), **endpoint_filter) - self.assertEqual('%s/v3' % BASE_URI, url) - - self.assertTrue(token_auth.has_user_token) - self.assertFalse(token_auth.has_service_token) - self.assertIsNone(token_auth.service) - - def test_doesnt_auto_set_content_type(self): - # webob will set content_type = 'text/html' by default if nothing is - # provided. We don't want our middleware messing with the content type - # of the underlying applications. - - text = uuid.uuid4().hex - - def _middleware(environ, start_response): - start_response(200, []) - return text - - def _start_response(status_code, headerlist, exc_info=None): - self.assertIn('200', status_code) # will be '200 OK' - self.assertEqual([], headerlist) - - m = auth_token.AuthProtocol(_middleware, self.conf) - - env = {'REQUEST_METHOD': 'GET', - 'HTTP_X_AUTH_TOKEN': self.token_dict['uuid_token_default']} - - r = m(env, _start_response) - self.assertEqual(text, r) - - -class V2CertDownloadMiddlewareTest(BaseAuthTokenMiddlewareTest, - testresources.ResourcedTestCase): - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def __init__(self, *args, **kwargs): - super(V2CertDownloadMiddlewareTest, self).__init__(*args, **kwargs) - self.auth_version = 'v2.0' - self.fake_app = None - self.ca_path = '/v2.0/certificates/ca' - self.signing_path = '/v2.0/certificates/signing' - - def setUp(self): - super(V2CertDownloadMiddlewareTest, self).setUp( - auth_version=self.auth_version, - fake_app=self.fake_app) - self.base_dir = tempfile.mkdtemp() - self.addCleanup(shutil.rmtree, self.base_dir) - self.cert_dir = os.path.join(self.base_dir, 'certs') - os.makedirs(self.cert_dir, stat.S_IRWXU) - conf = { - 'signing_dir': self.cert_dir, - 'auth_version': self.auth_version, - } - - self.requests_mock.get(BASE_URI, - json=VERSION_LIST_v3, - status_code=300) - - self.set_middleware(conf=conf) - - # Usually we supply a signed_dir with pre-installed certificates, - # so invocation of /usr/bin/openssl succeeds. This time we give it - # an empty directory, so it fails. - def test_request_no_token_dummy(self): - cms._ensure_subprocess() - - self.requests_mock.get('%s%s' % (BASE_URI, self.ca_path), - status_code=404) - self.requests_mock.get('%s%s' % (BASE_URI, self.signing_path), - status_code=404) - self.assertRaises(exceptions.CertificateConfigError, - self.middleware._verify_signed_token, - self.examples.SIGNED_TOKEN_SCOPED, - [self.examples.SIGNED_TOKEN_SCOPED_HASH]) - - def test_fetch_signing_cert(self): - data = 'FAKE CERT' - url = "%s%s" % (BASE_URI, self.signing_path) - self.requests_mock.get(url, text=data) - self.middleware._fetch_signing_cert() - - signing_cert_path = self.middleware._signing_directory.calc_path( - self.middleware._SIGNING_CERT_FILE_NAME) - with open(signing_cert_path, 'r') as f: - self.assertEqual(f.read(), data) - - self.assertEqual(url, self.requests_mock.last_request.url) - - def test_fetch_signing_ca(self): - data = 'FAKE CA' - url = "%s%s" % (BASE_URI, self.ca_path) - self.requests_mock.get(url, text=data) - self.middleware._fetch_ca_cert() - - ca_file_path = self.middleware._signing_directory.calc_path( - self.middleware._SIGNING_CA_FILE_NAME) - with open(ca_file_path, 'r') as f: - self.assertEqual(f.read(), data) - - self.assertEqual(url, self.requests_mock.last_request.url) - - def test_prefix_trailing_slash(self): - del self.conf['identity_uri'] - self.conf['auth_protocol'] = 'https' - self.conf['auth_host'] = 'keystone.example.com' - self.conf['auth_port'] = '1234' - self.conf['auth_admin_prefix'] = '/newadmin/' - - base_url = '%s/newadmin' % BASE_HOST - ca_url = "%s%s" % (base_url, self.ca_path) - signing_url = "%s%s" % (base_url, self.signing_path) - - self.requests_mock.get(base_url, - json=VERSION_LIST_v3, - status_code=300) - self.requests_mock.get(ca_url, text='FAKECA') - self.requests_mock.get(signing_url, text='FAKECERT') - - self.set_middleware(conf=self.conf) - - self.middleware._fetch_ca_cert() - self.assertEqual(ca_url, self.requests_mock.last_request.url) - - self.middleware._fetch_signing_cert() - self.assertEqual(signing_url, self.requests_mock.last_request.url) - - def test_without_prefix(self): - del self.conf['identity_uri'] - self.conf['auth_protocol'] = 'https' - self.conf['auth_host'] = 'keystone.example.com' - self.conf['auth_port'] = '1234' - self.conf['auth_admin_prefix'] = '' - - ca_url = "%s%s" % (BASE_HOST, self.ca_path) - signing_url = "%s%s" % (BASE_HOST, self.signing_path) - - self.requests_mock.get(BASE_HOST, - json=VERSION_LIST_v3, - status_code=300) - self.requests_mock.get(ca_url, text='FAKECA') - self.requests_mock.get(signing_url, text='FAKECERT') - - self.set_middleware(conf=self.conf) - - self.middleware._fetch_ca_cert() - self.assertEqual(ca_url, self.requests_mock.last_request.url) - - self.middleware._fetch_signing_cert() - self.assertEqual(signing_url, self.requests_mock.last_request.url) - - -class V3CertDownloadMiddlewareTest(V2CertDownloadMiddlewareTest): - - def __init__(self, *args, **kwargs): - super(V3CertDownloadMiddlewareTest, self).__init__(*args, **kwargs) - self.auth_version = 'v3.0' - self.fake_app = v3FakeApp - self.ca_path = '/v3/OS-SIMPLE-CERT/ca' - self.signing_path = '/v3/OS-SIMPLE-CERT/certificates' - - -def network_error_response(request, context): - raise exceptions.ConnectionRefused("Network connection refused.") - - -class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest, - CommonAuthTokenMiddlewareTest, - testresources.ResourcedTestCase): - """v2 token specific tests. - - There are some differences between how the auth-token middleware handles - v2 and v3 tokens over and above the token formats, namely: - - - A v3 keystone server will auto scope a token to a user's default project - if no scope is specified. A v2 server assumes that the auth-token - middleware will do that. - - A v2 keystone server may issue a token without a catalog, even with a - tenant - - The tests below were originally part of the generic AuthTokenMiddlewareTest - class, but now, since they really are v2 specific, they are included here. - - """ - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def setUp(self): - super(v2AuthTokenMiddlewareTest, self).setUp() - - self.token_dict = { - 'uuid_token_default': self.examples.UUID_TOKEN_DEFAULT, - 'uuid_token_unscoped': self.examples.UUID_TOKEN_UNSCOPED, - 'uuid_token_bind': self.examples.UUID_TOKEN_BIND, - 'uuid_token_unknown_bind': self.examples.UUID_TOKEN_UNKNOWN_BIND, - 'signed_token_scoped': self.examples.SIGNED_TOKEN_SCOPED, - 'signed_token_scoped_pkiz': self.examples.SIGNED_TOKEN_SCOPED_PKIZ, - 'signed_token_scoped_hash': self.examples.SIGNED_TOKEN_SCOPED_HASH, - 'signed_token_scoped_hash_sha256': - self.examples.SIGNED_TOKEN_SCOPED_HASH_SHA256, - 'signed_token_scoped_expired': - self.examples.SIGNED_TOKEN_SCOPED_EXPIRED, - 'revoked_token': self.examples.REVOKED_TOKEN, - 'revoked_token_pkiz': self.examples.REVOKED_TOKEN_PKIZ, - 'revoked_token_pkiz_hash': - self.examples.REVOKED_TOKEN_PKIZ_HASH, - 'revoked_token_hash': self.examples.REVOKED_TOKEN_HASH, - 'revoked_token_hash_sha256': - self.examples.REVOKED_TOKEN_HASH_SHA256, - } - - self.requests_mock.get(BASE_URI, - json=VERSION_LIST_v2, - status_code=300) - - self.requests_mock.post('%s/v2.0/tokens' % BASE_URI, - text=FAKE_ADMIN_TOKEN) - - self.revocation_url = '%s/v2.0/tokens/revoked' % BASE_URI - self.requests_mock.get(self.revocation_url, - text=self.examples.SIGNED_REVOCATION_LIST) - - for token in (self.examples.UUID_TOKEN_DEFAULT, - self.examples.UUID_TOKEN_UNSCOPED, - self.examples.UUID_TOKEN_BIND, - self.examples.UUID_TOKEN_UNKNOWN_BIND, - self.examples.UUID_TOKEN_NO_SERVICE_CATALOG, - self.examples.SIGNED_TOKEN_SCOPED_KEY, - self.examples.SIGNED_TOKEN_SCOPED_PKIZ_KEY,): - url = "%s/v2.0/tokens/%s" % (BASE_URI, token) - text = self.examples.JSON_TOKEN_RESPONSES[token] - self.requests_mock.get(url, text=text) - - url = '%s/v2.0/tokens/%s' % (BASE_URI, ERROR_TOKEN) - self.requests_mock.get(url, text=network_error_response) - - self.set_middleware() - - def assert_unscoped_default_tenant_auto_scopes(self, token): - """Unscoped v2 requests with a default tenant should "auto-scope." - - The implied scope is the user's tenant ID. - - """ - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(200, resp.status_int) - self.assertEqual(FakeApp.SUCCESS, resp.body) - self.assertIn('keystone.token_info', resp.request.environ) - - def assert_valid_last_url(self, token_id): - self.assertLastPath("/v2.0/tokens/%s" % token_id) - - def test_default_tenant_uuid_token(self): - self.assert_unscoped_default_tenant_auto_scopes( - self.examples.UUID_TOKEN_DEFAULT) - - def test_default_tenant_signed_token(self): - self.assert_unscoped_default_tenant_auto_scopes( - self.examples.SIGNED_TOKEN_SCOPED) - - def assert_unscoped_token_receives_401(self, token): - """Unscoped requests with no default tenant ID should be rejected.""" - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(401, resp.status_int) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", - resp.headers['WWW-Authenticate']) - - def test_unscoped_uuid_token_receives_401(self): - self.assert_unscoped_token_receives_401( - self.examples.UUID_TOKEN_UNSCOPED) - - def test_unscoped_pki_token_receives_401(self): - self.assert_unscoped_token_receives_401( - self.examples.SIGNED_TOKEN_UNSCOPED) - - def test_request_prevent_service_catalog_injection(self): - token = self.examples.UUID_TOKEN_NO_SERVICE_CATALOG - resp = self.call_middleware(headers={'X-Service-Catalog': '[]', - 'X-Auth-Token': token}) - - self.assertEqual(200, resp.status_int) - self.assertFalse(resp.request.headers.get('X-Service-Catalog')) - self.assertEqual(FakeApp.SUCCESS, resp.body) - - def test_user_plugin_token_properties(self): - token = self.examples.UUID_TOKEN_DEFAULT - token_data = self.examples.TOKEN_RESPONSES[token] - - resp = self.call_middleware(headers={'X-Service-Catalog': '[]', - 'X-Auth-Token': token, - 'X-Service-Token': token}) - - self.assertEqual(200, resp.status_int) - self.assertEqual(FakeApp.SUCCESS, resp.body) - - token_auth = resp.request.environ['keystone.token_auth'] - - self.assertTrue(token_auth.has_user_token) - self.assertTrue(token_auth.has_service_token) - - for t in [token_auth.user, token_auth.service]: - self.assertEqual(token_data.user_id, t.user_id) - self.assertEqual(token_data.tenant_id, t.project_id) - - self.assertThat(t.role_names, matchers.HasLength(2)) - self.assertIn('role1', t.role_names) - self.assertIn('role2', t.role_names) - - self.assertIsNone(t.trust_id) - self.assertIsNone(t.user_domain_id) - self.assertIsNone(t.project_domain_id) - - -class CrossVersionAuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest, - testresources.ResourcedTestCase): - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def test_valid_uuid_request_forced_to_2_0(self): - """Test forcing auth_token to use lower api version. - - By installing the v3 http hander, auth_token will be get - a version list that looks like a v3 server - from which it - would normally chose v3.0 as the auth version. However, here - we specify v2.0 in the configuration - which should force - auth_token to use that version instead. - - """ - conf = { - 'auth_version': 'v2.0' - } - - self.requests_mock.get(BASE_URI, - json=VERSION_LIST_v3, - status_code=300) - - self.requests_mock.post('%s/v2.0/tokens' % BASE_URI, - text=FAKE_ADMIN_TOKEN) - - token = self.examples.UUID_TOKEN_DEFAULT - url = "%s/v2.0/tokens/%s" % (BASE_URI, token) - text = self.examples.JSON_TOKEN_RESPONSES[token] - self.requests_mock.get(url, text=text) - - self.set_middleware(conf=conf) - - # This tests will only work is auth_token has chosen to use the - # lower, v2, api version - resp = self.call_middleware(headers={'X-Auth-Token': token}) - self.assertEqual(200, resp.status_int) - self.assertEqual(url, self.requests_mock.last_request.url) - - -class v3AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest, - CommonAuthTokenMiddlewareTest, - testresources.ResourcedTestCase): - """Test auth_token middleware with v3 tokens. - - Re-execute the AuthTokenMiddlewareTest class tests, but with the - auth_token middleware configured to expect v3 tokens back from - a keystone server. - - This is done by configuring the AuthTokenMiddlewareTest class via - its Setup(), passing in v3 style data that will then be used by - the tests themselves. This approach has been used to ensure we - really are running the same tests for both v2 and v3 tokens. - - There a few additional specific test for v3 only: - - - We allow an unscoped token to be validated (as unscoped), where - as for v2 tokens, the auth_token middleware is expected to try and - auto-scope it (and fail if there is no default tenant) - - Domain scoped tokens - - Since we don't specify an auth version for auth_token to use, by - definition we are thefore implicitely testing that it will use - the highest available auth version, i.e. v3.0 - - """ - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def setUp(self): - super(v3AuthTokenMiddlewareTest, self).setUp( - auth_version='v3.0', - fake_app=v3FakeApp) - - self.token_dict = { - 'uuid_token_default': self.examples.v3_UUID_TOKEN_DEFAULT, - 'uuid_token_unscoped': self.examples.v3_UUID_TOKEN_UNSCOPED, - 'uuid_token_bind': self.examples.v3_UUID_TOKEN_BIND, - 'uuid_token_unknown_bind': - self.examples.v3_UUID_TOKEN_UNKNOWN_BIND, - 'signed_token_scoped': self.examples.SIGNED_v3_TOKEN_SCOPED, - 'signed_token_scoped_pkiz': - self.examples.SIGNED_v3_TOKEN_SCOPED_PKIZ, - 'signed_token_scoped_hash': - self.examples.SIGNED_v3_TOKEN_SCOPED_HASH, - 'signed_token_scoped_hash_sha256': - self.examples.SIGNED_v3_TOKEN_SCOPED_HASH_SHA256, - 'signed_token_scoped_expired': - self.examples.SIGNED_TOKEN_SCOPED_EXPIRED, - 'revoked_token': self.examples.REVOKED_v3_TOKEN, - 'revoked_token_pkiz': self.examples.REVOKED_v3_TOKEN_PKIZ, - 'revoked_token_hash': self.examples.REVOKED_v3_TOKEN_HASH, - 'revoked_token_hash_sha256': - self.examples.REVOKED_v3_TOKEN_HASH_SHA256, - 'revoked_token_pkiz_hash': - self.examples.REVOKED_v3_PKIZ_TOKEN_HASH, - } - - self.requests_mock.get(BASE_URI, - json=VERSION_LIST_v3, - status_code=300) - - # TODO(jamielennox): auth_token middleware uses a v2 admin token - # regardless of the auth_version that is set. - self.requests_mock.post('%s/v2.0/tokens' % BASE_URI, - text=FAKE_ADMIN_TOKEN) - - self.revocation_url = '%s/v3/auth/tokens/OS-PKI/revoked' % BASE_URI - self.requests_mock.get(self.revocation_url, - text=self.examples.SIGNED_REVOCATION_LIST) - - self.requests_mock.get('%s/v3/auth/tokens' % BASE_URI, - text=self.token_response, - headers={'X-Subject-Token': uuid.uuid4().hex}) - - self.set_middleware() - - def token_response(self, request, context): - auth_id = request.headers.get('X-Auth-Token') - token_id = request.headers.get('X-Subject-Token') - self.assertEqual(auth_id, FAKE_ADMIN_TOKEN_ID) - - if token_id == ERROR_TOKEN: - raise exceptions.ConnectionRefused("Network connection refused.") - - try: - response = self.examples.JSON_TOKEN_RESPONSES[token_id] - except KeyError: - response = "" - context.status_code = 404 - - return response - - def assert_valid_last_url(self, token_id): - self.assertLastPath('/v3/auth/tokens') - - def test_valid_unscoped_uuid_request(self): - # Remove items that won't be in an unscoped token - delta_expected_env = { - 'HTTP_X_PROJECT_ID': None, - 'HTTP_X_PROJECT_NAME': None, - 'HTTP_X_PROJECT_DOMAIN_ID': None, - 'HTTP_X_PROJECT_DOMAIN_NAME': None, - 'HTTP_X_TENANT_ID': None, - 'HTTP_X_TENANT_NAME': None, - 'HTTP_X_ROLES': '', - 'HTTP_X_TENANT': None, - 'HTTP_X_ROLE': '', - } - self.set_middleware(expected_env=delta_expected_env) - self.assert_valid_request_200(self.examples.v3_UUID_TOKEN_UNSCOPED, - with_catalog=False) - self.assertLastPath('/v3/auth/tokens') - - def test_domain_scoped_uuid_request(self): - # Modify items compared to default token for a domain scope - delta_expected_env = { - 'HTTP_X_DOMAIN_ID': 'domain_id1', - 'HTTP_X_DOMAIN_NAME': 'domain_name1', - 'HTTP_X_PROJECT_ID': None, - 'HTTP_X_PROJECT_NAME': None, - 'HTTP_X_PROJECT_DOMAIN_ID': None, - 'HTTP_X_PROJECT_DOMAIN_NAME': None, - 'HTTP_X_TENANT_ID': None, - 'HTTP_X_TENANT_NAME': None, - 'HTTP_X_TENANT': None - } - self.set_middleware(expected_env=delta_expected_env) - self.assert_valid_request_200( - self.examples.v3_UUID_TOKEN_DOMAIN_SCOPED) - self.assertLastPath('/v3/auth/tokens') - - def test_gives_v2_catalog(self): - self.set_middleware() - req = self.assert_valid_request_200( - self.examples.SIGNED_v3_TOKEN_SCOPED) - - catalog = jsonutils.loads(req.headers['X-Service-Catalog']) - - for service in catalog: - for endpoint in service['endpoints']: - # no point checking everything, just that it's in v2 format - self.assertIn('adminURL', endpoint) - self.assertIn('publicURL', endpoint) - self.assertIn('adminURL', endpoint) - - def test_fallback_to_online_validation_with_signing_error(self): - self.requests_mock.get('%s/v3/OS-SIMPLE-CERT/certificates' % BASE_URI, - status_code=404) - self.assert_valid_request_200(self.token_dict['signed_token_scoped']) - self.assert_valid_request_200( - self.token_dict['signed_token_scoped_pkiz']) - - def test_fallback_to_online_validation_with_ca_error(self): - self.requests_mock.get('%s/v3/OS-SIMPLE-CERT/ca' % BASE_URI, - status_code=404) - self.assert_valid_request_200(self.token_dict['signed_token_scoped']) - self.assert_valid_request_200( - self.token_dict['signed_token_scoped_pkiz']) - - def test_fallback_to_online_validation_with_revocation_list_error(self): - self.requests_mock.get(self.revocation_url, status_code=404) - self.assert_valid_request_200(self.token_dict['signed_token_scoped']) - self.assert_valid_request_200( - self.token_dict['signed_token_scoped_pkiz']) - - def test_user_plugin_token_properties(self): - token = self.examples.v3_UUID_TOKEN_DEFAULT - token_data = self.examples.TOKEN_RESPONSES[token] - - resp = self.call_middleware(headers={'X-Service-Catalog': '[]', - 'X-Auth-Token': token, - 'X-Service-Token': token}) - - self.assertEqual(200, resp.status_int) - self.assertEqual(FakeApp.SUCCESS, resp.body) - - token_auth = resp.request.environ['keystone.token_auth'] - - self.assertTrue(token_auth.has_user_token) - self.assertTrue(token_auth.has_service_token) - - for t in [token_auth.user, token_auth.service]: - self.assertEqual(token_data.user_id, t.user_id) - self.assertEqual(token_data.project_id, t.project_id) - self.assertEqual(token_data.user_domain_id, t.user_domain_id) - self.assertEqual(token_data.project_domain_id, t.project_domain_id) - - self.assertThat(t.role_names, matchers.HasLength(2)) - self.assertIn('role1', t.role_names) - self.assertIn('role2', t.role_names) - - self.assertIsNone(t.trust_id) - - def test_expire_stored_in_cache(self): - # tests the upgrade path from storing a tuple vs just the data in the - # cache. Can be removed in the future. - token = 'mytoken' - data = 'this_data' - self.set_middleware() - self.middleware._token_cache.initialize({}) - now = datetime.datetime.utcnow() - delta = datetime.timedelta(hours=1) - expires = strtime(at=(now + delta)) - self.middleware._token_cache.store(token, (data, expires)) - self.assertEqual(self.middleware._token_cache.get(token), data) - - -class DelayedAuthTests(BaseAuthTokenMiddlewareTest): - - def test_header_in_401(self): - body = uuid.uuid4().hex - auth_uri = 'http://local.test' - conf = {'delay_auth_decision': 'True', - 'auth_version': 'v3.0', - 'auth_uri': auth_uri} - - middleware = self.create_simple_middleware(status='401 Unauthorized', - body=body, - conf=conf) - resp = self.call(middleware) - self.assertEqual(six.b(body), resp.body) - - self.assertEqual(401, resp.status_int) - self.assertEqual("Keystone uri='%s'" % auth_uri, - resp.headers['WWW-Authenticate']) - - def test_delayed_auth_values(self): - conf = {'auth_uri': 'http://local.test'} - status = '401 Unauthorized' - - middleware = self.create_simple_middleware(status=status, conf=conf) - self.assertFalse(middleware._delay_auth_decision) - - for v in ('True', '1', 'on', 'yes'): - conf = {'delay_auth_decision': v, - 'auth_uri': 'http://local.test'} - - middleware = self.create_simple_middleware(status=status, - conf=conf) - self.assertTrue(middleware._delay_auth_decision) - - for v in ('False', '0', 'no'): - conf = {'delay_auth_decision': v, - 'auth_uri': 'http://local.test'} - - middleware = self.create_simple_middleware(status=status, - conf=conf) - self.assertFalse(middleware._delay_auth_decision) - - def test_auth_plugin_with_no_tokens(self): - body = uuid.uuid4().hex - auth_uri = 'http://local.test' - conf = {'delay_auth_decision': True, 'auth_uri': auth_uri} - - middleware = self.create_simple_middleware(body=body, conf=conf) - resp = self.call(middleware) - self.assertEqual(six.b(body), resp.body) - - token_auth = resp.request.environ['keystone.token_auth'] - - self.assertFalse(token_auth.has_user_token) - self.assertIsNone(token_auth.user) - self.assertFalse(token_auth.has_service_token) - self.assertIsNone(token_auth.service) - - -class CommonCompositeAuthTests(object): - """Test Composite authentication. - - Test the behaviour of adding a service-token. - """ - - def test_composite_auth_ok(self): - token = self.token_dict['uuid_token_default'] - service_token = self.token_dict['uuid_service_token_default'] - fake_logger = fixtures.FakeLogger(level=logging.DEBUG) - self.middleware.logger = self.useFixture(fake_logger) - resp = self.call_middleware(headers={'X-Auth-Token': token, - 'X-Service-Token': service_token}) - self.assertEqual(200, resp.status_int) - self.assertEqual(FakeApp.SUCCESS, resp.body) - expected_env = dict(EXPECTED_V2_DEFAULT_ENV_RESPONSE) - expected_env.update(EXPECTED_V2_DEFAULT_SERVICE_ENV_RESPONSE) - - # role list may get reordered, check for string pieces individually - self.assertIn('Received request from user: ', fake_logger.output) - self.assertIn('user_id %(HTTP_X_USER_ID)s, ' - 'project_id %(HTTP_X_TENANT_ID)s, ' - 'roles ' % expected_env, fake_logger.output) - self.assertIn('service: user_id %(HTTP_X_SERVICE_USER_ID)s, ' - 'project_id %(HTTP_X_SERVICE_PROJECT_ID)s, ' - 'roles ' % expected_env, fake_logger.output) - - roles = ','.join([expected_env['HTTP_X_SERVICE_ROLES'], - expected_env['HTTP_X_ROLES']]) - - for r in roles.split(','): - self.assertIn(r, fake_logger.output) - - def test_composite_auth_invalid_service_token(self): - token = self.token_dict['uuid_token_default'] - service_token = 'invalid-service-token' - resp = self.call_middleware(headers={'X-Auth-Token': token, - 'X-Service-Token': service_token}) - self.assertEqual(401, resp.status_int) - self.assertEqual(b'Authentication required', resp.body) - - def test_composite_auth_no_service_token(self): - self.purge_service_token_expected_env() - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = self.token_dict['uuid_token_default'] - - # Ensure injection of service headers is not possible - for key, value in six.iteritems(self.service_token_expected_env): - header_key = key[len('HTTP_'):].replace('_', '-') - req.headers[header_key] = value - # Check arbitrary headers not removed - req.headers['X-Foo'] = 'Bar' - resp = req.get_response(self.middleware) - for key in six.iterkeys(self.service_token_expected_env): - header_key = key[len('HTTP_'):].replace('_', '-') - self.assertFalse(req.headers.get(header_key)) - self.assertEqual('Bar', req.headers.get('X-Foo')) - self.assertEqual(418, resp.status_int) - self.assertEqual(FakeApp.FORBIDDEN, resp.body) - - def test_composite_auth_invalid_user_token(self): - token = 'invalid-token' - service_token = self.token_dict['uuid_service_token_default'] - resp = self.call_middleware(headers={'X-Auth-Token': token, - 'X-Service-Token': service_token}) - self.assertEqual(401, resp.status_int) - self.assertEqual(b'Authentication required', resp.body) - - def test_composite_auth_no_user_token(self): - service_token = self.token_dict['uuid_service_token_default'] - resp = self.call_middleware(headers={'X-Service-Token': service_token}) - self.assertEqual(401, resp.status_int) - self.assertEqual(b'Authentication required', resp.body) - - def test_composite_auth_delay_ok(self): - self.middleware._delay_auth_decision = True - token = self.token_dict['uuid_token_default'] - service_token = self.token_dict['uuid_service_token_default'] - resp = self.call_middleware(headers={'X-Auth-Token': token, - 'X-Service-Token': service_token}) - self.assertEqual(200, resp.status_int) - self.assertEqual(FakeApp.SUCCESS, resp.body) - - def test_composite_auth_delay_invalid_service_token(self): - self.middleware._delay_auth_decision = True - self.purge_service_token_expected_env() - expected_env = { - 'HTTP_X_SERVICE_IDENTITY_STATUS': 'Invalid', - } - self.update_expected_env(expected_env) - - token = self.token_dict['uuid_token_default'] - service_token = 'invalid-service-token' - resp = self.call_middleware(headers={'X-Auth-Token': token, - 'X-Service-Token': service_token}) - self.assertEqual(420, resp.status_int) - self.assertEqual(FakeApp.FORBIDDEN, resp.body) - - def test_composite_auth_delay_invalid_service_and_user_tokens(self): - self.middleware._delay_auth_decision = True - self.purge_service_token_expected_env() - self.purge_token_expected_env() - expected_env = { - 'HTTP_X_IDENTITY_STATUS': 'Invalid', - 'HTTP_X_SERVICE_IDENTITY_STATUS': 'Invalid', - } - self.update_expected_env(expected_env) - - token = 'invalid-token' - service_token = 'invalid-service-token' - resp = self.call_middleware(headers={'X-Auth-Token': token, - 'X-Service-Token': service_token}) - self.assertEqual(419, resp.status_int) - self.assertEqual(FakeApp.FORBIDDEN, resp.body) - - def test_composite_auth_delay_no_service_token(self): - self.middleware._delay_auth_decision = True - self.purge_service_token_expected_env() - - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = self.token_dict['uuid_token_default'] - - # Ensure injection of service headers is not possible - for key, value in six.iteritems(self.service_token_expected_env): - header_key = key[len('HTTP_'):].replace('_', '-') - req.headers[header_key] = value - # Check arbitrary headers not removed - req.headers['X-Foo'] = 'Bar' - resp = req.get_response(self.middleware) - for key in six.iterkeys(self.service_token_expected_env): - header_key = key[len('HTTP_'):].replace('_', '-') - self.assertFalse(req.headers.get(header_key)) - self.assertEqual('Bar', req.headers.get('X-Foo')) - self.assertEqual(418, resp.status_int) - self.assertEqual(FakeApp.FORBIDDEN, resp.body) - - def test_composite_auth_delay_invalid_user_token(self): - self.middleware._delay_auth_decision = True - self.purge_token_expected_env() - expected_env = { - 'HTTP_X_IDENTITY_STATUS': 'Invalid', - } - self.update_expected_env(expected_env) - - token = 'invalid-token' - service_token = self.token_dict['uuid_service_token_default'] - resp = self.call_middleware(headers={'X-Auth-Token': token, - 'X-Service-Token': service_token}) - self.assertEqual(403, resp.status_int) - self.assertEqual(FakeApp.FORBIDDEN, resp.body) - - def test_composite_auth_delay_no_user_token(self): - self.middleware._delay_auth_decision = True - self.purge_token_expected_env() - expected_env = { - 'HTTP_X_IDENTITY_STATUS': 'Invalid', - } - self.update_expected_env(expected_env) - - service_token = self.token_dict['uuid_service_token_default'] - resp = self.call_middleware(headers={'X-Service-Token': service_token}) - self.assertEqual(403, resp.status_int) - self.assertEqual(FakeApp.FORBIDDEN, resp.body) - - -class v2CompositeAuthTests(BaseAuthTokenMiddlewareTest, - CommonCompositeAuthTests, - testresources.ResourcedTestCase): - """Test auth_token middleware with v2 token based composite auth. - - Execute the Composite auth class tests, but with the - auth_token middleware configured to expect v2 tokens back from - a keystone server. - """ - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def setUp(self): - super(v2CompositeAuthTests, self).setUp( - expected_env=EXPECTED_V2_DEFAULT_SERVICE_ENV_RESPONSE, - fake_app=CompositeFakeApp) - - uuid_token_default = self.examples.UUID_TOKEN_DEFAULT - uuid_service_token_default = self.examples.UUID_SERVICE_TOKEN_DEFAULT - self.token_dict = { - 'uuid_token_default': uuid_token_default, - 'uuid_service_token_default': uuid_service_token_default, - } - - self.requests_mock.get(BASE_URI, - json=VERSION_LIST_v2, - status_code=300) - - self.requests_mock.post('%s/v2.0/tokens' % BASE_URI, - text=FAKE_ADMIN_TOKEN) - - self.requests_mock.get('%s/v2.0/tokens/revoked' % BASE_URI, - text=self.examples.SIGNED_REVOCATION_LIST, - status_code=200) - - for token in (self.examples.UUID_TOKEN_DEFAULT, - self.examples.UUID_SERVICE_TOKEN_DEFAULT,): - text = self.examples.JSON_TOKEN_RESPONSES[token] - self.requests_mock.get('%s/v2.0/tokens/%s' % (BASE_URI, token), - text=text) - - for invalid_uri in ("%s/v2.0/tokens/invalid-token" % BASE_URI, - "%s/v2.0/tokens/invalid-service-token" % BASE_URI): - self.requests_mock.get(invalid_uri, text='', status_code=404) - - self.token_expected_env = dict(EXPECTED_V2_DEFAULT_ENV_RESPONSE) - self.service_token_expected_env = dict( - EXPECTED_V2_DEFAULT_SERVICE_ENV_RESPONSE) - self.set_middleware() - - -class v3CompositeAuthTests(BaseAuthTokenMiddlewareTest, - CommonCompositeAuthTests, - testresources.ResourcedTestCase): - """Test auth_token middleware with v3 token based composite auth. - - Execute the Composite auth class tests, but with the - auth_token middleware configured to expect v3 tokens back from - a keystone server. - """ - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def setUp(self): - super(v3CompositeAuthTests, self).setUp( - auth_version='v3.0', - fake_app=v3CompositeFakeApp) - - uuid_token_default = self.examples.v3_UUID_TOKEN_DEFAULT - uuid_serv_token_default = self.examples.v3_UUID_SERVICE_TOKEN_DEFAULT - self.token_dict = { - 'uuid_token_default': uuid_token_default, - 'uuid_service_token_default': uuid_serv_token_default, - } - - self.requests_mock.get(BASE_URI, json=VERSION_LIST_v3, status_code=300) - - # TODO(jamielennox): auth_token middleware uses a v2 admin token - # regardless of the auth_version that is set. - self.requests_mock.post('%s/v2.0/tokens' % BASE_URI, - text=FAKE_ADMIN_TOKEN) - - self.requests_mock.get('%s/v3/auth/tokens/OS-PKI/revoked' % BASE_URI, - text=self.examples.SIGNED_REVOCATION_LIST) - - self.requests_mock.get('%s/v3/auth/tokens' % BASE_URI, - text=self.token_response, - headers={'X-Subject-Token': uuid.uuid4().hex}) - - self.token_expected_env = dict(EXPECTED_V2_DEFAULT_ENV_RESPONSE) - self.token_expected_env.update(EXPECTED_V3_DEFAULT_ENV_ADDITIONS) - self.service_token_expected_env = dict( - EXPECTED_V2_DEFAULT_SERVICE_ENV_RESPONSE) - self.service_token_expected_env.update( - EXPECTED_V3_DEFAULT_SERVICE_ENV_ADDITIONS) - self.set_middleware() - - def token_response(self, request, context): - auth_id = request.headers.get('X-Auth-Token') - token_id = request.headers.get('X-Subject-Token') - self.assertEqual(auth_id, FAKE_ADMIN_TOKEN_ID) - - status = 200 - response = "" - - if token_id == ERROR_TOKEN: - raise exceptions.ConnectionRefused("Network connection refused.") - - try: - response = self.examples.JSON_TOKEN_RESPONSES[token_id] - except KeyError: - status = 404 - - context.status_code = status - return response - - -class OtherTests(BaseAuthTokenMiddlewareTest): - - def setUp(self): - super(OtherTests, self).setUp() - self.logger = self.useFixture(fixtures.FakeLogger()) - - def test_unknown_server_versions(self): - versions = fixture.DiscoveryList(v2=False, v3_id='v4', href=BASE_URI) - self.set_middleware() - - self.requests_mock.get(BASE_URI, json=versions, status_code=300) - - resp = self.call_middleware(headers={'X-Auth-Token': uuid.uuid4().hex}) - self.assertEqual(503, resp.status_int) - - self.assertIn('versions [v3.0, v2.0]', self.logger.output) - - def _assert_auth_version(self, conf_version, identity_server_version): - self.set_middleware(conf={'auth_version': conf_version}) - identity_server = self.middleware._create_identity_server() - self.assertEqual(identity_server_version, - identity_server.auth_version) - - def test_micro_version(self): - self._assert_auth_version('v2', (2, 0)) - self._assert_auth_version('v2.0', (2, 0)) - self._assert_auth_version('v3', (3, 0)) - self._assert_auth_version('v3.0', (3, 0)) - self._assert_auth_version('v3.1', (3, 0)) - self._assert_auth_version('v3.2', (3, 0)) - self._assert_auth_version('v3.9', (3, 0)) - self._assert_auth_version('v3.3.1', (3, 0)) - self._assert_auth_version('v3.3.5', (3, 0)) - - def test_default_auth_version(self): - # VERSION_LIST_v3 contains both v2 and v3 version elements - self.requests_mock.get(BASE_URI, json=VERSION_LIST_v3, status_code=300) - self._assert_auth_version(None, (3, 0)) - - # VERSION_LIST_v2 contains only v2 version elements - self.requests_mock.get(BASE_URI, json=VERSION_LIST_v2, status_code=300) - self._assert_auth_version(None, (2, 0)) - - def test_unsupported_auth_version(self): - # If the requested version isn't supported we will use v2 - self._assert_auth_version('v1', (2, 0)) - self._assert_auth_version('v10', (2, 0)) - - -class AuthProtocolLoadingTests(BaseAuthTokenMiddlewareTest): - - AUTH_URL = 'http://auth.url/prefix' - DISC_URL = 'http://disc.url/prefix' - KEYSTONE_BASE_URL = 'http://keystone.url/prefix' - CRUD_URL = 'http://crud.url/prefix' - - # NOTE(jamielennox): use the /v2.0 prefix here because this is what's most - # likely to be in the service catalog and we should be able to ignore it. - KEYSTONE_URL = KEYSTONE_BASE_URL + '/v2.0' - - def setUp(self): - super(AuthProtocolLoadingTests, self).setUp() - - self.project_id = uuid.uuid4().hex - - # first touch is to discover the available versions at the auth_url - self.requests_mock.get(self.AUTH_URL, - json=fixture.DiscoveryList(href=self.DISC_URL), - status_code=300) - - # then we do discovery on the URL from the service catalog. In practice - # this is mostly the same URL as before but test the full range. - self.requests_mock.get(self.KEYSTONE_BASE_URL + '/', - json=fixture.DiscoveryList(href=self.CRUD_URL), - status_code=300) - - def good_request(self, app): - # admin_token is the token that the service will get back from auth - admin_token_id = uuid.uuid4().hex - admin_token = fixture.V3Token(project_id=self.project_id) - s = admin_token.add_service('identity', name='keystone') - s.add_standard_endpoints(admin=self.KEYSTONE_URL) - - self.requests_mock.post(self.DISC_URL + '/v3/auth/tokens', - json=admin_token, - headers={'X-Subject-Token': admin_token_id}) - - # user_token is the data from the user's inputted token - user_token_id = uuid.uuid4().hex - user_token = fixture.V3Token() - user_token.set_project_scope() - - request_headers = {'X-Subject-Token': user_token_id, - 'X-Auth-Token': admin_token_id} - - self.requests_mock.get(self.CRUD_URL + '/v3/auth/tokens', - request_headers=request_headers, - json=user_token, - headers={'X-Subject-Token': uuid.uuid4().hex}) - - resp = self.call(app, headers={'X-Auth-Token': user_token_id}) - self.assertEqual(200, resp.status_int) - return resp - - def test_loading_password_plugin(self): - # the password options aren't set on config until loading time, but we - # need them set so we can override the values for testing, so force it - opts = auth.get_plugin_options('password') - self.cfg.register_opts(opts, group=_base.AUTHTOKEN_GROUP) - - project_id = uuid.uuid4().hex - - # Register the authentication options - auth.register_conf_options(self.cfg.conf, group=_base.AUTHTOKEN_GROUP) - - # configure the authentication options - self.cfg.config(auth_plugin='password', - username='testuser', - password='testpass', - auth_url=self.AUTH_URL, - project_id=project_id, - user_domain_id='userdomainid', - group=_base.AUTHTOKEN_GROUP) - - body = uuid.uuid4().hex - app = self.create_simple_middleware(body=body) - - resp = self.good_request(app) - self.assertEqual(six.b(body), resp.body) - - @staticmethod - def get_plugin(app): - return app._identity_server._adapter.auth - - def test_invalid_plugin_fails_to_initialize(self): - auth.register_conf_options(self.cfg.conf, group=_base.AUTHTOKEN_GROUP) - self.cfg.config(auth_plugin=uuid.uuid4().hex, - group=_base.AUTHTOKEN_GROUP) - - self.assertRaises( - exceptions.NoMatchingPlugin, - self.create_simple_middleware) - - def test_plugin_loading_mixed_opts(self): - # some options via override and some via conf - opts = auth.get_plugin_options('password') - self.cfg.register_opts(opts, group=_base.AUTHTOKEN_GROUP) - - username = 'testuser' - password = 'testpass' - - # Register the authentication options - auth.register_conf_options(self.cfg.conf, group=_base.AUTHTOKEN_GROUP) - - # configure the authentication options - self.cfg.config(auth_plugin='password', - password=password, - project_id=self.project_id, - user_domain_id='userdomainid', - group=_base.AUTHTOKEN_GROUP) - - conf = {'username': username, 'auth_url': self.AUTH_URL} - - body = uuid.uuid4().hex - app = self.create_simple_middleware(body=body, conf=conf) - - resp = self.good_request(app) - self.assertEqual(six.b(body), resp.body) - - plugin = self.get_plugin(app) - - self.assertEqual(self.AUTH_URL, plugin.auth_url) - self.assertEqual(username, plugin._username) - self.assertEqual(password, plugin._password) - self.assertEqual(self.project_id, plugin._project_id) - - def test_plugin_loading_with_auth_section(self): - # some options via override and some via conf - section = 'testsection' - username = 'testuser' - password = 'testpass' - - auth.register_conf_options(self.cfg.conf, group=section) - opts = auth.get_plugin_options('password') - self.cfg.register_opts(opts, group=section) - - # Register the authentication options - auth.register_conf_options(self.cfg.conf, group=_base.AUTHTOKEN_GROUP) - - # configure the authentication options - self.cfg.config(auth_section=section, group=_base.AUTHTOKEN_GROUP) - self.cfg.config(auth_plugin='password', - password=password, - project_id=self.project_id, - user_domain_id='userdomainid', - group=section) - - conf = {'username': username, 'auth_url': self.AUTH_URL} - - body = uuid.uuid4().hex - app = self.create_simple_middleware(body=body, conf=conf) - - resp = self.good_request(app) - self.assertEqual(six.b(body), resp.body) - - plugin = self.get_plugin(app) - - self.assertEqual(self.AUTH_URL, plugin.auth_url) - self.assertEqual(username, plugin._username) - self.assertEqual(password, plugin._password) - self.assertEqual(self.project_id, plugin._project_id) - - -class TestAuthPluginUserAgentGeneration(BaseAuthTokenMiddlewareTest): - - def setUp(self): - super(TestAuthPluginUserAgentGeneration, self).setUp() - self.auth_url = uuid.uuid4().hex - self.project_id = uuid.uuid4().hex - self.username = uuid.uuid4().hex - self.password = uuid.uuid4().hex - self.section = uuid.uuid4().hex - self.user_domain_id = uuid.uuid4().hex - - auth.register_conf_options(self.cfg.conf, group=self.section) - opts = auth.get_plugin_options('password') - self.cfg.register_opts(opts, group=self.section) - - # Register the authentication options - auth.register_conf_options(self.cfg.conf, group=_base.AUTHTOKEN_GROUP) - - # configure the authentication options - self.cfg.config(auth_section=self.section, group=_base.AUTHTOKEN_GROUP) - self.cfg.config(auth_plugin='password', - password=self.password, - project_id=self.project_id, - user_domain_id=self.user_domain_id, - group=self.section) - - def test_no_project_configured(self): - ksm_version = uuid.uuid4().hex - conf = {'username': self.username, 'auth_url': self.auth_url} - - app = self._create_app(conf, ksm_version) - self._assert_user_agent(app, '', ksm_version) - - def test_project_in_configuration(self): - project = uuid.uuid4().hex - project_version = uuid.uuid4().hex - - conf = {'username': self.username, - 'auth_url': self.auth_url, - 'project': project} - app = self._create_app(conf, project_version) - project_with_version = '{0}/{1} '.format(project, project_version) - self._assert_user_agent(app, project_with_version, project_version) - - def test_project_in_oslo_configuration(self): - project = uuid.uuid4().hex - project_version = uuid.uuid4().hex - - conf = {'username': self.username, 'auth_url': self.auth_url} - with mock.patch.object(cfg.CONF, 'project', new=project, create=True): - app = self._create_app(conf, project_version) - project = '{0}/{1} '.format(project, project_version) - self._assert_user_agent(app, project, project_version) - - def _create_app(self, conf, project_version): - fake_pkg_resources = mock.Mock() - fake_pkg_resources.get_distribution().version = project_version - - body = uuid.uuid4().hex - with mock.patch('keystonemiddleware.auth_token.pkg_resources', - new=fake_pkg_resources): - return self.create_simple_middleware(body=body, conf=conf, - use_global_conf=True) - - def _assert_user_agent(self, app, project, ksm_version): - sess = app._identity_server._adapter.session - expected_ua = ('{0}keystonemiddleware.auth_token/{1}' - .format(project, ksm_version)) - self.assertEqual(expected_ua, sess.user_agent) - - -class TestAuthPluginLocalOsloConfig(BaseAuthTokenMiddlewareTest): - def test_project_in_local_oslo_configuration(self): - options = { - 'auth_plugin': 'password', - 'auth_uri': uuid.uuid4().hex, - 'password': uuid.uuid4().hex, - } - - content = ("[keystone_authtoken]\n" - "auth_plugin=%(auth_plugin)s\n" - "auth_uri=%(auth_uri)s\n" - "password=%(password)s\n" % options) - conf_file_fixture = self.useFixture( - createfile.CreateFileWithContent("my_app", content)) - conf = {'oslo_config_project': 'my_app', - 'oslo_config_file': conf_file_fixture.path} - app = self._create_app(conf, uuid.uuid4().hex) - for option in options: - self.assertEqual(options[option], app._conf_get(option)) - - def _create_app(self, conf, project_version): - fake_pkg_resources = mock.Mock() - fake_pkg_resources.get_distribution().version = project_version - - body = uuid.uuid4().hex - with mock.patch('keystonemiddleware.auth_token.pkg_resources', - new=fake_pkg_resources): - return self.create_simple_middleware(body=body, conf=conf) - - -def load_tests(loader, tests, pattern): - return testresources.OptimisingTestSuite(tests) diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_base_middleware.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_base_middleware.py deleted file mode 100644 index b213f546..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_base_middleware.py +++ /dev/null @@ -1,202 +0,0 @@ -# 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 datetime -import uuid - -from keystoneclient import fixture -import mock -import six -import testtools -import webob - -from keystonemiddleware import auth_token -from keystonemiddleware.auth_token import _request - - -class FakeApp(object): - - @webob.dec.wsgify - def __call__(self, req): - return webob.Response() - - -class FetchingMiddleware(auth_token._BaseAuthProtocol): - - def __init__(self, app, token_dict={}, **kwargs): - super(FetchingMiddleware, self).__init__(app, **kwargs) - self.token_dict = token_dict - - def _fetch_token(self, token): - try: - return self.token_dict[token] - except KeyError: - raise auth_token.InvalidToken() - - -class BaseAuthProtocolTests(testtools.TestCase): - - @mock.patch.multiple(auth_token._BaseAuthProtocol, - process_request=mock.DEFAULT, - process_response=mock.DEFAULT) - def test_process_flow(self, process_request, process_response): - m = auth_token._BaseAuthProtocol(FakeApp()) - - process_request.return_value = None - process_response.side_effect = lambda x: x - - req = webob.Request.blank('/', method='GET') - resp = req.get_response(m) - - self.assertEqual(200, resp.status_code) - - self.assertEqual(1, process_request.call_count) - self.assertIsInstance(process_request.call_args[0][0], - _request._AuthTokenRequest) - - self.assertEqual(1, process_response.call_count) - self.assertIsInstance(process_response.call_args[0][0], webob.Response) - - @classmethod - def call(cls, middleware, method='GET', path='/', headers=None): - req = webob.Request.blank(path) - req.method = method - - for k, v in six.iteritems(headers or {}): - req.headers[k] = v - - resp = req.get_response(middleware) - resp.request = req - return resp - - def test_good_v3_user_token(self): - t = fixture.V3Token() - t.set_project_scope() - role = t.add_role() - - token_id = uuid.uuid4().hex - token_dict = {token_id: t} - - @webob.dec.wsgify - def _do_cb(req): - self.assertEqual(token_id, req.headers['X-Auth-Token']) - - self.assertEqual('Confirmed', req.headers['X-Identity-Status']) - self.assertNotIn('X-Service-Token', req.headers) - - p = req.environ['keystone.token_auth'] - - self.assertTrue(p.has_user_token) - self.assertFalse(p.has_service_token) - - self.assertEqual(t.project_id, p.user.project_id) - self.assertEqual(t.project_domain_id, p.user.project_domain_id) - self.assertEqual(t.user_id, p.user.user_id) - self.assertEqual(t.user_domain_id, p.user.user_domain_id) - self.assertIn(role['name'], p.user.role_names) - - return webob.Response() - - m = FetchingMiddleware(_do_cb, token_dict) - self.call(m, headers={'X-Auth-Token': token_id}) - - def test_invalid_user_token(self): - token_id = uuid.uuid4().hex - - @webob.dec.wsgify - def _do_cb(req): - self.assertEqual('Invalid', req.headers['X-Identity-Status']) - self.assertEqual(token_id, req.headers['X-Auth-Token']) - return webob.Response() - - m = FetchingMiddleware(_do_cb) - self.call(m, headers={'X-Auth-Token': token_id}) - - def test_expired_user_token(self): - t = fixture.V3Token() - t.set_project_scope() - t.expires = datetime.datetime.utcnow() - datetime.timedelta(minutes=10) - - token_id = uuid.uuid4().hex - token_dict = {token_id: t} - - @webob.dec.wsgify - def _do_cb(req): - self.assertEqual('Invalid', req.headers['X-Identity-Status']) - self.assertEqual(token_id, req.headers['X-Auth-Token']) - return webob.Response() - - m = FetchingMiddleware(_do_cb, token_dict=token_dict) - self.call(m, headers={'X-Auth-Token': token_id}) - - def test_good_v3_service_token(self): - t = fixture.V3Token() - t.set_project_scope() - role = t.add_role() - - token_id = uuid.uuid4().hex - token_dict = {token_id: t} - - @webob.dec.wsgify - def _do_cb(req): - self.assertEqual(token_id, req.headers['X-Service-Token']) - - self.assertEqual('Confirmed', - req.headers['X-Service-Identity-Status']) - self.assertNotIn('X-Auth-Token', req.headers) - - p = req.environ['keystone.token_auth'] - - self.assertFalse(p.has_user_token) - self.assertTrue(p.has_service_token) - - self.assertEqual(t.project_id, p.service.project_id) - self.assertEqual(t.project_domain_id, p.service.project_domain_id) - self.assertEqual(t.user_id, p.service.user_id) - self.assertEqual(t.user_domain_id, p.service.user_domain_id) - self.assertIn(role['name'], p.service.role_names) - - return webob.Response() - - m = FetchingMiddleware(_do_cb, token_dict) - self.call(m, headers={'X-Service-Token': token_id}) - - def test_invalid_service_token(self): - token_id = uuid.uuid4().hex - - @webob.dec.wsgify - def _do_cb(req): - self.assertEqual('Invalid', - req.headers['X-Service-Identity-Status']) - self.assertEqual(token_id, req.headers['X-Service-Token']) - return webob.Response() - - m = FetchingMiddleware(_do_cb) - self.call(m, headers={'X-Service-Token': token_id}) - - def test_expired_service_token(self): - t = fixture.V3Token() - t.set_project_scope() - t.expires = datetime.datetime.utcnow() - datetime.timedelta(minutes=10) - - token_id = uuid.uuid4().hex - token_dict = {token_id: t} - - @webob.dec.wsgify - def _do_cb(req): - self.assertEqual('Invalid', - req.headers['X-Service-Identity-Status']) - self.assertEqual(token_id, req.headers['X-Service-Token']) - return webob.Response() - - m = FetchingMiddleware(_do_cb, token_dict=token_dict) - self.call(m, headers={'X-Service-Token': token_id}) diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_connection_pool.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_connection_pool.py deleted file mode 100644 index 074d1e5d..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_connection_pool.py +++ /dev/null @@ -1,118 +0,0 @@ -# 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 time - -import mock -from six.moves import queue -import testtools -from testtools import matchers - -from keystonemiddleware.auth_token import _memcache_pool -from keystonemiddleware.tests.unit import utils - - -class _TestConnectionPool(_memcache_pool.ConnectionPool): - destroyed_value = 'destroyed' - - def _create_connection(self): - return mock.MagicMock() - - def _destroy_connection(self, conn): - conn(self.destroyed_value) - - -class TestConnectionPool(utils.TestCase): - def setUp(self): - super(TestConnectionPool, self).setUp() - self.unused_timeout = 10 - self.maxsize = 2 - self.connection_pool = _TestConnectionPool( - maxsize=self.maxsize, - unused_timeout=self.unused_timeout) - - def test_get_context_manager(self): - self.assertThat(self.connection_pool.queue, matchers.HasLength(0)) - with self.connection_pool.acquire() as conn: - self.assertEqual(1, self.connection_pool._acquired) - self.assertEqual(0, self.connection_pool._acquired) - self.assertThat(self.connection_pool.queue, matchers.HasLength(1)) - self.assertEqual(conn, self.connection_pool.queue[0].connection) - - def test_cleanup_pool(self): - self.test_get_context_manager() - newtime = time.time() + self.unused_timeout * 2 - non_expired_connection = _memcache_pool._PoolItem( - ttl=(newtime * 2), - connection=mock.MagicMock()) - self.connection_pool.queue.append(non_expired_connection) - self.assertThat(self.connection_pool.queue, matchers.HasLength(2)) - with mock.patch.object(time, 'time', return_value=newtime): - conn = self.connection_pool.queue[0].connection - with self.connection_pool.acquire(): - pass - conn.assert_has_calls( - [mock.call(self.connection_pool.destroyed_value)]) - self.assertThat(self.connection_pool.queue, matchers.HasLength(1)) - self.assertEqual(0, non_expired_connection.connection.call_count) - - def test_acquire_conn_exception_returns_acquired_count(self): - class TestException(Exception): - pass - - with mock.patch.object(_TestConnectionPool, '_create_connection', - side_effect=TestException): - with testtools.ExpectedException(TestException): - with self.connection_pool.acquire(): - pass - self.assertThat(self.connection_pool.queue, - matchers.HasLength(0)) - self.assertEqual(0, self.connection_pool._acquired) - - def test_connection_pool_limits_maximum_connections(self): - # NOTE(morganfainberg): To ensure we don't lockup tests until the - # job limit, explicitly call .get_nowait() and .put_nowait() in this - # case. - conn1 = self.connection_pool.get_nowait() - conn2 = self.connection_pool.get_nowait() - - # Use a nowait version to raise an Empty exception indicating we would - # not get another connection until one is placed back into the queue. - self.assertRaises(queue.Empty, self.connection_pool.get_nowait) - - # Place the connections back into the pool. - self.connection_pool.put_nowait(conn1) - self.connection_pool.put_nowait(conn2) - - # Make sure we can get a connection out of the pool again. - self.connection_pool.get_nowait() - - def test_connection_pool_maximum_connection_get_timeout(self): - connection_pool = _TestConnectionPool( - maxsize=1, - unused_timeout=self.unused_timeout, - conn_get_timeout=0) - - def _acquire_connection(): - with connection_pool.acquire(): - pass - - # Make sure we've consumed the only available connection from the pool - conn = connection_pool.get_nowait() - - self.assertRaises(_memcache_pool.ConnectionGetTimeoutException, - _acquire_connection) - - # Put the connection back and ensure we can acquire the connection - # after it is available. - connection_pool.put_nowait(conn) - _acquire_connection() diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_memcache_crypt.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_memcache_crypt.py deleted file mode 100644 index e9189831..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_memcache_crypt.py +++ /dev/null @@ -1,97 +0,0 @@ -# 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 six - -from keystonemiddleware.auth_token import _memcache_crypt as memcache_crypt -from keystonemiddleware.tests.unit import utils - - -class MemcacheCryptPositiveTests(utils.BaseTestCase): - def _setup_keys(self, strategy): - return memcache_crypt.derive_keys(b'token', b'secret', strategy) - - def test_constant_time_compare(self): - # make sure it works as a compare, the "constant time" aspect - # isn't appropriate to test in unittests - ctc = memcache_crypt.constant_time_compare - self.assertTrue(ctc('abcd', 'abcd')) - self.assertTrue(ctc('', '')) - self.assertFalse(ctc('abcd', 'efgh')) - self.assertFalse(ctc('abc', 'abcd')) - self.assertFalse(ctc('abc', 'abc\x00')) - self.assertFalse(ctc('', 'abc')) - - # For Python 3, we want to test these functions with both str and bytes - # as input. - if six.PY3: - self.assertTrue(ctc(b'abcd', b'abcd')) - self.assertTrue(ctc(b'', b'')) - self.assertFalse(ctc(b'abcd', b'efgh')) - self.assertFalse(ctc(b'abc', b'abcd')) - self.assertFalse(ctc(b'abc', b'abc\x00')) - self.assertFalse(ctc(b'', b'abc')) - - def test_derive_keys(self): - keys = self._setup_keys(b'strategy') - self.assertEqual(len(keys['ENCRYPTION']), - len(keys['CACHE_KEY'])) - self.assertEqual(len(keys['CACHE_KEY']), - len(keys['MAC'])) - self.assertNotEqual(keys['ENCRYPTION'], - keys['MAC']) - self.assertIn('strategy', keys.keys()) - - def test_key_strategy_diff(self): - k1 = self._setup_keys(b'MAC') - k2 = self._setup_keys(b'ENCRYPT') - self.assertNotEqual(k1, k2) - - def test_sign_data(self): - keys = self._setup_keys(b'MAC') - sig = memcache_crypt.sign_data(keys['MAC'], b'data') - self.assertEqual(len(sig), memcache_crypt.DIGEST_LENGTH_B64) - - def test_encryption(self): - keys = self._setup_keys(b'ENCRYPT') - # what you put in is what you get out - for data in [b'data', b'1234567890123456', b'\x00\xFF' * 13 - ] + [six.int2byte(x % 256) * x for x in range(768)]: - crypt = memcache_crypt.encrypt_data(keys['ENCRYPTION'], data) - decrypt = memcache_crypt.decrypt_data(keys['ENCRYPTION'], crypt) - self.assertEqual(data, decrypt) - self.assertRaises(memcache_crypt.DecryptError, - memcache_crypt.decrypt_data, - keys['ENCRYPTION'], crypt[:-1]) - - def test_protect_wrappers(self): - data = b'My Pretty Little Data' - for strategy in [b'MAC', b'ENCRYPT']: - keys = self._setup_keys(strategy) - protected = memcache_crypt.protect_data(keys, data) - self.assertNotEqual(protected, data) - if strategy == b'ENCRYPT': - self.assertNotIn(data, protected) - unprotected = memcache_crypt.unprotect_data(keys, protected) - self.assertEqual(data, unprotected) - self.assertRaises(memcache_crypt.InvalidMacError, - memcache_crypt.unprotect_data, - keys, protected[:-1]) - self.assertIsNone(memcache_crypt.unprotect_data(keys, None)) - - def test_no_pycrypt(self): - aes = memcache_crypt.AES - memcache_crypt.AES = None - self.assertRaises(memcache_crypt.CryptoUnavailableError, - memcache_crypt.encrypt_data, 'token', 'secret', - 'data') - memcache_crypt.AES = aes diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_request.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_request.py deleted file mode 100644 index 223433f8..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_request.py +++ /dev/null @@ -1,253 +0,0 @@ -# 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 itertools -import uuid - -from keystoneclient import access -from keystoneclient import fixture - -from keystonemiddleware.auth_token import _request -from keystonemiddleware.tests.unit import utils - - -class RequestObjectTests(utils.TestCase): - - def setUp(self): - super(RequestObjectTests, self).setUp() - self.request = _request._AuthTokenRequest.blank('/') - - def test_setting_user_token_valid(self): - self.assertNotIn('X-Identity-Status', self.request.headers) - - self.request.user_token_valid = True - self.assertEqual('Confirmed', - self.request.headers['X-Identity-Status']) - self.assertTrue(self.request.user_token_valid) - - self.request.user_token_valid = False - self.assertEqual('Invalid', - self.request.headers['X-Identity-Status']) - self.assertFalse(self.request.user_token_valid) - - def test_setting_service_token_valid(self): - self.assertNotIn('X-Service-Identity-Status', self.request.headers) - - self.request.service_token_valid = True - self.assertEqual('Confirmed', - self.request.headers['X-Service-Identity-Status']) - self.assertTrue(self.request.service_token_valid) - - self.request.service_token_valid = False - self.assertEqual('Invalid', - self.request.headers['X-Service-Identity-Status']) - self.assertFalse(self.request.service_token_valid) - - def test_removing_headers(self): - GOOD = ('X-Auth-Token', - 'unknownstring', - uuid.uuid4().hex) - - BAD = ('X-Domain-Id', - 'X-Domain-Name', - 'X-Project-Id', - 'X-Project-Name', - 'X-Project-Domain-Id', - 'X-Project-Domain-Name', - 'X-User-Id', - 'X-User-Name', - 'X-User-Domain-Id', - 'X-User-Domain-Name', - 'X-Roles', - 'X-Identity-Status', - - 'X-Service-Domain-Id', - 'X-Service-Domain-Name', - 'X-Service-Project-Id', - 'X-Service-Project-Name', - 'X-Service-Project-Domain-Id', - 'X-Service-Project-Domain-Name', - 'X-Service-User-Id', - 'X-Service-User-Name', - 'X-Service-User-Domain-Id', - 'X-Service-User-Domain-Name', - 'X-Service-Roles', - 'X-Service-Identity-Status', - - 'X-Service-Catalog', - - 'X-Role', - 'X-User', - 'X-Tenant-Id', - 'X-Tenant-Name', - 'X-Tenant', - ) - - header_vals = {} - - for header in itertools.chain(GOOD, BAD): - v = uuid.uuid4().hex - header_vals[header] = v - self.request.headers[header] = v - - self.request.remove_auth_headers() - - for header in BAD: - self.assertNotIn(header, self.request.headers) - - for header in GOOD: - self.assertEqual(header_vals[header], self.request.headers[header]) - - def _test_v3_headers(self, token, prefix): - self.assertEqual(token.domain_id, - self.request.headers['X%s-Domain-Id' % prefix]) - self.assertEqual(token.domain_name, - self.request.headers['X%s-Domain-Name' % prefix]) - self.assertEqual(token.project_id, - self.request.headers['X%s-Project-Id' % prefix]) - self.assertEqual(token.project_name, - self.request.headers['X%s-Project-Name' % prefix]) - self.assertEqual( - token.project_domain_id, - self.request.headers['X%s-Project-Domain-Id' % prefix]) - self.assertEqual( - token.project_domain_name, - self.request.headers['X%s-Project-Domain-Name' % prefix]) - - self.assertEqual(token.user_id, - self.request.headers['X%s-User-Id' % prefix]) - self.assertEqual(token.user_name, - self.request.headers['X%s-User-Name' % prefix]) - self.assertEqual( - token.user_domain_id, - self.request.headers['X%s-User-Domain-Id' % prefix]) - self.assertEqual( - token.user_domain_name, - self.request.headers['X%s-User-Domain-Name' % prefix]) - - def test_project_scoped_user_headers(self): - token = fixture.V3Token() - token.set_project_scope() - token_id = uuid.uuid4().hex - - auth_ref = access.AccessInfo.factory(token_id=token_id, body=token) - self.request.set_user_headers(auth_ref, include_service_catalog=True) - - self._test_v3_headers(token, '') - - def test_project_scoped_service_headers(self): - token = fixture.V3Token() - token.set_project_scope() - token_id = uuid.uuid4().hex - - auth_ref = access.AccessInfo.factory(token_id=token_id, body=token) - self.request.set_service_headers(auth_ref) - - self._test_v3_headers(token, '-Service') - - def test_auth_type(self): - self.assertIsNone(self.request.auth_type) - self.request.environ['AUTH_TYPE'] = 'NeGoTiatE' - self.assertEqual('negotiate', self.request.auth_type) - - def test_user_token(self): - token = uuid.uuid4().hex - self.assertIsNone(self.request.user_token) - self.request.headers['X-Auth-Token'] = token - self.assertEqual(token, self.request.user_token) - - def test_storage_token(self): - storage_token = uuid.uuid4().hex - user_token = uuid.uuid4().hex - - self.assertIsNone(self.request.user_token) - self.request.headers['X-Storage-Token'] = storage_token - self.assertEqual(storage_token, self.request.user_token) - self.request.headers['X-Auth-Token'] = user_token - self.assertEqual(user_token, self.request.user_token) - - def test_service_token(self): - token = uuid.uuid4().hex - self.assertIsNone(self.request.service_token) - self.request.headers['X-Service-Token'] = token - self.assertEqual(token, self.request.service_token) - - def test_token_auth(self): - plugin = object() - - self.assertNotIn('keystone.token_auth', self.request.environ) - self.request.token_auth = plugin - self.assertIs(plugin, self.request.environ['keystone.token_auth']) - self.assertIs(plugin, self.request.token_auth) - - -class CatalogConversionTests(utils.TestCase): - - PUBLIC_URL = 'http://server:5000/v2.0' - ADMIN_URL = 'http://admin:35357/v2.0' - INTERNAL_URL = 'http://internal:5000/v2.0' - - REGION_ONE = 'RegionOne' - REGION_TWO = 'RegionTwo' - REGION_THREE = 'RegionThree' - - def test_basic_convert(self): - token = fixture.V3Token() - s = token.add_service(type='identity') - s.add_standard_endpoints(public=self.PUBLIC_URL, - admin=self.ADMIN_URL, - internal=self.INTERNAL_URL, - region=self.REGION_ONE) - - auth_ref = access.AccessInfo.factory(body=token) - catalog_data = auth_ref.service_catalog.get_data() - catalog = _request._v3_to_v2_catalog(catalog_data) - - self.assertEqual(1, len(catalog)) - service = catalog[0] - self.assertEqual(1, len(service['endpoints'])) - endpoints = service['endpoints'][0] - - self.assertEqual('identity', service['type']) - self.assertEqual(4, len(endpoints)) - self.assertEqual(self.PUBLIC_URL, endpoints['publicURL']) - self.assertEqual(self.ADMIN_URL, endpoints['adminURL']) - self.assertEqual(self.INTERNAL_URL, endpoints['internalURL']) - self.assertEqual(self.REGION_ONE, endpoints['region']) - - def test_multi_region(self): - token = fixture.V3Token() - s = token.add_service(type='identity') - - s.add_endpoint('internal', self.INTERNAL_URL, region=self.REGION_ONE) - s.add_endpoint('public', self.PUBLIC_URL, region=self.REGION_TWO) - s.add_endpoint('admin', self.ADMIN_URL, region=self.REGION_THREE) - - auth_ref = access.AccessInfo.factory(body=token) - catalog_data = auth_ref.service_catalog.get_data() - catalog = _request._v3_to_v2_catalog(catalog_data) - - self.assertEqual(1, len(catalog)) - service = catalog[0] - - # the 3 regions will come through as 3 separate endpoints - expected = [{'internalURL': self.INTERNAL_URL, - 'region': self.REGION_ONE}, - {'publicURL': self.PUBLIC_URL, - 'region': self.REGION_TWO}, - {'adminURL': self.ADMIN_URL, - 'region': self.REGION_THREE}] - - self.assertEqual('identity', service['type']) - self.assertEqual(3, len(service['endpoints'])) - for e in expected: - self.assertIn(e, expected) diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_revocations.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_revocations.py deleted file mode 100644 index 258e195a..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_revocations.py +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright 2014 IBM Corp. -# -# 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 datetime -import json -import shutil -import uuid - -import mock - -from keystonemiddleware.auth_token import _exceptions as exc -from keystonemiddleware.auth_token import _revocations -from keystonemiddleware.auth_token import _signing_dir -from keystonemiddleware.tests.unit import utils - - -class RevocationsTests(utils.BaseTestCase): - - def _setup_revocations(self, revoked_list): - directory_name = '/tmp/%s' % uuid.uuid4().hex - signing_directory = _signing_dir.SigningDirectory(directory_name) - self.addCleanup(shutil.rmtree, directory_name) - - identity_server = mock.Mock() - - verify_result_obj = {'revoked': revoked_list} - cms_verify = mock.Mock(return_value=json.dumps(verify_result_obj)) - - revocations = _revocations.Revocations( - timeout=datetime.timedelta(1), signing_directory=signing_directory, - identity_server=identity_server, cms_verify=cms_verify) - return revocations - - def _check_with_list(self, revoked_list, token_ids): - revoked_list = list({'id': r} for r in revoked_list) - revocations = self._setup_revocations(revoked_list) - revocations.check(token_ids) - - def test_check_empty_list(self): - # When the identity server returns an empty list, a token isn't - # revoked. - - revoked_tokens = [] - token_ids = [uuid.uuid4().hex] - # No assert because this would raise - self._check_with_list(revoked_tokens, token_ids) - - def test_check_revoked(self): - # When the identity server returns a list with a token in it, that - # token is revoked. - - token_id = uuid.uuid4().hex - revoked_tokens = [token_id] - token_ids = [token_id] - self.assertRaises(exc.InvalidToken, - self._check_with_list, revoked_tokens, token_ids) - - def test_check_by_audit_id_revoked(self): - # When the audit ID is in the revocation list, InvalidToken is raised. - audit_id = uuid.uuid4().hex - revoked_list = [{'id': uuid.uuid4().hex, 'audit_id': audit_id}] - revocations = self._setup_revocations(revoked_list) - self.assertRaises(exc.InvalidToken, - revocations.check_by_audit_id, [audit_id]) - - def test_check_by_audit_id_chain_revoked(self): - # When the token's audit chain ID is in the revocation list, - # InvalidToken is raised. - revoked_audit_id = uuid.uuid4().hex - revoked_list = [{'id': uuid.uuid4().hex, 'audit_id': revoked_audit_id}] - revocations = self._setup_revocations(revoked_list) - - token_audit_ids = [uuid.uuid4().hex, revoked_audit_id] - self.assertRaises(exc.InvalidToken, - revocations.check_by_audit_id, token_audit_ids) - - def test_check_by_audit_id_not_revoked(self): - # When the audit ID is not in the revocation list no exception. - revoked_list = [{'id': uuid.uuid4().hex, 'audit_id': uuid.uuid4().hex}] - revocations = self._setup_revocations(revoked_list) - - audit_id = uuid.uuid4().hex - revocations.check_by_audit_id([audit_id]) - - def test_check_by_audit_id_no_audit_ids(self): - # Older identity servers don't send audit_ids in the revocation list. - # When this happens, check_by_audit_id still works, just doesn't - # verify anything. - revoked_list = [{'id': uuid.uuid4().hex}] - revocations = self._setup_revocations(revoked_list) - - audit_id = uuid.uuid4().hex - revocations.check_by_audit_id([audit_id]) diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_signing_dir.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_signing_dir.py deleted file mode 100644 index b2ef95dd..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_signing_dir.py +++ /dev/null @@ -1,137 +0,0 @@ -# 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 -import shutil -import stat -import uuid - -from keystonemiddleware.auth_token import _signing_dir -from keystonemiddleware.tests.unit import utils - - -class SigningDirectoryTests(utils.BaseTestCase): - - def test_directory_created_when_doesnt_exist(self): - # When _SigningDirectory is created, if the directory doesn't exist - # it's created with the expected permissions. - tmp_name = uuid.uuid4().hex - parent_directory = '/tmp/%s' % tmp_name - directory_name = '/tmp/%s/%s' % ((tmp_name,) * 2) - - # Directories are created by __init__. - _signing_dir.SigningDirectory(directory_name) - self.addCleanup(shutil.rmtree, parent_directory) - - self.assertTrue(os.path.isdir(directory_name)) - self.assertTrue(os.access(directory_name, os.W_OK)) - self.assertEqual(os.stat(directory_name).st_uid, os.getuid()) - self.assertEqual(stat.S_IMODE(os.stat(directory_name).st_mode), - stat.S_IRWXU) - - def test_use_directory_already_exists(self): - # The directory can already exist. - - tmp_name = uuid.uuid4().hex - parent_directory = '/tmp/%s' % tmp_name - directory_name = '/tmp/%s/%s' % ((tmp_name,) * 2) - os.makedirs(directory_name, stat.S_IRWXU) - self.addCleanup(shutil.rmtree, parent_directory) - - _signing_dir.SigningDirectory(directory_name) - - def test_write_file(self): - # write_file when the file doesn't exist creates the file. - - signing_directory = _signing_dir.SigningDirectory() - self.addCleanup(shutil.rmtree, signing_directory._directory_name) - - file_name = self.getUniqueString() - contents = self.getUniqueString() - signing_directory.write_file(file_name, contents) - - file_path = signing_directory.calc_path(file_name) - with open(file_path) as f: - actual_contents = f.read() - - self.assertEqual(contents, actual_contents) - - def test_replace_file(self): - # write_file when the file already exists overwrites it. - - signing_directory = _signing_dir.SigningDirectory() - self.addCleanup(shutil.rmtree, signing_directory._directory_name) - - file_name = self.getUniqueString() - orig_contents = self.getUniqueString() - signing_directory.write_file(file_name, orig_contents) - - new_contents = self.getUniqueString() - signing_directory.write_file(file_name, new_contents) - - file_path = signing_directory.calc_path(file_name) - with open(file_path) as f: - actual_contents = f.read() - - self.assertEqual(new_contents, actual_contents) - - def test_recreate_directory(self): - # If the original directory is lost, it gets recreated when a file - # is written. - - signing_directory = _signing_dir.SigningDirectory() - self.addCleanup(shutil.rmtree, signing_directory._directory_name) - - # Delete the directory. - shutil.rmtree(signing_directory._directory_name) - - file_name = self.getUniqueString() - contents = self.getUniqueString() - signing_directory.write_file(file_name, contents) - - actual_contents = signing_directory.read_file(file_name) - self.assertEqual(contents, actual_contents) - - def test_read_file(self): - # Can read a file that was written. - - signing_directory = _signing_dir.SigningDirectory() - self.addCleanup(shutil.rmtree, signing_directory._directory_name) - - file_name = self.getUniqueString() - contents = self.getUniqueString() - signing_directory.write_file(file_name, contents) - - actual_contents = signing_directory.read_file(file_name) - - self.assertEqual(contents, actual_contents) - - def test_read_file_doesnt_exist(self): - # Show what happens when try to read a file that wasn't written. - - signing_directory = _signing_dir.SigningDirectory() - self.addCleanup(shutil.rmtree, signing_directory._directory_name) - - file_name = self.getUniqueString() - self.assertRaises(IOError, signing_directory.read_file, file_name) - - def test_calc_path(self): - # calc_path returns the actual filename built from the directory name. - - signing_directory = _signing_dir.SigningDirectory() - self.addCleanup(shutil.rmtree, signing_directory._directory_name) - - file_name = self.getUniqueString() - actual_path = signing_directory.calc_path(file_name) - expected_path = os.path.join(signing_directory._directory_name, - file_name) - self.assertEqual(expected_path, actual_path) diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_user_auth_plugin.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_user_auth_plugin.py deleted file mode 100644 index 19d3d7a9..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_user_auth_plugin.py +++ /dev/null @@ -1,201 +0,0 @@ -# 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 uuid -import warnings - -from keystoneclient import auth -from keystoneclient import fixture - -from keystonemiddleware.auth_token import _base -from keystonemiddleware.tests.unit.auth_token import base - -# NOTE(jamielennox): just some sample values that we can use for testing -BASE_URI = 'https://keystone.example.com:1234' -AUTH_URL = 'https://keystone.auth.com:1234' - - -class BaseUserPluginTests(object): - - def configure_middleware(self, - auth_plugin, - group='keystone_authtoken', - **kwargs): - # NOTE(gyee): For this test suite and for the stable liberty branch - # only, we will ignore deprecated calls that keystonemiddleware makes. - warnings.filterwarnings('ignore', category=DeprecationWarning, - module='^keystonemiddleware\\.') - - opts = auth.get_plugin_class(auth_plugin).get_options() - self.cfg.register_opts(opts, group=group) - - # Since these tests cfg.config() themselves rather than waiting for - # auth_token to do it on __init__ we need to register the base auth - # options (e.g., auth_plugin) - auth.register_conf_options(self.cfg.conf, group=_base.AUTHTOKEN_GROUP) - - self.cfg.config(group=group, - auth_plugin=auth_plugin, - **kwargs) - - def assertTokenDataEqual(self, token_id, token, token_data): - self.assertEqual(token_id, token_data.auth_token) - self.assertEqual(token.user_id, token_data.user_id) - try: - trust_id = token.trust_id - except KeyError: - trust_id = None - self.assertEqual(trust_id, token_data.trust_id) - self.assertEqual(self.get_role_names(token), token_data.role_names) - - def get_plugin(self, token_id, service_token_id=None): - headers = {'X-Auth-Token': token_id} - - if service_token_id: - headers['X-Service-Token'] = service_token_id - - m = self.create_simple_middleware() - - resp = self.call(m, headers=headers) - self.assertEqual(200, resp.status_int) - return resp.request.environ['keystone.token_auth'] - - def test_user_information(self): - token_id, token = self.get_token() - plugin = self.get_plugin(token_id) - - self.assertTokenDataEqual(token_id, token, plugin.user) - self.assertFalse(plugin.has_service_token) - self.assertIsNone(plugin.service) - - def test_with_service_information(self): - token_id, token = self.get_token() - service_id, service = self.get_token() - - plugin = self.get_plugin(token_id, service_id) - - self.assertTokenDataEqual(token_id, token, plugin.user) - self.assertTokenDataEqual(service_id, service, plugin.service) - - -class V2UserPluginTests(BaseUserPluginTests, base.BaseAuthTokenTestCase): - - def setUp(self): - super(V2UserPluginTests, self).setUp() - - self.service_token = fixture.V2Token() - self.service_token.set_scope() - s = self.service_token.add_service('identity', name='keystone') - - s.add_endpoint(public=BASE_URI, - admin=BASE_URI, - internal=BASE_URI) - - self.configure_middleware(auth_plugin='v2password', - auth_url='%s/v2.0/' % AUTH_URL, - user_id=self.service_token.user_id, - password=uuid.uuid4().hex, - tenant_id=self.service_token.tenant_id) - - auth_discovery = fixture.DiscoveryList(href=AUTH_URL, v3=False) - self.requests_mock.get(AUTH_URL, json=auth_discovery) - - base_discovery = fixture.DiscoveryList(href=BASE_URI, v3=False) - self.requests_mock.get(BASE_URI, json=base_discovery) - - url = '%s/v2.0/tokens' % AUTH_URL - self.requests_mock.post(url, json=self.service_token) - - def get_role_names(self, token): - return set(x['name'] for x in token['access']['user'].get('roles', [])) - - def get_token(self): - token = fixture.V2Token() - token.set_scope() - token.add_role() - - request_headers = {'X-Auth-Token': self.service_token.token_id} - - url = '%s/v2.0/tokens/%s' % (BASE_URI, token.token_id) - self.requests_mock.get(url, - request_headers=request_headers, - json=token) - - return token.token_id, token - - def assertTokenDataEqual(self, token_id, token, token_data): - super(V2UserPluginTests, self).assertTokenDataEqual(token_id, - token, - token_data) - - self.assertEqual(token.tenant_id, token_data.project_id) - self.assertIsNone(token_data.user_domain_id) - self.assertIsNone(token_data.project_domain_id) - - -class V3UserPluginTests(BaseUserPluginTests, base.BaseAuthTokenTestCase): - - def setUp(self): - super(V3UserPluginTests, self).setUp() - - self.service_token_id = uuid.uuid4().hex - self.service_token = fixture.V3Token() - s = self.service_token.add_service('identity', name='keystone') - s.add_standard_endpoints(public=BASE_URI, - admin=BASE_URI, - internal=BASE_URI) - - self.configure_middleware(auth_plugin='v3password', - auth_url='%s/v3/' % AUTH_URL, - user_id=self.service_token.user_id, - password=uuid.uuid4().hex, - project_id=self.service_token.project_id) - - auth_discovery = fixture.DiscoveryList(href=AUTH_URL) - self.requests_mock.get(AUTH_URL, json=auth_discovery) - - base_discovery = fixture.DiscoveryList(href=BASE_URI) - self.requests_mock.get(BASE_URI, json=base_discovery) - - self.requests_mock.post( - '%s/v3/auth/tokens' % AUTH_URL, - headers={'X-Subject-Token': self.service_token_id}, - json=self.service_token) - - def get_role_names(self, token): - return set(x['name'] for x in token['token'].get('roles', [])) - - def get_token(self): - token_id = uuid.uuid4().hex - token = fixture.V3Token() - token.set_project_scope() - token.add_role() - - request_headers = {'X-Auth-Token': self.service_token_id, - 'X-Subject-Token': token_id} - headers = {'X-Subject-Token': token_id} - - self.requests_mock.get('%s/v3/auth/tokens' % BASE_URI, - request_headers=request_headers, - headers=headers, - json=token) - - return token_id, token - - def assertTokenDataEqual(self, token_id, token, token_data): - super(V3UserPluginTests, self).assertTokenDataEqual(token_id, - token, - token_data) - - self.assertEqual(token.user_domain_id, token_data.user_domain_id) - self.assertEqual(token.project_id, token_data.project_id) - self.assertEqual(token.project_domain_id, token_data.project_domain_id) diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_utils.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_utils.py deleted file mode 100644 index fcd1e628..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/auth_token/test_utils.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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 testtools - -from keystonemiddleware.auth_token import _utils - - -class TokenEncodingTest(testtools.TestCase): - - def test_unquoted_token(self): - self.assertEqual('foo%20bar', _utils.safe_quote('foo bar')) - - def test_quoted_token(self): - self.assertEqual('foo%20bar', _utils.safe_quote('foo%20bar')) - - def test_messages_encoded_as_bytes(self): - """Test that string are passed around as bytes for PY3.""" - msg = "This is an error" - - class FakeResp(_utils.MiniResp): - def __init__(self, error, env): - super(FakeResp, self).__init__(error, env) - - fake_resp = FakeResp(msg, dict(REQUEST_METHOD='GET')) - # On Py2 .encode() don't do much but that's better than to - # have a ifdef with six.PY3 - self.assertEqual(msg.encode(), fake_resp.body[0]) diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/client_fixtures.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/client_fixtures.py deleted file mode 100644 index ee4111ec..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/client_fixtures.py +++ /dev/null @@ -1,452 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# -# 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 - -import fixtures -from keystoneclient.common import cms -from keystoneclient import fixture -from keystoneclient import utils -from oslo_serialization import jsonutils -from oslo_utils import timeutils -import six -import testresources - - -TESTDIR = os.path.dirname(os.path.abspath(__file__)) -ROOTDIR = os.path.normpath(os.path.join(TESTDIR, '..', '..', '..')) -CERTDIR = os.path.join(ROOTDIR, 'examples', 'pki', 'certs') -CMSDIR = os.path.join(ROOTDIR, 'examples', 'pki', 'cms') -KEYDIR = os.path.join(ROOTDIR, 'examples', 'pki', 'private') - - -def _hash_signed_token_safe(signed_text, **kwargs): - if isinstance(signed_text, six.text_type): - signed_text = signed_text.encode('utf-8') - return utils.hash_signed_token(signed_text, **kwargs) - - -class Examples(fixtures.Fixture): - """Example tokens and certs loaded from the examples directory. - - To use this class correctly, the module needs to override the test suite - class to use testresources.OptimisingTestSuite (otherwise the files will - be read on every test). This is done by defining a load_tests function - in the module, like this: - - def load_tests(loader, tests, pattern): - return testresources.OptimisingTestSuite(tests) - - (see http://docs.python.org/2/library/unittest.html#load-tests-protocol ) - - """ - - def setUp(self): - super(Examples, self).setUp() - - # The data for several tests are signed using openssl and are stored in - # files in the signing subdirectory. In order to keep the values - # consistent between the tests and the signed documents, we read them - # in for use in the tests. - with open(os.path.join(CMSDIR, 'auth_token_scoped.json')) as f: - self.TOKEN_SCOPED_DATA = cms.cms_to_token(f.read()) - - with open(os.path.join(CMSDIR, 'auth_token_scoped.pem')) as f: - self.SIGNED_TOKEN_SCOPED = cms.cms_to_token(f.read()) - self.SIGNED_TOKEN_SCOPED_HASH = _hash_signed_token_safe( - self.SIGNED_TOKEN_SCOPED) - self.SIGNED_TOKEN_SCOPED_HASH_SHA256 = _hash_signed_token_safe( - self.SIGNED_TOKEN_SCOPED, mode='sha256') - with open(os.path.join(CMSDIR, 'auth_token_unscoped.pem')) as f: - self.SIGNED_TOKEN_UNSCOPED = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_v3_token_scoped.pem')) as f: - self.SIGNED_v3_TOKEN_SCOPED = cms.cms_to_token(f.read()) - self.SIGNED_v3_TOKEN_SCOPED_HASH = _hash_signed_token_safe( - self.SIGNED_v3_TOKEN_SCOPED) - self.SIGNED_v3_TOKEN_SCOPED_HASH_SHA256 = _hash_signed_token_safe( - self.SIGNED_v3_TOKEN_SCOPED, mode='sha256') - with open(os.path.join(CMSDIR, 'auth_token_revoked.pem')) as f: - self.REVOKED_TOKEN = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_token_scoped_expired.pem')) as f: - self.SIGNED_TOKEN_SCOPED_EXPIRED = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_v3_token_revoked.pem')) as f: - self.REVOKED_v3_TOKEN = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_token_scoped.pkiz')) as f: - self.SIGNED_TOKEN_SCOPED_PKIZ = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_token_unscoped.pkiz')) as f: - self.SIGNED_TOKEN_UNSCOPED_PKIZ = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_v3_token_scoped.pkiz')) as f: - self.SIGNED_v3_TOKEN_SCOPED_PKIZ = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_token_revoked.pkiz')) as f: - self.REVOKED_TOKEN_PKIZ = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, - 'auth_token_scoped_expired.pkiz')) as f: - self.SIGNED_TOKEN_SCOPED_EXPIRED_PKIZ = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_v3_token_revoked.pkiz')) as f: - self.REVOKED_v3_TOKEN_PKIZ = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'revocation_list.json')) as f: - self.REVOCATION_LIST = jsonutils.loads(f.read()) - with open(os.path.join(CMSDIR, 'revocation_list.pem')) as f: - self.SIGNED_REVOCATION_LIST = jsonutils.dumps({'signed': f.read()}) - - self.SIGNING_CERT_FILE = os.path.join(CERTDIR, 'signing_cert.pem') - with open(self.SIGNING_CERT_FILE) as f: - self.SIGNING_CERT = f.read() - - self.KERBEROS_BIND = 'USER@REALM' - - self.SIGNING_KEY_FILE = os.path.join(KEYDIR, 'signing_key.pem') - with open(self.SIGNING_KEY_FILE) as f: - self.SIGNING_KEY = f.read() - - self.SIGNING_CA_FILE = os.path.join(CERTDIR, 'cacert.pem') - with open(self.SIGNING_CA_FILE) as f: - self.SIGNING_CA = f.read() - - self.UUID_TOKEN_DEFAULT = "ec6c0710ec2f471498484c1b53ab4f9d" - self.UUID_TOKEN_NO_SERVICE_CATALOG = '8286720fbe4941e69fa8241723bb02df' - self.UUID_TOKEN_UNSCOPED = '731f903721c14827be7b2dc912af7776' - self.UUID_TOKEN_BIND = '3fc54048ad64405c98225ce0897af7c5' - self.UUID_TOKEN_UNKNOWN_BIND = '8885fdf4d42e4fb9879e6379fa1eaf48' - self.VALID_DIABLO_TOKEN = 'b0cf19b55dbb4f20a6ee18e6c6cf1726' - self.v3_UUID_TOKEN_DEFAULT = '5603457654b346fdbb93437bfe76f2f1' - self.v3_UUID_TOKEN_UNSCOPED = 'd34835fdaec447e695a0a024d84f8d79' - self.v3_UUID_TOKEN_DOMAIN_SCOPED = 'e8a7b63aaa4449f38f0c5c05c3581792' - self.v3_UUID_TOKEN_BIND = '2f61f73e1c854cbb9534c487f9bd63c2' - self.v3_UUID_TOKEN_UNKNOWN_BIND = '7ed9781b62cd4880b8d8c6788ab1d1e2' - - self.UUID_SERVICE_TOKEN_DEFAULT = 'fe4c0710ec2f492748596c1b53ab124' - self.v3_UUID_SERVICE_TOKEN_DEFAULT = 'g431071bbc2f492748596c1b53cb229' - - revoked_token = self.REVOKED_TOKEN - if isinstance(revoked_token, six.text_type): - revoked_token = revoked_token.encode('utf-8') - self.REVOKED_TOKEN_HASH = utils.hash_signed_token(revoked_token) - self.REVOKED_TOKEN_HASH_SHA256 = utils.hash_signed_token(revoked_token, - mode='sha256') - self.REVOKED_TOKEN_LIST = ( - {'revoked': [{'id': self.REVOKED_TOKEN_HASH, - 'expires': timeutils.utcnow()}]}) - self.REVOKED_TOKEN_LIST_JSON = jsonutils.dumps(self.REVOKED_TOKEN_LIST) - - revoked_v3_token = self.REVOKED_v3_TOKEN - if isinstance(revoked_v3_token, six.text_type): - revoked_v3_token = revoked_v3_token.encode('utf-8') - self.REVOKED_v3_TOKEN_HASH = utils.hash_signed_token(revoked_v3_token) - hash = utils.hash_signed_token(revoked_v3_token, mode='sha256') - self.REVOKED_v3_TOKEN_HASH_SHA256 = hash - self.REVOKED_v3_TOKEN_LIST = ( - {'revoked': [{'id': self.REVOKED_v3_TOKEN_HASH, - 'expires': timeutils.utcnow()}]}) - self.REVOKED_v3_TOKEN_LIST_JSON = jsonutils.dumps( - self.REVOKED_v3_TOKEN_LIST) - - revoked_token_pkiz = self.REVOKED_TOKEN_PKIZ - if isinstance(revoked_token_pkiz, six.text_type): - revoked_token_pkiz = revoked_token_pkiz.encode('utf-8') - self.REVOKED_TOKEN_PKIZ_HASH = utils.hash_signed_token( - revoked_token_pkiz) - revoked_v3_token_pkiz = self.REVOKED_v3_TOKEN_PKIZ - if isinstance(revoked_v3_token_pkiz, six.text_type): - revoked_v3_token_pkiz = revoked_v3_token_pkiz.encode('utf-8') - self.REVOKED_v3_PKIZ_TOKEN_HASH = utils.hash_signed_token( - revoked_v3_token_pkiz) - - self.REVOKED_TOKEN_PKIZ_LIST = ( - {'revoked': [{'id': self.REVOKED_TOKEN_PKIZ_HASH, - 'expires': timeutils.utcnow()}, - {'id': self.REVOKED_v3_PKIZ_TOKEN_HASH, - 'expires': timeutils.utcnow()}, - ]}) - self.REVOKED_TOKEN_PKIZ_LIST_JSON = jsonutils.dumps( - self.REVOKED_TOKEN_PKIZ_LIST) - - self.SIGNED_TOKEN_SCOPED_KEY = cms.cms_hash_token( - self.SIGNED_TOKEN_SCOPED) - self.SIGNED_TOKEN_UNSCOPED_KEY = cms.cms_hash_token( - self.SIGNED_TOKEN_UNSCOPED) - self.SIGNED_v3_TOKEN_SCOPED_KEY = cms.cms_hash_token( - self.SIGNED_v3_TOKEN_SCOPED) - - self.SIGNED_TOKEN_SCOPED_PKIZ_KEY = cms.cms_hash_token( - self.SIGNED_TOKEN_SCOPED_PKIZ) - self.SIGNED_TOKEN_UNSCOPED_PKIZ_KEY = cms.cms_hash_token( - self.SIGNED_TOKEN_UNSCOPED_PKIZ) - self.SIGNED_v3_TOKEN_SCOPED_PKIZ_KEY = cms.cms_hash_token( - self.SIGNED_v3_TOKEN_SCOPED_PKIZ) - - self.INVALID_SIGNED_TOKEN = ( - "MIIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" - "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" - "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD" - "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE" - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "0000000000000000000000000000000000000000000000000000000000000000" - "1111111111111111111111111111111111111111111111111111111111111111" - "2222222222222222222222222222222222222222222222222222222222222222" - "3333333333333333333333333333333333333333333333333333333333333333" - "4444444444444444444444444444444444444444444444444444444444444444" - "5555555555555555555555555555555555555555555555555555555555555555" - "6666666666666666666666666666666666666666666666666666666666666666" - "7777777777777777777777777777777777777777777777777777777777777777" - "8888888888888888888888888888888888888888888888888888888888888888" - "9999999999999999999999999999999999999999999999999999999999999999" - "0000000000000000000000000000000000000000000000000000000000000000") - - self.INVALID_SIGNED_PKIZ_TOKEN = ( - "PKIZ_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" - "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" - "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD" - "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE" - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "0000000000000000000000000000000000000000000000000000000000000000" - "1111111111111111111111111111111111111111111111111111111111111111" - "2222222222222222222222222222222222222222222222222222222222222222" - "3333333333333333333333333333333333333333333333333333333333333333" - "4444444444444444444444444444444444444444444444444444444444444444" - "5555555555555555555555555555555555555555555555555555555555555555" - "6666666666666666666666666666666666666666666666666666666666666666" - "7777777777777777777777777777777777777777777777777777777777777777" - "8888888888888888888888888888888888888888888888888888888888888888" - "9999999999999999999999999999999999999999999999999999999999999999" - "0000000000000000000000000000000000000000000000000000000000000000") - - # JSON responses keyed by token ID - self.TOKEN_RESPONSES = {} - - # basic values - PROJECT_ID = 'tenant_id1' - PROJECT_NAME = 'tenant_name1' - USER_ID = 'user_id1' - USER_NAME = 'user_name1' - DOMAIN_ID = 'domain_id1' - DOMAIN_NAME = 'domain_name1' - ROLE_NAME1 = 'role1' - ROLE_NAME2 = 'role2' - - SERVICE_PROJECT_ID = 'service_project_id1' - SERVICE_PROJECT_NAME = 'service_project_name1' - SERVICE_USER_ID = 'service_user_id1' - SERVICE_USER_NAME = 'service_user_name1' - SERVICE_DOMAIN_ID = 'service_domain_id1' - SERVICE_DOMAIN_NAME = 'service_domain_name1' - SERVICE_ROLE_NAME1 = 'service_role1' - SERVICE_ROLE_NAME2 = 'service_role2' - - self.SERVICE_TYPE = 'identity' - self.UNVERSIONED_SERVICE_URL = 'http://keystone.server:5000/' - self.SERVICE_URL = self.UNVERSIONED_SERVICE_URL + 'v2.0' - - # Old Tokens - - self.TOKEN_RESPONSES[self.VALID_DIABLO_TOKEN] = { - 'access': { - 'token': { - 'id': self.VALID_DIABLO_TOKEN, - 'expires': '2020-01-01T00:00:10.000123Z', - 'tenantId': PROJECT_ID, - }, - 'user': { - 'id': USER_ID, - 'name': USER_NAME, - 'roles': [ - {'name': ROLE_NAME1}, - {'name': ROLE_NAME2}, - ], - }, - }, - } - - # Generated V2 Tokens - - token = fixture.V2Token(token_id=self.UUID_TOKEN_DEFAULT, - tenant_id=PROJECT_ID, - tenant_name=PROJECT_NAME, - user_id=USER_ID, - user_name=USER_NAME) - token.add_role(name=ROLE_NAME1) - token.add_role(name=ROLE_NAME2) - svc = token.add_service(self.SERVICE_TYPE) - svc.add_endpoint(public=self.SERVICE_URL) - self.TOKEN_RESPONSES[self.UUID_TOKEN_DEFAULT] = token - - token = fixture.V2Token(token_id=self.UUID_TOKEN_UNSCOPED, - user_id=USER_ID, - user_name=USER_NAME) - self.TOKEN_RESPONSES[self.UUID_TOKEN_UNSCOPED] = token - - token = fixture.V2Token(token_id='valid-token', - tenant_id=PROJECT_ID, - tenant_name=PROJECT_NAME, - user_id=USER_ID, - user_name=USER_NAME) - token.add_role(ROLE_NAME1) - token.add_role(ROLE_NAME2) - self.TOKEN_RESPONSES[self.UUID_TOKEN_NO_SERVICE_CATALOG] = token - - token = fixture.V2Token(token_id=self.SIGNED_TOKEN_SCOPED_KEY, - tenant_id=PROJECT_ID, - tenant_name=PROJECT_NAME, - user_id=USER_ID, - user_name=USER_NAME) - token.add_role(ROLE_NAME1) - token.add_role(ROLE_NAME2) - self.TOKEN_RESPONSES[self.SIGNED_TOKEN_SCOPED_KEY] = token - - token = fixture.V2Token(token_id=self.SIGNED_TOKEN_UNSCOPED_KEY, - user_id=USER_ID, - user_name=USER_NAME) - self.TOKEN_RESPONSES[self.SIGNED_TOKEN_UNSCOPED_KEY] = token - - token = fixture.V2Token(token_id=self.UUID_TOKEN_BIND, - tenant_id=PROJECT_ID, - tenant_name=PROJECT_NAME, - user_id=USER_ID, - user_name=USER_NAME) - token.add_role(ROLE_NAME1) - token.add_role(ROLE_NAME2) - token['access']['token']['bind'] = {'kerberos': self.KERBEROS_BIND} - self.TOKEN_RESPONSES[self.UUID_TOKEN_BIND] = token - - token = fixture.V2Token(token_id=self.UUID_TOKEN_UNKNOWN_BIND, - tenant_id=PROJECT_ID, - tenant_name=PROJECT_NAME, - user_id=USER_ID, - user_name=USER_NAME) - token.add_role(ROLE_NAME1) - token.add_role(ROLE_NAME2) - token['access']['token']['bind'] = {'FOO': 'BAR'} - self.TOKEN_RESPONSES[self.UUID_TOKEN_UNKNOWN_BIND] = token - - token = fixture.V2Token(token_id=self.UUID_SERVICE_TOKEN_DEFAULT, - tenant_id=SERVICE_PROJECT_ID, - tenant_name=SERVICE_PROJECT_NAME, - user_id=SERVICE_USER_ID, - user_name=SERVICE_USER_NAME) - token.add_role(name=SERVICE_ROLE_NAME1) - token.add_role(name=SERVICE_ROLE_NAME2) - svc = token.add_service(self.SERVICE_TYPE) - svc.add_endpoint(public=self.SERVICE_URL) - self.TOKEN_RESPONSES[self.UUID_SERVICE_TOKEN_DEFAULT] = token - - # Generated V3 Tokens - - token = fixture.V3Token(user_id=USER_ID, - user_name=USER_NAME, - user_domain_id=DOMAIN_ID, - user_domain_name=DOMAIN_NAME, - project_id=PROJECT_ID, - project_name=PROJECT_NAME, - project_domain_id=DOMAIN_ID, - project_domain_name=DOMAIN_NAME) - token.add_role(id=ROLE_NAME1, name=ROLE_NAME1) - token.add_role(id=ROLE_NAME2, name=ROLE_NAME2) - svc = token.add_service(self.SERVICE_TYPE) - svc.add_endpoint('public', self.SERVICE_URL) - self.TOKEN_RESPONSES[self.v3_UUID_TOKEN_DEFAULT] = token - - token = fixture.V3Token(user_id=USER_ID, - user_name=USER_NAME, - user_domain_id=DOMAIN_ID, - user_domain_name=DOMAIN_NAME) - self.TOKEN_RESPONSES[self.v3_UUID_TOKEN_UNSCOPED] = token - - token = fixture.V3Token(user_id=USER_ID, - user_name=USER_NAME, - user_domain_id=DOMAIN_ID, - user_domain_name=DOMAIN_NAME, - domain_id=DOMAIN_ID, - domain_name=DOMAIN_NAME) - token.add_role(id=ROLE_NAME1, name=ROLE_NAME1) - token.add_role(id=ROLE_NAME2, name=ROLE_NAME2) - svc = token.add_service(self.SERVICE_TYPE) - svc.add_endpoint('public', self.SERVICE_URL) - self.TOKEN_RESPONSES[self.v3_UUID_TOKEN_DOMAIN_SCOPED] = token - - token = fixture.V3Token(user_id=USER_ID, - user_name=USER_NAME, - user_domain_id=DOMAIN_ID, - user_domain_name=DOMAIN_NAME, - project_id=PROJECT_ID, - project_name=PROJECT_NAME, - project_domain_id=DOMAIN_ID, - project_domain_name=DOMAIN_NAME) - token.add_role(name=ROLE_NAME1) - token.add_role(name=ROLE_NAME2) - svc = token.add_service(self.SERVICE_TYPE) - svc.add_endpoint('public', self.SERVICE_URL) - self.TOKEN_RESPONSES[self.SIGNED_v3_TOKEN_SCOPED_KEY] = token - - token = fixture.V3Token(user_id=USER_ID, - user_name=USER_NAME, - user_domain_id=DOMAIN_ID, - user_domain_name=DOMAIN_NAME, - project_id=PROJECT_ID, - project_name=PROJECT_NAME, - project_domain_id=DOMAIN_ID, - project_domain_name=DOMAIN_NAME) - token.add_role(name=ROLE_NAME1) - token.add_role(name=ROLE_NAME2) - svc = token.add_service(self.SERVICE_TYPE) - svc.add_endpoint('public', self.SERVICE_URL) - token['token']['bind'] = {'kerberos': self.KERBEROS_BIND} - self.TOKEN_RESPONSES[self.v3_UUID_TOKEN_BIND] = token - - token = fixture.V3Token(user_id=USER_ID, - user_name=USER_NAME, - user_domain_id=DOMAIN_ID, - user_domain_name=DOMAIN_NAME, - project_id=PROJECT_ID, - project_name=PROJECT_NAME, - project_domain_id=DOMAIN_ID, - project_domain_name=DOMAIN_NAME) - token.add_role(name=ROLE_NAME1) - token.add_role(name=ROLE_NAME2) - svc = token.add_service(self.SERVICE_TYPE) - svc.add_endpoint('public', self.SERVICE_URL) - token['token']['bind'] = {'FOO': 'BAR'} - self.TOKEN_RESPONSES[self.v3_UUID_TOKEN_UNKNOWN_BIND] = token - - token = fixture.V3Token(user_id=SERVICE_USER_ID, - user_name=SERVICE_USER_NAME, - user_domain_id=SERVICE_DOMAIN_ID, - user_domain_name=SERVICE_DOMAIN_NAME, - project_id=SERVICE_PROJECT_ID, - project_name=SERVICE_PROJECT_NAME, - project_domain_id=SERVICE_DOMAIN_ID, - project_domain_name=SERVICE_DOMAIN_NAME) - token.add_role(id=SERVICE_ROLE_NAME1, - name=SERVICE_ROLE_NAME1) - token.add_role(id=SERVICE_ROLE_NAME2, - name=SERVICE_ROLE_NAME2) - svc = token.add_service(self.SERVICE_TYPE) - svc.add_endpoint('public', self.SERVICE_URL) - self.TOKEN_RESPONSES[self.v3_UUID_SERVICE_TOKEN_DEFAULT] = token - - # PKIZ tokens generally link to above tokens - - self.TOKEN_RESPONSES[self.SIGNED_TOKEN_SCOPED_PKIZ_KEY] = ( - self.TOKEN_RESPONSES[self.SIGNED_TOKEN_SCOPED_KEY]) - self.TOKEN_RESPONSES[self.SIGNED_TOKEN_UNSCOPED_PKIZ_KEY] = ( - self.TOKEN_RESPONSES[self.SIGNED_TOKEN_UNSCOPED_KEY]) - self.TOKEN_RESPONSES[self.SIGNED_v3_TOKEN_SCOPED_PKIZ_KEY] = ( - self.TOKEN_RESPONSES[self.SIGNED_v3_TOKEN_SCOPED_KEY]) - - self.JSON_TOKEN_RESPONSES = dict([(k, jsonutils.dumps(v)) for k, v in - six.iteritems(self.TOKEN_RESPONSES)]) - - -EXAMPLES_RESOURCE = testresources.FixtureResource(Examples()) diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/test_audit_middleware.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/test_audit_middleware.py deleted file mode 100644 index fc761c0f..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/test_audit_middleware.py +++ /dev/null @@ -1,560 +0,0 @@ -# -# 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 -import tempfile -import uuid -import warnings - -import mock -from oslo_config import cfg -from pycadf import identifier -from testtools import matchers -import webob - -from keystonemiddleware import audit -from keystonemiddleware.tests.unit import utils - - -class FakeApp(object): - def __call__(self, env, start_response): - body = 'Some response' - start_response('200 OK', [ - ('Content-Type', 'text/plain'), - ('Content-Length', str(sum(map(len, body)))) - ]) - return [body] - - -class FakeFailingApp(object): - def __call__(self, env, start_response): - raise Exception('It happens!') - - -class BaseAuditMiddlewareTest(utils.BaseTestCase): - def setUp(self): - super(BaseAuditMiddlewareTest, self).setUp() - self.fd, self.audit_map = tempfile.mkstemp() - - with open(self.audit_map, "w") as f: - f.write("[custom_actions]\n") - f.write("reboot = start/reboot\n") - f.write("os-migrations/get = read\n\n") - f.write("[path_keywords]\n") - f.write("action = None\n") - f.write("os-hosts = host\n") - f.write("os-migrations = None\n") - f.write("reboot = None\n") - f.write("servers = server\n\n") - f.write("[service_endpoints]\n") - f.write("compute = service/compute") - - cfg.CONF([], project='keystonemiddleware') - - self.middleware = audit.AuditMiddleware( - FakeApp(), audit_map_file=self.audit_map, - service_name='pycadf') - - # NOTE(stevemar): For this test suite and for the stable liberty branch - # only, we will ignore deprecated calls that keystonemiddleware makes. - warnings.filterwarnings('ignore', category=DeprecationWarning, - module='^keystonemiddleware\\.') - - self.addCleanup(lambda: os.close(self.fd)) - self.addCleanup(cfg.CONF.reset) - - @staticmethod - def get_environ_header(req_type): - env_headers = {'HTTP_X_SERVICE_CATALOG': - '''[{"endpoints_links": [], - "endpoints": [{"adminURL": - "http://admin_host:8774", - "region": "RegionOne", - "publicURL": - "http://public_host:8774", - "internalURL": - "http://internal_host:8774", - "id": "resource_id"}], - "type": "compute", - "name": "nova"},]''', - 'HTTP_X_USER_ID': 'user_id', - 'HTTP_X_USER_NAME': 'user_name', - 'HTTP_X_AUTH_TOKEN': 'token', - 'HTTP_X_PROJECT_ID': 'tenant_id', - 'HTTP_X_IDENTITY_STATUS': 'Confirmed'} - env_headers['REQUEST_METHOD'] = req_type - return env_headers - - -@mock.patch('oslo_messaging.get_transport', mock.MagicMock()) -class AuditMiddlewareTest(BaseAuditMiddlewareTest): - - def test_api_request(self): - req = webob.Request.blank('/foo/bar', - environ=self.get_environ_header('GET')) - with mock.patch('oslo_messaging.Notifier.info') as notify: - self.middleware(req) - # Check first notification with only 'request' - call_args = notify.call_args_list[0][0] - self.assertEqual('audit.http.request', call_args[1]) - self.assertEqual('/foo/bar', call_args[2]['requestPath']) - self.assertEqual('pending', call_args[2]['outcome']) - self.assertNotIn('reason', call_args[2]) - self.assertNotIn('reporterchain', call_args[2]) - - # Check second notification with request + response - call_args = notify.call_args_list[1][0] - self.assertEqual('audit.http.response', call_args[1]) - self.assertEqual('/foo/bar', call_args[2]['requestPath']) - self.assertEqual('success', call_args[2]['outcome']) - self.assertIn('reason', call_args[2]) - self.assertIn('reporterchain', call_args[2]) - - def test_api_request_failure(self): - self.middleware = audit.AuditMiddleware( - FakeFailingApp(), - audit_map_file=self.audit_map, - service_name='pycadf') - req = webob.Request.blank('/foo/bar', - environ=self.get_environ_header('GET')) - with mock.patch('oslo_messaging.Notifier.info') as notify: - try: - self.middleware(req) - self.fail('Application exception has not been re-raised') - except Exception: - pass - # Check first notification with only 'request' - call_args = notify.call_args_list[0][0] - self.assertEqual('audit.http.request', call_args[1]) - self.assertEqual('/foo/bar', call_args[2]['requestPath']) - self.assertEqual('pending', call_args[2]['outcome']) - self.assertNotIn('reporterchain', call_args[2]) - - # Check second notification with request + response - call_args = notify.call_args_list[1][0] - self.assertEqual('audit.http.response', call_args[1]) - self.assertEqual('/foo/bar', call_args[2]['requestPath']) - self.assertEqual('unknown', call_args[2]['outcome']) - self.assertIn('reporterchain', call_args[2]) - - def test_process_request_fail(self): - req = webob.Request.blank('/foo/bar', - environ=self.get_environ_header('GET')) - with mock.patch('oslo_messaging.Notifier.info', - side_effect=Exception('error')) as notify: - self.middleware._process_request(req) - self.assertTrue(notify.called) - - def test_process_response_fail(self): - req = webob.Request.blank('/foo/bar', - environ=self.get_environ_header('GET')) - with mock.patch('oslo_messaging.Notifier.info', - side_effect=Exception('error')) as notify: - self.middleware._process_response(req, webob.response.Response()) - self.assertTrue(notify.called) - - def test_ignore_req_opt(self): - self.middleware = audit.AuditMiddleware(FakeApp(), - audit_map_file=self.audit_map, - ignore_req_list='get, PUT') - req = webob.Request.blank('/skip/foo', - environ=self.get_environ_header('GET')) - req1 = webob.Request.blank('/skip/foo', - environ=self.get_environ_header('PUT')) - req2 = webob.Request.blank('/accept/foo', - environ=self.get_environ_header('POST')) - with mock.patch('oslo_messaging.Notifier.info') as notify: - # Check GET/PUT request does not send notification - self.middleware(req) - self.middleware(req1) - self.assertEqual([], notify.call_args_list) - - # Check non-GET/PUT request does send notification - self.middleware(req2) - self.assertThat(notify.call_args_list, matchers.HasLength(2)) - call_args = notify.call_args_list[0][0] - self.assertEqual('audit.http.request', call_args[1]) - self.assertEqual('/accept/foo', call_args[2]['requestPath']) - - call_args = notify.call_args_list[1][0] - self.assertEqual('audit.http.response', call_args[1]) - self.assertEqual('/accept/foo', call_args[2]['requestPath']) - - def test_api_request_no_messaging(self): - req = webob.Request.blank('/foo/bar', - environ=self.get_environ_header('GET')) - with mock.patch('keystonemiddleware.audit.messaging', None): - with mock.patch('keystonemiddleware.audit._LOG.info') as log: - self.middleware(req) - # Check first notification with only 'request' - call_args = log.call_args_list[0][0] - self.assertEqual('audit.http.request', - call_args[1]['event_type']) - - # Check second notification with request + response - call_args = log.call_args_list[1][0] - self.assertEqual('audit.http.response', - call_args[1]['event_type']) - - def test_cadf_event_scoped_to_request(self): - middleware = audit.AuditMiddleware( - FakeApp(), - audit_map_file=self.audit_map, - service_name='pycadf') - req = webob.Request.blank('/foo/bar', - environ=self.get_environ_header('GET')) - with mock.patch('oslo_messaging.Notifier.info') as notify: - middleware(req) - self.assertIsNotNone(req.environ.get('cadf_event')) - - # ensure exact same event is used between request and response - self.assertEqual(notify.call_args_list[0][0][2]['id'], - notify.call_args_list[1][0][2]['id']) - - def test_cadf_event_scoped_to_request_on_error(self): - middleware = audit.AuditMiddleware( - FakeApp(), - audit_map_file=self.audit_map, - service_name='pycadf') - req = webob.Request.blank('/foo/bar', - environ=self.get_environ_header('GET')) - with mock.patch('oslo_messaging.Notifier.info', - side_effect=Exception('error')) as notify: - middleware._process_request(req) - self.assertTrue(notify.called) - req2 = webob.Request.blank('/foo/bar', - environ=self.get_environ_header('GET')) - with mock.patch('oslo_messaging.Notifier.info') as notify: - middleware._process_response(req2, webob.response.Response()) - self.assertTrue(notify.called) - # ensure event is not the same across requests - self.assertNotEqual(req.environ['cadf_event'].id, - notify.call_args_list[0][0][2]['id']) - - -@mock.patch('oslo_messaging.rpc', mock.MagicMock()) -class AuditApiLogicTest(BaseAuditMiddlewareTest): - - def api_request(self, method, url): - req = webob.Request.blank(url, environ=self.get_environ_header(method), - remote_addr='192.168.0.1') - self.middleware._process_request(req) - return req - - def test_get_list(self): - req = self.api_request('GET', 'http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/servers') - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['action'], 'read/list') - self.assertEqual(payload['typeURI'], - 'http://schemas.dmtf.org/cloud/audit/1.0/event') - self.assertEqual(payload['outcome'], 'pending') - self.assertEqual(payload['eventType'], 'activity') - self.assertEqual(payload['target']['name'], 'nova') - self.assertEqual(payload['target']['id'], 'openstack:resource_id') - self.assertEqual(payload['target']['typeURI'], - 'service/compute/servers') - self.assertEqual(len(payload['target']['addresses']), 3) - self.assertEqual(payload['target']['addresses'][0]['name'], 'admin') - self.assertEqual(payload['target']['addresses'][0]['url'], - 'http://admin_host:8774') - self.assertEqual(payload['initiator']['id'], 'openstack:user_id') - self.assertEqual(payload['initiator']['name'], 'user_name') - self.assertEqual(payload['initiator']['project_id'], - 'openstack:tenant_id') - self.assertEqual(payload['initiator']['host']['address'], - '192.168.0.1') - self.assertEqual(payload['initiator']['typeURI'], - 'service/security/account/user') - self.assertNotEqual(payload['initiator']['credential']['token'], - 'token') - self.assertEqual(payload['initiator']['credential']['identity_status'], - 'Confirmed') - self.assertNotIn('reason', payload) - self.assertNotIn('reporterchain', payload) - self.assertEqual(payload['observer']['id'], 'target') - self.assertEqual(req.path, payload['requestPath']) - - def test_get_read(self): - req = self.api_request('GET', 'http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/servers/' - + str(uuid.uuid4())) - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['target']['typeURI'], - 'service/compute/servers/server') - self.assertEqual(payload['action'], 'read') - self.assertEqual(payload['outcome'], 'pending') - - def test_get_unknown_endpoint(self): - req = self.api_request('GET', 'http://unknown:8774/v2/' - + str(uuid.uuid4()) + '/servers') - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['action'], 'read/list') - self.assertEqual(payload['outcome'], 'pending') - self.assertEqual(payload['target']['name'], 'unknown') - self.assertEqual(payload['target']['id'], 'unknown') - self.assertEqual(payload['target']['typeURI'], 'unknown') - - def test_get_unknown_endpoint_default_set(self): - with open(self.audit_map, "w") as f: - f.write("[DEFAULT]\n") - f.write("target_endpoint_type = compute\n") - f.write("[path_keywords]\n") - f.write("servers = server\n\n") - f.write("[service_endpoints]\n") - f.write("compute = service/compute") - - self.middleware = audit.AuditMiddleware( - FakeApp(), audit_map_file=self.audit_map, - service_name='pycadf') - - req = self.api_request('GET', 'http://unknown:8774/v2/' - + str(uuid.uuid4()) + '/servers') - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['action'], 'read/list') - self.assertEqual(payload['outcome'], 'pending') - self.assertEqual(payload['target']['name'], 'nova') - self.assertEqual(payload['target']['id'], 'openstack:resource_id') - self.assertEqual(payload['target']['typeURI'], - 'service/compute/servers') - - def test_put(self): - req = self.api_request('PUT', 'http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/servers') - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['target']['typeURI'], - 'service/compute/servers') - self.assertEqual(payload['action'], 'update') - self.assertEqual(payload['outcome'], 'pending') - - def test_delete(self): - req = self.api_request('DELETE', 'http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/servers') - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['target']['typeURI'], - 'service/compute/servers') - self.assertEqual(payload['action'], 'delete') - self.assertEqual(payload['outcome'], 'pending') - - def test_head(self): - req = self.api_request('HEAD', 'http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/servers') - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['target']['typeURI'], - 'service/compute/servers') - self.assertEqual(payload['action'], 'read') - self.assertEqual(payload['outcome'], 'pending') - - def test_post_update(self): - req = self.api_request('POST', - 'http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/servers/' - + str(uuid.uuid4())) - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['target']['typeURI'], - 'service/compute/servers/server') - self.assertEqual(payload['action'], 'update') - self.assertEqual(payload['outcome'], 'pending') - - def test_post_create(self): - req = self.api_request('POST', 'http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/servers') - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['target']['typeURI'], - 'service/compute/servers') - self.assertEqual(payload['action'], 'create') - self.assertEqual(payload['outcome'], 'pending') - - def test_post_action(self): - req = webob.Request.blank('http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/servers/action', - environ=self.get_environ_header('POST')) - req.body = b'{"createImage" : {"name" : "new-image","metadata": ' \ - b'{"ImageType": "Gold","ImageVersion": "2.0"}}}' - self.middleware._process_request(req) - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['target']['typeURI'], - 'service/compute/servers/action') - self.assertEqual(payload['action'], 'update/createImage') - self.assertEqual(payload['outcome'], 'pending') - - def test_post_empty_body_action(self): - req = self.api_request('POST', 'http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/servers/action') - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['target']['typeURI'], - 'service/compute/servers/action') - self.assertEqual(payload['action'], 'create') - self.assertEqual(payload['outcome'], 'pending') - - def test_custom_action(self): - req = self.api_request('GET', 'http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/os-hosts/' - + str(uuid.uuid4()) + '/reboot') - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['target']['typeURI'], - 'service/compute/os-hosts/host/reboot') - self.assertEqual(payload['action'], 'start/reboot') - self.assertEqual(payload['outcome'], 'pending') - - def test_custom_action_complex(self): - req = self.api_request('GET', 'http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/os-migrations') - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['target']['typeURI'], - 'service/compute/os-migrations') - self.assertEqual(payload['action'], 'read') - req = self.api_request('POST', 'http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/os-migrations') - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['target']['typeURI'], - 'service/compute/os-migrations') - self.assertEqual(payload['action'], 'create') - - def test_response_mod_msg(self): - req = self.api_request('GET', 'http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/servers') - payload = req.environ['cadf_event'].as_dict() - self.middleware._process_response(req, webob.Response()) - payload2 = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['id'], payload2['id']) - self.assertEqual(payload['tags'], payload2['tags']) - self.assertEqual(payload2['outcome'], 'success') - self.assertEqual(payload2['reason']['reasonType'], 'HTTP') - self.assertEqual(payload2['reason']['reasonCode'], '200') - self.assertEqual(len(payload2['reporterchain']), 1) - self.assertEqual(payload2['reporterchain'][0]['role'], 'modifier') - self.assertEqual(payload2['reporterchain'][0]['reporter']['id'], - 'target') - - def test_no_response(self): - req = self.api_request('GET', 'http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/servers') - payload = req.environ['cadf_event'].as_dict() - self.middleware._process_response(req, None) - payload2 = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['id'], payload2['id']) - self.assertEqual(payload['tags'], payload2['tags']) - self.assertEqual(payload2['outcome'], 'unknown') - self.assertNotIn('reason', payload2) - self.assertEqual(len(payload2['reporterchain']), 1) - self.assertEqual(payload2['reporterchain'][0]['role'], 'modifier') - self.assertEqual(payload2['reporterchain'][0]['reporter']['id'], - 'target') - - def test_missing_req(self): - req = webob.Request.blank('http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/servers', - environ=self.get_environ_header('GET')) - self.assertNotIn('cadf_event', req.environ) - self.middleware._process_response(req, webob.Response()) - self.assertIn('cadf_event', req.environ) - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['outcome'], 'success') - self.assertEqual(payload['reason']['reasonType'], 'HTTP') - self.assertEqual(payload['reason']['reasonCode'], '200') - self.assertEqual(payload['observer']['id'], 'target') - - def test_missing_catalog_endpoint_id(self): - env_headers = {'HTTP_X_SERVICE_CATALOG': - '''[{"endpoints_links": [], - "endpoints": [{"adminURL": - "http://admin_host:8774", - "region": "RegionOne", - "publicURL": - "http://public_host:8774", - "internalURL": - "http://internal_host:8774"}], - "type": "compute", - "name": "nova"},]''', - 'HTTP_X_USER_ID': 'user_id', - 'HTTP_X_USER_NAME': 'user_name', - 'HTTP_X_AUTH_TOKEN': 'token', - 'HTTP_X_PROJECT_ID': 'tenant_id', - 'HTTP_X_IDENTITY_STATUS': 'Confirmed', - 'REQUEST_METHOD': 'GET'} - req = webob.Request.blank('http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/servers', - environ=env_headers) - self.middleware._process_request(req) - payload = req.environ['cadf_event'].as_dict() - self.assertEqual(payload['target']['id'], identifier.norm_ns('nova')) - - def test_endpoint_missing_internal_url(self): - env_headers = {'HTTP_X_SERVICE_CATALOG': - '''[{"endpoints_links": [], - "endpoints": [{"adminURL": - "http://admin_host:8774", - "region": "RegionOne", - "publicURL": - "http://public_host:8774"}], - "type": "compute", - "name": "nova"},]''', - 'HTTP_X_USER_ID': 'user_id', - 'HTTP_X_USER_NAME': 'user_name', - 'HTTP_X_AUTH_TOKEN': 'token', - 'HTTP_X_PROJECT_ID': 'tenant_id', - 'HTTP_X_IDENTITY_STATUS': 'Confirmed', - 'REQUEST_METHOD': 'GET'} - req = webob.Request.blank('http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/servers', - environ=env_headers) - self.middleware._process_request(req) - payload = req.environ['cadf_event'].as_dict() - self.assertEqual((payload['target']['addresses'][1]['url']), "unknown") - - def test_endpoint_missing_public_url(self): - env_headers = {'HTTP_X_SERVICE_CATALOG': - '''[{"endpoints_links": [], - "endpoints": [{"adminURL": - "http://admin_host:8774", - "region": "RegionOne", - "internalURL": - "http://internal_host:8774"}], - "type": "compute", - "name": "nova"},]''', - 'HTTP_X_USER_ID': 'user_id', - 'HTTP_X_USER_NAME': 'user_name', - 'HTTP_X_AUTH_TOKEN': 'token', - 'HTTP_X_PROJECT_ID': 'tenant_id', - 'HTTP_X_IDENTITY_STATUS': 'Confirmed', - 'REQUEST_METHOD': 'GET'} - req = webob.Request.blank('http://admin_host:8774/v2/' - + str(uuid.uuid4()) + '/servers', - environ=env_headers) - self.middleware._process_request(req) - payload = req.environ['cadf_event'].as_dict() - self.assertEqual((payload['target']['addresses'][2]['url']), "unknown") - - def test_endpoint_missing_admin_url(self): - env_headers = {'HTTP_X_SERVICE_CATALOG': - '''[{"endpoints_links": [], - "endpoints": [{"region": "RegionOne", - "publicURL": - "http://public_host:8774", - "internalURL": - "http://internal_host:8774"}], - "type": "compute", - "name": "nova"},]''', - 'HTTP_X_USER_ID': 'user_id', - 'HTTP_X_USER_NAME': 'user_name', - 'HTTP_X_AUTH_TOKEN': 'token', - 'HTTP_X_PROJECT_ID': 'tenant_id', - 'HTTP_X_IDENTITY_STATUS': 'Confirmed', - 'REQUEST_METHOD': 'GET'} - req = webob.Request.blank('http://public_host:8774/v2/' - + str(uuid.uuid4()) + '/servers', - environ=env_headers) - self.middleware._process_request(req) - payload = req.environ['cadf_event'].as_dict() - self.assertEqual((payload['target']['addresses'][0]['url']), "unknown") diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/test_opts.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/test_opts.py deleted file mode 100644 index 9ddb8005..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/test_opts.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (c) 2014 OpenStack Foundation. -# -# 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 stevedore -from testtools import matchers - -from keystonemiddleware import opts -from keystonemiddleware.tests.unit import utils - - -class OptsTestCase(utils.TestCase): - - def _test_list_auth_token_opts(self, result): - self.assertThat(result, matchers.HasLength(1)) - - for group in (g for (g, _l) in result): - self.assertEqual('keystone_authtoken', group) - - expected_opt_names = [ - 'auth_admin_prefix', - 'auth_host', - 'auth_port', - 'auth_protocol', - 'auth_uri', - 'identity_uri', - 'auth_version', - 'delay_auth_decision', - 'http_connect_timeout', - 'http_request_max_retries', - 'admin_token', - 'admin_user', - 'admin_password', - 'admin_tenant_name', - 'cache', - 'certfile', - 'keyfile', - 'cafile', - 'region_name', - 'insecure', - 'signing_dir', - 'memcached_servers', - 'token_cache_time', - 'revocation_cache_time', - 'memcache_security_strategy', - 'memcache_secret_key', - 'memcache_use_advanced_pool', - 'memcache_pool_dead_retry', - 'memcache_pool_maxsize', - 'memcache_pool_unused_timeout', - 'memcache_pool_conn_get_timeout', - 'memcache_pool_socket_timeout', - 'include_service_catalog', - 'enforce_token_bind', - 'check_revocations_for_cached', - 'hash_algorithms' - ] - opt_names = [o.name for (g, l) in result for o in l] - self.assertThat(opt_names, matchers.HasLength(len(expected_opt_names))) - - for opt in opt_names: - self.assertIn(opt, expected_opt_names) - - def test_list_auth_token_opts(self): - self._test_list_auth_token_opts(opts.list_auth_token_opts()) - - def test_entry_point(self): - em = stevedore.ExtensionManager('oslo.config.opts', - invoke_on_load=True) - for extension in em: - if extension.name == 'keystonemiddleware.auth_token': - break - else: - self.fail('keystonemiddleware.auth_token not found') - - self._test_list_auth_token_opts(extension.obj) diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/test_s3_token_middleware.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/test_s3_token_middleware.py deleted file mode 100644 index b0993886..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/test_s3_token_middleware.py +++ /dev/null @@ -1,268 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# 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 mock -from oslo_serialization import jsonutils -import requests -from requests_mock.contrib import fixture as rm_fixture -import six -from six.moves import urllib -import webob - -from keystonemiddleware import s3_token -from keystonemiddleware.tests.unit import utils - - -GOOD_RESPONSE = {'access': {'token': {'id': 'TOKEN_ID', - 'tenant': {'id': 'TENANT_ID'}}}} - - -class FakeApp(object): - """This represents a WSGI app protected by the auth_token middleware.""" - def __call__(self, env, start_response): - resp = webob.Response() - resp.environ = env - return resp(env, start_response) - - -class S3TokenMiddlewareTestBase(utils.TestCase): - - TEST_PROTOCOL = 'https' - TEST_HOST = 'fakehost' - TEST_PORT = 35357 - TEST_URL = '%s://%s:%d/v2.0/s3tokens' % (TEST_PROTOCOL, - TEST_HOST, - TEST_PORT) - - def setUp(self): - super(S3TokenMiddlewareTestBase, self).setUp() - - self.conf = { - 'auth_host': self.TEST_HOST, - 'auth_port': self.TEST_PORT, - 'auth_protocol': self.TEST_PROTOCOL, - } - - self.requests_mock = self.useFixture(rm_fixture.Fixture()) - - def start_fake_response(self, status, headers): - self.response_status = int(status.split(' ', 1)[0]) - self.response_headers = dict(headers) - - -class S3TokenMiddlewareTestGood(S3TokenMiddlewareTestBase): - - def setUp(self): - super(S3TokenMiddlewareTestGood, self).setUp() - self.middleware = s3_token.S3Token(FakeApp(), self.conf) - - self.requests_mock.post(self.TEST_URL, - status_code=201, - json=GOOD_RESPONSE) - - # Ignore the request and pass to the next middleware in the - # pipeline if no path has been specified. - def test_no_path_request(self): - req = webob.Request.blank('/') - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 200) - - # Ignore the request and pass to the next middleware in the - # pipeline if no Authorization header has been specified - def test_without_authorization(self): - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 200) - - def test_without_auth_storage_token(self): - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'badboy' - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 200) - - def test_authorized(self): - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'access:signature' - req.headers['X-Storage-Token'] = 'token' - req.get_response(self.middleware) - self.assertTrue(req.path.startswith('/v1/AUTH_TENANT_ID')) - self.assertEqual(req.headers['X-Auth-Token'], 'TOKEN_ID') - - def test_authorized_http(self): - self.requests_mock.post(self.TEST_URL.replace('https', 'http'), - status_code=201, - json=GOOD_RESPONSE) - - self.middleware = ( - s3_token.filter_factory({'auth_protocol': 'http', - 'auth_host': self.TEST_HOST, - 'auth_port': self.TEST_PORT})(FakeApp())) - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'access:signature' - req.headers['X-Storage-Token'] = 'token' - req.get_response(self.middleware) - self.assertTrue(req.path.startswith('/v1/AUTH_TENANT_ID')) - self.assertEqual(req.headers['X-Auth-Token'], 'TOKEN_ID') - - def test_authorization_nova_toconnect(self): - req = webob.Request.blank('/v1/AUTH_swiftint/c/o') - req.headers['Authorization'] = 'access:FORCED_TENANT_ID:signature' - req.headers['X-Storage-Token'] = 'token' - req.get_response(self.middleware) - path = req.environ['PATH_INFO'] - self.assertTrue(path.startswith('/v1/AUTH_FORCED_TENANT_ID')) - - @mock.patch.object(requests, 'post') - def test_insecure(self, MOCK_REQUEST): - self.middleware = ( - s3_token.filter_factory({'insecure': 'True'})(FakeApp())) - - text_return_value = jsonutils.dumps(GOOD_RESPONSE) - if six.PY3: - text_return_value = text_return_value.encode() - MOCK_REQUEST.return_value = utils.TestResponse({ - 'status_code': 201, - 'text': text_return_value}) - - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'access:signature' - req.headers['X-Storage-Token'] = 'token' - req.get_response(self.middleware) - - self.assertTrue(MOCK_REQUEST.called) - mock_args, mock_kwargs = MOCK_REQUEST.call_args - self.assertIs(mock_kwargs['verify'], False) - - def test_insecure_option(self): - # insecure is passed as a string. - - # Some non-secure values. - true_values = ['true', 'True', '1', 'yes'] - for val in true_values: - config = {'insecure': val, 'certfile': 'false_ind'} - middleware = s3_token.filter_factory(config)(FakeApp()) - self.assertIs(False, middleware._verify) - - # Some "secure" values, including unexpected value. - false_values = ['false', 'False', '0', 'no', 'someweirdvalue'] - for val in false_values: - config = {'insecure': val, 'certfile': 'false_ind'} - middleware = s3_token.filter_factory(config)(FakeApp()) - self.assertEqual('false_ind', middleware._verify) - - # Default is secure. - config = {'certfile': 'false_ind'} - middleware = s3_token.filter_factory(config)(FakeApp()) - self.assertIs('false_ind', middleware._verify) - - def test_unicode_path(self): - url = u'/v1/AUTH_cfa/c/euro\u20ac'.encode('utf8') - req = webob.Request.blank(urllib.parse.quote(url)) - req.headers['Authorization'] = 'access:signature' - req.headers['X-Storage-Token'] = 'token' - req.get_response(self.middleware) - - -class S3TokenMiddlewareTestBad(S3TokenMiddlewareTestBase): - def setUp(self): - super(S3TokenMiddlewareTestBad, self).setUp() - self.middleware = s3_token.S3Token(FakeApp(), self.conf) - - def test_unauthorized_token(self): - ret = {"error": - {"message": "EC2 access key not found.", - "code": 401, - "title": "Unauthorized"}} - self.requests_mock.post(self.TEST_URL, status_code=403, json=ret) - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'access:signature' - req.headers['X-Storage-Token'] = 'token' - resp = req.get_response(self.middleware) - s3_denied_req = self.middleware._deny_request('AccessDenied') - self.assertEqual(resp.body, s3_denied_req.body) - self.assertEqual(resp.status_int, s3_denied_req.status_int) - - def test_bogus_authorization(self): - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'badboy' - req.headers['X-Storage-Token'] = 'token' - resp = req.get_response(self.middleware) - self.assertEqual(resp.status_int, 400) - s3_invalid_req = self.middleware._deny_request('InvalidURI') - self.assertEqual(resp.body, s3_invalid_req.body) - self.assertEqual(resp.status_int, s3_invalid_req.status_int) - - def test_fail_to_connect_to_keystone(self): - with mock.patch.object(self.middleware, '_json_request') as o: - s3_invalid_req = self.middleware._deny_request('InvalidURI') - o.side_effect = s3_token.ServiceError(s3_invalid_req) - - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'access:signature' - req.headers['X-Storage-Token'] = 'token' - resp = req.get_response(self.middleware) - self.assertEqual(resp.body, s3_invalid_req.body) - self.assertEqual(resp.status_int, s3_invalid_req.status_int) - - def test_bad_reply(self): - self.requests_mock.post(self.TEST_URL, - status_code=201, - text="<badreply>") - - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'access:signature' - req.headers['X-Storage-Token'] = 'token' - resp = req.get_response(self.middleware) - s3_invalid_req = self.middleware._deny_request('InvalidURI') - self.assertEqual(resp.body, s3_invalid_req.body) - self.assertEqual(resp.status_int, s3_invalid_req.status_int) - - -class S3TokenMiddlewareTestUtil(utils.BaseTestCase): - def test_split_path_failed(self): - self.assertRaises(ValueError, s3_token._split_path, '') - self.assertRaises(ValueError, s3_token._split_path, '/') - self.assertRaises(ValueError, s3_token._split_path, '//') - self.assertRaises(ValueError, s3_token._split_path, '//a') - self.assertRaises(ValueError, s3_token._split_path, '/a/c') - self.assertRaises(ValueError, s3_token._split_path, '//c') - self.assertRaises(ValueError, s3_token._split_path, '/a/c/') - self.assertRaises(ValueError, s3_token._split_path, '/a//') - self.assertRaises(ValueError, s3_token._split_path, '/a', 2) - self.assertRaises(ValueError, s3_token._split_path, '/a', 2, 3) - self.assertRaises(ValueError, s3_token._split_path, '/a', 2, 3, True) - self.assertRaises(ValueError, s3_token._split_path, '/a/c/o/r', 3, 3) - self.assertRaises(ValueError, s3_token._split_path, '/a', 5, 4) - - def test_split_path_success(self): - self.assertEqual(s3_token._split_path('/a'), ['a']) - self.assertEqual(s3_token._split_path('/a/'), ['a']) - self.assertEqual(s3_token._split_path('/a/c', 2), ['a', 'c']) - self.assertEqual(s3_token._split_path('/a/c/o', 3), ['a', 'c', 'o']) - self.assertEqual(s3_token._split_path('/a/c/o/r', 3, 3, True), - ['a', 'c', 'o/r']) - self.assertEqual(s3_token._split_path('/a/c', 2, 3, True), - ['a', 'c', None]) - self.assertEqual(s3_token._split_path('/a/c/', 2), ['a', 'c']) - self.assertEqual(s3_token._split_path('/a/c/', 2, 3), ['a', 'c', '']) - - def test_split_path_invalid_path(self): - try: - s3_token._split_path('o\nn e', 2) - except ValueError as err: - self.assertEqual(str(err), 'Invalid path: o%0An%20e') - try: - s3_token._split_path('o\nn e', 2, 3, True) - except ValueError as err: - self.assertEqual(str(err), 'Invalid path: o%0An%20e') diff --git a/keystonemiddleware-moon/keystonemiddleware/tests/unit/utils.py b/keystonemiddleware-moon/keystonemiddleware/tests/unit/utils.py deleted file mode 100644 index 8c6c0e9a..00000000 --- a/keystonemiddleware-moon/keystonemiddleware/tests/unit/utils.py +++ /dev/null @@ -1,150 +0,0 @@ -# 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 logging -import sys -import time -import warnings - -import fixtures -import mock -import oslotest.base as oslotest -import requests -import uuid - - -class BaseTestCase(oslotest.BaseTestCase): - def setUp(self): - super(BaseTestCase, self).setUp() - - # If keystonemiddleware calls any deprecated function this will raise - # an exception. - warnings.filterwarnings('error', category=DeprecationWarning, - module='^keystonemiddleware\\.') - self.addCleanup(warnings.resetwarnings) - - -class TestCase(BaseTestCase): - TEST_DOMAIN_ID = '1' - TEST_DOMAIN_NAME = 'aDomain' - TEST_GROUP_ID = uuid.uuid4().hex - TEST_ROLE_ID = uuid.uuid4().hex - TEST_TENANT_ID = '1' - TEST_TENANT_NAME = 'aTenant' - TEST_TOKEN = 'aToken' - TEST_TRUST_ID = 'aTrust' - TEST_USER = 'test' - TEST_USER_ID = uuid.uuid4().hex - - TEST_ROOT_URL = 'http://127.0.0.1:5000/' - - def setUp(self): - super(TestCase, self).setUp() - self.logger = self.useFixture(fixtures.FakeLogger(level=logging.DEBUG)) - self.time_patcher = mock.patch.object(time, 'time', lambda: 1234) - self.time_patcher.start() - - def tearDown(self): - self.time_patcher.stop() - super(TestCase, self).tearDown() - - -if tuple(sys.version_info)[0:2] < (2, 7): - - def assertDictEqual(self, d1, d2, msg=None): - # Simple version taken from 2.7 - self.assertIsInstance(d1, dict, - 'First argument is not a dictionary') - self.assertIsInstance(d2, dict, - 'Second argument is not a dictionary') - if d1 != d2: - if msg: - self.fail(msg) - else: - standardMsg = '%r != %r' % (d1, d2) - self.fail(standardMsg) - - TestCase.assertDictEqual = assertDictEqual - - -class TestResponse(requests.Response): - """Class used to wrap requests.Response and provide some - convenience to initialize with a dict. - """ - - def __init__(self, data): - self._text = None - super(TestResponse, self).__init__() - if isinstance(data, dict): - self.status_code = data.get('status_code', 200) - headers = data.get('headers') - if headers: - self.headers.update(headers) - # Fake the text attribute to streamline Response creation - # _content is defined by requests.Response - self._content = data.get('text') - else: - self.status_code = data - - def __eq__(self, other): - return self.__dict__ == other.__dict__ - - @property - def text(self): - return self.content - - -class DisableModuleFixture(fixtures.Fixture): - """A fixture to provide support for unloading/disabling modules.""" - - def __init__(self, module, *args, **kw): - super(DisableModuleFixture, self).__init__(*args, **kw) - self.module = module - self._finders = [] - self._cleared_modules = {} - - def tearDown(self): - super(DisableModuleFixture, self).tearDown() - for finder in self._finders: - sys.meta_path.remove(finder) - sys.modules.update(self._cleared_modules) - - def clear_module(self): - cleared_modules = {} - for fullname in list(sys.modules.keys()): - if (fullname == self.module or - fullname.startswith(self.module + '.')): - cleared_modules[fullname] = sys.modules.pop(fullname) - return cleared_modules - - def setUp(self): - """Ensure ImportError for the specified module.""" - - super(DisableModuleFixture, self).setUp() - - # Clear 'module' references in sys.modules - self._cleared_modules.update(self.clear_module()) - - finder = NoModuleFinder(self.module) - self._finders.append(finder) - sys.meta_path.insert(0, finder) - - -class NoModuleFinder(object): - """Disallow further imports of 'module'.""" - - def __init__(self, module): - self.module = module - - def find_module(self, fullname, path): - if fullname == self.module or fullname.startswith(self.module + '.'): - raise ImportError diff --git a/keystonemiddleware-moon/openstack-common.conf b/keystonemiddleware-moon/openstack-common.conf deleted file mode 100644 index abdd7b30..00000000 --- a/keystonemiddleware-moon/openstack-common.conf +++ /dev/null @@ -1,7 +0,0 @@ -[DEFAULT] - -# The list of modules to copy from oslo-incubator -module=memorycache - -# The base module to hold the copy of openstack.common -base=keystonemiddleware diff --git a/keystonemiddleware-moon/requirements.txt b/keystonemiddleware-moon/requirements.txt deleted file mode 100644 index 4d39b223..00000000 --- a/keystonemiddleware-moon/requirements.txt +++ /dev/null @@ -1,16 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. - -Babel>=1.3 -oslo.config>=2.3.0 # Apache-2.0 -oslo.context>=0.2.0 # Apache-2.0 -oslo.i18n>=1.5.0 # Apache-2.0 -oslo.serialization>=1.4.0 # Apache-2.0 -oslo.utils!=2.6.0,>=2.0.0 # Apache-2.0 -pbr>=1.6 -pycadf>=1.1.0 -python-keystoneclient!=1.8.0,>=1.6.0 -requests!=2.8.0,!=2.9.0,>=2.5.2 -six>=1.9.0 -WebOb>=1.2.3 diff --git a/keystonemiddleware-moon/setup.cfg b/keystonemiddleware-moon/setup.cfg deleted file mode 100644 index 6893198b..00000000 --- a/keystonemiddleware-moon/setup.cfg +++ /dev/null @@ -1,57 +0,0 @@ -[metadata] -name = keystonemiddleware -summary = Middleware for OpenStack Identity -description-file = - README.rst -author = OpenStack -author-email = openstack-dev@lists.openstack.org -home-page = http://launchpad.net/keystonemiddleware -license = Apache-2.0 -classifier = - Environment :: OpenStack - Intended Audience :: Information Technology - Intended Audience :: System Administrators - License :: OSI Approved :: Apache Software License - Operating System :: POSIX :: Linux - Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.4 - -[files] -packages = - keystonemiddleware - -[global] -setup-hooks = - pbr.hooks.setup_hook - -[entry_points] -oslo.config.opts = - keystonemiddleware.auth_token = keystonemiddleware.opts:list_auth_token_opts - -[build_sphinx] -source-dir = doc/source -build-dir = doc/build -all_files = 1 - -[upload_sphinx] -upload-dir = doc/build/html - -[compile_catalog] -directory = keystonemiddleware/locale -domain = keystonemiddleware - -[update_catalog] -domain = keystonemiddleware -output_dir = keystonemiddleware/locale -input_file = keystonemiddleware/locale/keystonemiddleware.pot - -[extract_messages] -keywords = _ gettext ngettext l_ lazy_gettext -mapping_file = babel.cfg -output_file = keystonemiddleware/locale/keystonemiddleware.pot - -[wheel] -universal = 1 diff --git a/keystonemiddleware-moon/setup.py b/keystonemiddleware-moon/setup.py deleted file mode 100644 index 782bb21f..00000000 --- a/keystonemiddleware-moon/setup.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# 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. - -# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT -import setuptools - -# In python < 2.7.4, a lazy loading of package `pbr` will break -# setuptools if some other modules registered functions in `atexit`. -# solution from: http://bugs.python.org/issue15881#msg170215 -try: - import multiprocessing # noqa -except ImportError: - pass - -setuptools.setup( - setup_requires=['pbr>=1.8'], - pbr=True) diff --git a/keystonemiddleware-moon/test-requirements-py3.txt b/keystonemiddleware-moon/test-requirements-py3.txt deleted file mode 100644 index ff9e614c..00000000 --- a/keystonemiddleware-moon/test-requirements-py3.txt +++ /dev/null @@ -1,18 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. - -coverage>=3.6 -discover -fixtures>=0.3.14 -hacking>=0.8.0,<0.9 -mock>=1.0 -pycrypto>=2.6 -oslosphinx>=2.2.0 # Apache-2.0 -oslotest>=1.2.0 # Apache-2.0 -oslo.messaging>=1.6.0 # Apache-2.0 -requests-mock>=0.5.1 # Apache-2.0 -sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3 -testrepository>=0.0.18 -testresources>=0.2.4 -testtools>=0.9.36,!=1.2.0 diff --git a/keystonemiddleware-moon/test-requirements.txt b/keystonemiddleware-moon/test-requirements.txt deleted file mode 100644 index 261a8ffc..00000000 --- a/keystonemiddleware-moon/test-requirements.txt +++ /dev/null @@ -1,24 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. - -hacking<0.11,>=0.10.0 - -coverage>=3.6 -fixtures>=1.3.1 -mock>=1.2 -pycrypto>=2.6 -oslosphinx>=2.5.0 # Apache-2.0 -oslotest>=1.10.0 # Apache-2.0 -oslo.messaging!=1.17.0,!=1.17.1,!=2.6.0,!=2.6.1,!=2.7.0,!=2.8.0,!=2.8.1,!=2.9.0,!=3.1.0,>=1.16.0 # Apache-2.0 -requests-mock>=0.6.0 # Apache-2.0 -sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 -stevedore>=1.5.0 # Apache-2.0 -testrepository>=0.0.18 -testresources>=0.2.4 -testtools>=1.4.0 -python-memcached>=1.56 - -# Bandit security code scanner -bandit>=0.13.2 - diff --git a/keystonemiddleware-moon/tools/install_venv_common.py b/keystonemiddleware-moon/tools/install_venv_common.py deleted file mode 100644 index e279159a..00000000 --- a/keystonemiddleware-moon/tools/install_venv_common.py +++ /dev/null @@ -1,172 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# Copyright 2013 IBM Corp. -# -# 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. - -"""Provides methods needed by installation script for OpenStack development -virtual environments. - -Since this script is used to bootstrap a virtualenv from the system's Python -environment, it should be kept strictly compatible with Python 2.6. - -Synced in from openstack-common -""" - -from __future__ import print_function - -import optparse -import os -import subprocess -import sys - - -class InstallVenv(object): - - def __init__(self, root, venv, requirements, - test_requirements, py_version, - project): - self.root = root - self.venv = venv - self.requirements = requirements - self.test_requirements = test_requirements - self.py_version = py_version - self.project = project - - def die(self, message, *args): - print(message % args, file=sys.stderr) - sys.exit(1) - - def check_python_version(self): - if sys.version_info < (2, 6): - self.die("Need Python Version >= 2.6") - - def run_command_with_code(self, cmd, redirect_output=True, - check_exit_code=True): - """Runs a command in an out-of-process shell. - - Returns the output of that command. Working directory is self.root. - """ - if redirect_output: - stdout = subprocess.PIPE - else: - stdout = None - - proc = subprocess.Popen(cmd, cwd=self.root, stdout=stdout) - output = proc.communicate()[0] - if check_exit_code and proc.returncode != 0: - self.die('Command "%s" failed.\n%s', ' '.join(cmd), output) - return (output, proc.returncode) - - def run_command(self, cmd, redirect_output=True, check_exit_code=True): - return self.run_command_with_code(cmd, redirect_output, - check_exit_code)[0] - - def get_distro(self): - if (os.path.exists('/etc/fedora-release') or - os.path.exists('/etc/redhat-release')): - return Fedora( - self.root, self.venv, self.requirements, - self.test_requirements, self.py_version, self.project) - else: - return Distro( - self.root, self.venv, self.requirements, - self.test_requirements, self.py_version, self.project) - - def check_dependencies(self): - self.get_distro().install_virtualenv() - - def create_virtualenv(self, no_site_packages=True): - """Creates the virtual environment and installs PIP. - - Creates the virtual environment and installs PIP only into the - virtual environment. - """ - if not os.path.isdir(self.venv): - print('Creating venv...', end=' ') - if no_site_packages: - self.run_command(['virtualenv', '-q', '--no-site-packages', - self.venv]) - else: - self.run_command(['virtualenv', '-q', self.venv]) - print('done.') - else: - print("venv already exists...") - pass - - def pip_install(self, *args): - self.run_command(['tools/with_venv.sh', - 'pip', 'install', '--upgrade'] + list(args), - redirect_output=False) - - def install_dependencies(self): - print('Installing dependencies with pip (this can take a while)...') - - # First things first, make sure our venv has the latest pip and - # setuptools and pbr - self.pip_install('pip>=1.4') - self.pip_install('setuptools') - self.pip_install('pbr') - - self.pip_install('-r', self.requirements, '-r', self.test_requirements) - - def parse_args(self, argv): - """Parses command-line arguments.""" - parser = optparse.OptionParser() - parser.add_option('-n', '--no-site-packages', - action='store_true', - help="Do not inherit packages from global Python " - "install.") - return parser.parse_args(argv[1:])[0] - - -class Distro(InstallVenv): - - def check_cmd(self, cmd): - return bool(self.run_command(['which', cmd], - check_exit_code=False).strip()) - - def install_virtualenv(self): - if self.check_cmd('virtualenv'): - return - - if self.check_cmd('easy_install'): - print('Installing virtualenv via easy_install...', end=' ') - if self.run_command(['easy_install', 'virtualenv']): - print('Succeeded') - return - else: - print('Failed') - - self.die('ERROR: virtualenv not found.\n\n%s development' - ' requires virtualenv, please install it using your' - ' favorite package management tool' % self.project) - - -class Fedora(Distro): - """This covers all Fedora-based distributions. - - Includes: Fedora, RHEL, CentOS, Scientific Linux - """ - - def check_pkg(self, pkg): - return self.run_command_with_code(['rpm', '-q', pkg], - check_exit_code=False)[1] == 0 - - def install_virtualenv(self): - if self.check_cmd('virtualenv'): - return - - if not self.check_pkg('python-virtualenv'): - self.die("Please install 'python-virtualenv'.") - - super(Fedora, self).install_virtualenv() diff --git a/keystonemiddleware-moon/tox.ini b/keystonemiddleware-moon/tox.ini deleted file mode 100644 index 790bf027..00000000 --- a/keystonemiddleware-moon/tox.ini +++ /dev/null @@ -1,50 +0,0 @@ -[tox] -minversion = 1.6 -skipsdist = True -envlist = py26,py27,py34,pep8 - -[testenv] -usedevelop = True -install_command = pip install -U {opts} {packages} -setenv = VIRTUAL_ENV={envdir} - OS_STDOUT_NOCAPTURE=False - OS_STDERR_NOCAPTURE=False - -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt -commands = python setup.py testr --testr-args='{posargs}' - -[testenv:pep8] -commands = - flake8 - -[testenv:venv] -commands = {posargs} - -[testenv:cover] -commands = python setup.py testr --coverage --testr-args='{posargs}' - -[tox:jenkins] -downloadcache = ~/cache/pip - -[testenv:debug] - -commands = oslo_debug_helper {posargs} - -[testenv:bandit] -deps = -r{toxinidir}/test-requirements.txt -commands = bandit -c bandit.yaml -r keystonemiddleware -n5 -p keystone_conservative - -[flake8] -# H405: multi line docstring summary not separated with an empty line -ignore = H405 -show-source = True -exclude = .venv,.tox,dist,doc,*egg,build,*openstack/common* - -[testenv:docs] -commands= - python setup.py build_sphinx - -[hacking] -import_exceptions = - keystonemiddleware.i18n |