initial commit

Change-Id: Ie417df96258c2daa852d14e588de4ad2d54bb819
This commit is contained in:
hosingh000 2017-06-03 17:28:58 -05:00
parent 6253f36d96
commit 3de38762aa
871 changed files with 105408 additions and 0 deletions

58
.gitignore vendored Normal file
View File

@ -0,0 +1,58 @@
*.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
cover/
.coverage*
!.coveragerc
.tox
nosetests.xml
.testrepository
.venv
# 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
.*sw?
# Files created by releasenotes build
releasenotes/build

1
MANIFEST.in Normal file
View File

@ -0,0 +1 @@
recursive-include public *

13
README.rst Normal file
View File

@ -0,0 +1,13 @@
===============================
orm
===============================
Openstack Resource Management
* TODO
Features
--------
* TODO

2
babel.cfg Normal file
View File

@ -0,0 +1,2 @@
[python: **.py]

54
config.py Normal file
View File

@ -0,0 +1,54 @@
# Server Specific Configurations
server = {
'port': '9866',
'host': '0.0.0.0'
}
# Pecan Application Configurations
app = {
'root': 'orm.controllers.root.RootController',
'modules': ['orm'],
'static_root': '%(confdir)s/public',
'template_path': '%(confdir)s/orm/templates',
'debug': True,
'errors': {
404: '/error/404',
'__force_dict__': True
}
}
logging = {
'root': {'level': 'INFO', 'handlers': ['console']},
'loggers': {
'orm': {'level': 'DEBUG', 'handlers': ['console']},
'pecan': {'level': 'DEBUG', 'handlers': ['console']},
'py.warnings': {'handlers': ['console']},
'__force_dict__': True
},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'color'
}
},
'formatters': {
'simple': {
'format': ('%(asctime)s %(levelname)-5.5s [%(name)s]'
'[%(threadName)s] %(message)s')
},
'color': {
'()': 'pecan.log.ColorFormatter',
'format': ('%(asctime)s [%(padded_color_levelname)s] [%(name)s]'
'[%(threadName)s] %(message)s'),
'__force_dict__': True
}
}
}
# Custom Configurations must be in Python dictionary format::
#
# foo = {'bar':'baz'}
#
# All configurations are accessible at::
# pecan.conf

View File

@ -0,0 +1,5 @@
====================
Administrators guide
====================
Administrators guide of ranger.

5
doc/source/cli/index.rst Normal file
View File

@ -0,0 +1,5 @@
================================
Command line interface reference
================================
CLI reference of ranger.

81
doc/source/conf.py Executable file
View File

@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
# 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 sys
sys.path.insert(0, 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',
'openstackdocstheme',
#'sphinx.ext.intersphinx',
]
# autodoc generation is a bit aggressive and a nuisance when doing heavy
# text edit cycles.
# execute "export SPHINX_DEBUG=1" in your terminal to disable
# The suffix of source filenames.
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'ranger'
copyright = u'2017, OpenStack Developers'
# openstackdocstheme options
repository_name = 'openstack/ranger'
bug_project = 'ranger'
bug_tag = ''
# 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
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# -- 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'
# html_static_path = ['static']
html_theme = 'openstackdocs'
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
('index',
'%s.tex' % project,
u'%s Documentation' % project,
u'OpenStack Developers', 'manual'),
]
# Example configuration for intersphinx: refer to the Python standard library.
#intersphinx_mapping = {'http://docs.python.org/': None}

View File

@ -0,0 +1,5 @@
=============
Configuration
=============
Configuration of ranger.

View File

@ -0,0 +1,4 @@
============
Contributing
============
.. include:: ../../../CONTRIBUTING.rst

View File

@ -0,0 +1,9 @@
===========================
Contributor Documentation
===========================
.. toctree::
:maxdepth: 2
contributing

30
doc/source/index.rst Normal file
View File

@ -0,0 +1,30 @@
.. ranger documentation master file, created by
sphinx-quickstart on Tue Jul 9 22:26:36 2013.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
======================================
Welcome to the documentation of ranger
======================================
Contents:
.. toctree::
:maxdepth: 2
readme
install/index
library/index
contributor/index
configuration/index
cli/index
user/index
admin/index
reference/index
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -0,0 +1,10 @@
2. Edit the ``/etc/ranger/ranger.conf`` file and complete the following
actions:
* In the ``[database]`` section, configure database access:
.. code-block:: ini
[database]
...
connection = mysql+pymysql://ranger:RANGER_DBPASS@controller/ranger

View File

@ -0,0 +1,75 @@
Prerequisites
-------------
Before you install and configure the ranger service,
you must create a database, service credentials, and API endpoints.
#. To create the database, complete these steps:
* Use the database access client to connect to the database
server as the ``root`` user:
.. code-block:: console
$ mysql -u root -p
* Create the ``ranger`` database:
.. code-block:: none
CREATE DATABASE ranger;
* Grant proper access to the ``ranger`` database:
.. code-block:: none
GRANT ALL PRIVILEGES ON ranger.* TO 'ranger'@'localhost' \
IDENTIFIED BY 'RANGER_DBPASS';
GRANT ALL PRIVILEGES ON ranger.* TO 'ranger'@'%' \
IDENTIFIED BY 'RANGER_DBPASS';
Replace ``RANGER_DBPASS`` with a suitable password.
* Exit the database access client.
.. code-block:: none
exit;
#. Source the ``admin`` credentials to gain access to
admin-only CLI commands:
.. code-block:: console
$ . admin-openrc
#. To create the service credentials, complete these steps:
* Create the ``ranger`` user:
.. code-block:: console
$ openstack user create --domain default --password-prompt ranger
* Add the ``admin`` role to the ``ranger`` user:
.. code-block:: console
$ openstack role add --project service --user ranger admin
* Create the ranger service entities:
.. code-block:: console
$ openstack service create --name ranger --description "ranger" ranger
#. Create the ranger service API endpoints:
.. code-block:: console
$ openstack endpoint create --region RegionOne \
ranger public http://controller:XXXX/vY/%\(tenant_id\)s
$ openstack endpoint create --region RegionOne \
ranger internal http://controller:XXXX/vY/%\(tenant_id\)s
$ openstack endpoint create --region RegionOne \
ranger admin http://controller:XXXX/vY/%\(tenant_id\)s

View File

@ -0,0 +1,9 @@
=======================
ranger service overview
=======================
The ranger service provides...
The ranger service consists of the following components:
``ranger-api`` service
Accepts and responds to end user compute API calls...

View File

@ -0,0 +1,17 @@
=================================
ranger service installation guide
=================================
.. toctree::
:maxdepth: 2
get_started.rst
install.rst
verify.rst
next-steps.rst
The ranger service (ranger) provides...
This chapter assumes a working setup of OpenStack following the
`OpenStack Installation Tutorial
<https://docs.openstack.org/project-install-guide/ocata/>`_.

View File

@ -0,0 +1,34 @@
.. _install-obs:
Install and configure for openSUSE and SUSE Linux Enterprise
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This section describes how to install and configure the ranger service
for openSUSE Leap 42.1 and SUSE Linux Enterprise Server 12 SP1.
.. include:: common_prerequisites.rst
Install and configure components
--------------------------------
#. Install the packages:
.. code-block:: console
# zypper --quiet --non-interactive install
.. include:: common_configure.rst
Finalize installation
---------------------
Start the ranger services and configure them to start when
the system boots:
.. code-block:: console
# systemctl enable openstack-ranger-api.service
# systemctl start openstack-ranger-api.service

View File

@ -0,0 +1,33 @@
.. _install-rdo:
Install and configure for Red Hat Enterprise Linux and CentOS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This section describes how to install and configure the ranger service
for Red Hat Enterprise Linux 7 and CentOS 7.
.. include:: common_prerequisites.rst
Install and configure components
--------------------------------
#. Install the packages:
.. code-block:: console
# yum install
.. include:: common_configure.rst
Finalize installation
---------------------
Start the ranger services and configure them to start when
the system boots:
.. code-block:: console
# systemctl enable openstack-ranger-api.service
# systemctl start openstack-ranger-api.service

View File

@ -0,0 +1,31 @@
.. _install-ubuntu:
Install and configure for Ubuntu
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This section describes how to install and configure the ranger
service for Ubuntu 14.04 (LTS).
.. include:: common_prerequisites.rst
Install and configure components
--------------------------------
#. Install the packages:
.. code-block:: console
# apt-get update
# apt-get install
.. include:: common_configure.rst
Finalize installation
---------------------
Restart the ranger services:
.. code-block:: console
# service openstack-ranger-api restart

View File

@ -0,0 +1,20 @@
.. _install:
Install and configure
~~~~~~~~~~~~~~~~~~~~~
This section describes how to install and configure the
ranger service, code-named ranger, on the controller node.
This section assumes that you already have a working OpenStack
environment with at least the following components installed:
.. (add the appropriate services here and further notes)
Note that installation and configuration vary by distribution.
.. toctree::
:maxdepth: 2
install-obs.rst
install-rdo.rst
install-ubuntu.rst

View File

@ -0,0 +1,9 @@
.. _next-steps:
Next steps
~~~~~~~~~~
Your OpenStack environment now includes the ranger service.
To add additional services, see
https://docs.openstack.org/project-install-guide/ocata/.

View File

@ -0,0 +1,24 @@
.. _verify:
Verify operation
~~~~~~~~~~~~~~~~
Verify operation of the ranger service.
.. note::
Perform these commands on the controller node.
#. Source the ``admin`` project credentials to gain access to
admin-only CLI commands:
.. code-block:: console
$ . admin-openrc
#. List service components to verify successful launch and registration
of each process:
.. code-block:: console
$ openstack ranger service list

View File

@ -0,0 +1,7 @@
========
Usage
========
To use ranger in a project::
import ranger

1
doc/source/readme.rst Normal file
View File

@ -0,0 +1 @@
.. include:: ../../README.rst

View File

@ -0,0 +1,5 @@
==========
References
==========
References of ranger.

View File

@ -0,0 +1,5 @@
===========
Users guide
===========
Users guide of ranger.

0
etc/orm.conf Normal file
View File

0
orm/__init__.py Normal file
View File

14
orm/app.py Normal file
View File

@ -0,0 +1,14 @@
from pecan import make_app
from orm import model
def setup_app(config):
model.init_model()
app_conf = dict(config.app)
return make_app(
app_conf.pop('root'),
logging=getattr(config, 'logging', {}),
**app_conf
)

0
orm/cmd/__init__.py Normal file
View File

19
orm/cmd/audit.py Normal file
View File

@ -0,0 +1,19 @@
# Copyright 2016 ATT
#
# 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 orm.services.audit_trail_manager.audit_server import app
def main():
app.main()

19
orm/cmd/cms.py Normal file
View File

@ -0,0 +1,19 @@
# Copyright 2016 ATT
#
# 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 orm.services.customer_manager.cms_rest import app
def main():
app.main()

19
orm/cmd/fms.py Normal file
View File

@ -0,0 +1,19 @@
# Copyright 2016 ATT
#
# 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 orm.services.flavor_manager.fms_rest import app
def main():
app.main()

19
orm/cmd/ims.py Normal file
View File

@ -0,0 +1,19 @@
# Copyright 2016 ATT
#
# 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 orm.services.image_manager.ims import app
def main():
app.main()

19
orm/cmd/keystone.py Normal file
View File

@ -0,0 +1,19 @@
# Copyright 2016 ATT
#
# 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 orm.services.resource_distributor.rds import app
def main():
app.main()

19
orm/cmd/rds.py Normal file
View File

@ -0,0 +1,19 @@
# Copyright 2016 ATT
#
# 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 orm.services.resource_distributor.rds import app
def main():
app.main()

19
orm/cmd/rms.py Normal file
View File

@ -0,0 +1,19 @@
# Copyright 2016 ATT
#
# 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 orm.services.region_manager.rms import app
def main():
app.main()

19
orm/cmd/uuidgen.py Normal file
View File

@ -0,0 +1,19 @@
# Copyright 2016 ATT
#
# 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 orm.services.id_generator.uuidgen import app
def main():
app.main()

0
orm/common/__init__.py Normal file
View File

View File

View File

View File

@ -0,0 +1,17 @@
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
If you already have a good understanding of how the system works and your
OpenStack accounts are set up, you can skip to the development workflow
section of this documentation to learn how changes to OpenStack should be
submitted for review via the Gerrit tool:
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/keystone_utils

View File

@ -0,0 +1,4 @@
keystone_utils Style Commandments
===============================================
Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/

View File

@ -0,0 +1,176 @@
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.

View File

@ -0,0 +1,6 @@
include AUTHORS
include ChangeLog
exclude .gitignore
exclude .gitreview
global-exclude *.pyc

View File

@ -0,0 +1,19 @@
===============================
keystone_utils
===============================
keyKeystone utils
Please feel here a long description which must be at least 3 lines wrapped on
80 cols, so that distribution package maintainers can use it in their packages.
Note that this is a hard requirement.
* Free software: Apache license
* Documentation: http://docs.openstack.org/developer/keystone_utils
* Source: http://git.openstack.org/cgit/keystone_utils/keystone_utils
* Bugs: http://bugs.launchpad.net/keystone_utils
Features
--------
* TODO

View File

View File

@ -0,0 +1,2 @@
[python: **.py]

View File

@ -0,0 +1 @@
aic-orm-keystone/* opt/app/orm/keystone_utils

View File

@ -0,0 +1,5 @@
aic-orm-keystone (3.5.0) stable; urgency=low
* this is release 3.5.0
-- Jenkins job <jenkins@unknown> Thu, 24 Jun 2016 14:48:02 +0000

View File

@ -0,0 +1 @@
9

View File

@ -0,0 +1,13 @@
Source: aic-orm-keystone
Section: unknown
Priority: optional
Maintainer: orm <orm@intl.att.com>
Build-Depends: debhelper (>= 8.0.0)
Standards-Version: 3.9.4
XS-Python-Version: >= 2.7
Homepage: <insert the upstream URL, if relevant>
Package: aic-orm-keystone
Architecture: any
Depends: python-keystoneclient (>= 1.2.0), python-requests (>= 2.2.0)
Description: aic-orm-keystone application for ORM

View File

@ -0,0 +1,34 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: aic-orm-keystone
Source: <url://example.com>
Files: *
Copyright: <years> <put author's name and email here>
<years> <likewise for another author>
License: GPL-3.0+
Files: debian/*
Copyright: 2016 root <root@unknown>
License: GPL-3.0+
License: GPL-3.0+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
.
On Debian systems, the complete text of the GNU General
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
# Please also look if there are files or directories which have a
# different copyright/license attached and list them here.
# Please avoid to pick license terms that are more restrictive than the
# packaged work, as it may make Debian's contributions unacceptable upstream.

View File

View File

@ -0,0 +1,4 @@
#!/bin/bash
#rm -rf /opt/app/orm/keystone_utils
#echo "Deleting /opt/app/orm/keystone_utils directory."

View File

@ -0,0 +1,8 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
%:
dh $@ --buildsystem=python_distutils -D aic-orm-keystone

View File

@ -0,0 +1 @@
3.0 (native)

View File

@ -0,0 +1,4 @@
============
Contributing
============
.. include:: ../../CONTRIBUTING.rst

View File

@ -0,0 +1,25 @@
.. keystone_utils documentation master file, created by
sphinx-quickstart on Tue Jul 9 22:26:36 2013.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to keystone_utils's documentation!
========================================================
Contents:
.. toctree::
:maxdepth: 2
readme
installation
usage
contributing
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -0,0 +1,12 @@
============
Installation
============
At the command line::
$ pip install keystone_utils
Or, if you have virtualenvwrapper installed::
$ mkvirtualenv keystone_utils
$ pip install keystone_utils

View File

@ -0,0 +1 @@
.. include:: ../../README.rst

View File

@ -0,0 +1,7 @@
========
Usage
========
To use keystone_utils in a project::
import keystone_utils

View File

@ -0,0 +1,21 @@
Metadata-Version: 1.1
Name: keystone-utils
Version: 0.1
Summary: keyKeystone utils
Home-page: http://www.openstack.org/
Author: OpenStack
Author-email: openstack-dev@lists.openstack.org
License: UNKNOWN
Description: UNKNOWN
Platform: UNKNOWN
Classifier: Environment :: OpenStack
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4

View File

@ -0,0 +1,25 @@
MANIFEST.in
README.rst
setup.cfg
setup.py
keystone_utils/__init__.py
keystone_utils/tokens.py
keystone_utils.egg-info/PKG-INFO
keystone_utils.egg-info/SOURCES.txt
keystone_utils.egg-info/dependency_links.txt
keystone_utils.egg-info/not-zip-safe
keystone_utils.egg-info/pbr.json
keystone_utils.egg-info/top_level.txt
keystone_utils/tests/__init__.py
keystone_utils/tests/unit/__init__.py
keystone_utils/tests/unit/test_tokens.py
mock_keystone/__init__.py
mock_keystone/keystoneclient/__init__.py
mock_keystone/keystoneclient/exceptions.py
mock_keystone/keystoneclient/v2_0/__init__.py
mock_keystone/keystoneclient/v2_0/client.py
mock_keystone/keystoneclient/v3/__init__.py
mock_keystone/keystoneclient/v3/client.py
mock_keystone/orm_common/__init__.py
mock_keystone/orm_common/utils/__init__.py
mock_keystone/orm_common/utils/dictator.py

View File

@ -0,0 +1 @@
{"is_release": false, "git_version": ""}

View File

@ -0,0 +1,2 @@
keystone_utils
mock_keystone

View File

@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
# 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.

View File

@ -0,0 +1,219 @@
"""keystone_utils token validator unittests."""
import mock
import unittest
from keystone_utils import tokens
class MyResponse(object):
def __init__(self, status, json_result):
self.status_code = status
self._json_result = json_result
def json(self):
return self._json_result
class MyKeystone(object):
def validate(self, a):
raise tokens.v3_client.exceptions.NotFound('test')
def find(self, **kwargs):
raise tokens.v3_client.exceptions.NotFound('test')
class MyClient(object):
def __init__(self, set_tokens=True):
if set_tokens:
self.tokens = MyKeystone()
else:
self.tokens = mock.MagicMock()
self.roles = MyKeystone()
class TokensTest(unittest.TestCase):
def setUp(self):
tokens._KEYSTONES = {}
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
def test_find_keystone_ep_sanity(self, mock_get):
result = tokens._find_keystone_ep('a', 'b')
self.assertEqual(result, 'test')
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE + 1, {'regions': [{'endpoints': [
{'publicURL': 'test', 'type': 'identity'}]}]}))
def test_find_keystone_ep_bad_return_code(self, mock_get):
result = tokens._find_keystone_ep('a', 'b')
self.assertIsNone(result)
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {}))
def test_find_keystone_ep_no_keystone_ep_in_response(self, mock_get):
result = tokens._find_keystone_ep('a', 'b')
self.assertIsNone(result)
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'test'}]}]}))
def test_find_keystone_ep_no_identity_in_response(self, mock_get):
result = tokens._find_keystone_ep('a', 'b')
self.assertIsNone(result)
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
@mock.patch.object(tokens.v3_client, 'Client')
def test_is_token_valid_sanity(self, mock_get, mock_client):
self.assertTrue(tokens.is_token_valid('a', 'b', tokens.TokenConf(
'a', 'b', 'c', 'd', '3')))
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
@mock.patch.object(tokens.v3_client, 'Client')
def test_is_token_valid_sanity_role_required(self, mock_get, mock_client):
user = {'user': {'id': 'test_id', 'domain': {'id': 'test'}}}
mock_client.tokens.validate = mock.MagicMock(return_value=user)
self.assertTrue(tokens.is_token_valid('a', 'b', tokens.TokenConf(
'a', 'b', 'c', 'd', '3'), 'test', {'domain': 'test'}))
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
def test_is_token_valid_token_not_found(self, mock_get):
client_backup = tokens.v3_client.Client
tokens.v3_client.Client = mock.MagicMock(return_value=MyClient())
self.assertFalse(tokens.is_token_valid('a', 'b', tokens.TokenConf(
'a', 'b', 'c', 'd', '3')))
tokens.v3_client.Client = client_backup
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
def test_is_token_valid_invalid_version(self, mock_get):
client_backup = tokens.v3_client.Client
tokens.v3_client.Client = mock.MagicMock(return_value=MyClient())
self.assertRaises(ValueError, tokens.is_token_valid, 'a', 'b',
tokens.TokenConf('a', 'b', 'c', 'd', '4'))
tokens.v3_client.Client = client_backup
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
def test_is_token_valid_keystone_v2(self, mock_get):
client_backup = tokens.v2_client.Client
tokens.v2_client.Client = mock.MagicMock()
self.assertFalse(tokens.is_token_valid('a', 'b',
tokens.TokenConf('a', 'b', 'c',
'd', '2.0'),
'test',
{'tenant': 'test'}))
tokens.v2_client.Client = client_backup
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
def test_is_token_valid_keystone_v2_invalid_location(self, mock_get):
client_backup = tokens.v2_client.Client
tokens.v2_client.Client = mock.MagicMock()
self.assertRaises(ValueError, tokens.is_token_valid, 'a', 'b',
tokens.TokenConf('a', 'b', 'c', 'd', '2.0'), 'test',
{'domain': 'test'})
tokens.v2_client.Client = client_backup
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE + 1, {'regions': [{'endpoints': [
{'publicURL': 'test', 'type': 'identity'}]}]}))
def test_is_token_valid_keystone_ep_not_found(self, mock_get):
self.assertRaises(tokens.KeystoneNotFoundError, tokens.is_token_valid,
'a', 'b', tokens.TokenConf('a', 'b', 'c', 'd', '3'))
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
def test_is_token_valid_no_role_location(self, mock_get):
tokens.v3_client.Client = mock.MagicMock()
self.assertRaises(ValueError, tokens.is_token_valid, 'a', 'b',
tokens.TokenConf('a', 'b', 'c', 'd', '3'), 'test')
@mock.patch.object(tokens.v3_client, 'Client')
def test_does_user_have_role_sanity_true(self, mock_client):
user = {'user': {'id': 'test_id', 'domain': {'id': 'test'}}}
self.assertTrue(tokens._does_user_have_role(mock_client, '3', user,
'admin',
{'domain': 'test'}))
@mock.patch.object(tokens.v3_client, 'Client')
def test_does_user_have_role_sanity_false(self, mock_client):
user = {'user': {'id': 'test_id', 'domain': {'id': 'test'}}}
mock_client.roles.check = mock.MagicMock(
side_effect=tokens.v3_client.exceptions.NotFound('test'))
self.assertFalse(tokens._does_user_have_role(mock_client, '3', user,
'admin',
{'domain': 'test'}))
@mock.patch.object(tokens.v3_client, 'Client')
def test_does_user_have_role_invalid_user(self, mock_client):
user = {}
self.assertFalse(tokens._does_user_have_role(mock_client, '3', user,
'admin',
{'domain': 'test'}))
@mock.patch.object(tokens.v3_client, 'Client')
def test_does_user_have_role_role_does_not_exist(self, mock_client):
user = {'user': {'id': 'test_id', 'domain': {'id': 'test'}}}
mock_client.roles.find = mock.MagicMock(
side_effect=tokens.v3_client.exceptions.NotFound('test'))
self.assertRaises(tokens.v3_client.exceptions.NotFound,
tokens._does_user_have_role, mock_client, '3',
user, 'test', {'domain': 'default'})
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
def test_is_token_valid_role_does_not_exist(self, mock_get):
tokens.v3_client.Client = mock.MagicMock(return_value=MyClient(False))
self.assertRaises(ValueError, tokens.is_token_valid, 'a', 'b',
tokens.TokenConf('a', 'b', 'c', 'd', '3'), 'test',
{'domain': 'test'})
def test_get_token_user_invalid_arguments(self):
self.assertRaises(ValueError, tokens.get_token_user, 'a', 'b')
@mock.patch.object(tokens, '_find_keystone_ep', return_value=None)
def test_get_token_user_keystone_ep_not_found(self,
mock_find_keystone_ep):
self.assertRaises(tokens.KeystoneNotFoundError,
tokens.get_token_user, 'a', mock.MagicMock(), 'c')
def test_get_token_user_invalid_keystone_version(self):
conf = tokens.TokenConf(*(None,)*5)
self.assertRaises(ValueError, tokens.get_token_user, 'a', conf, 'c',
'd')
@mock.patch.object(tokens, '_get_keystone_client')
def test_get_token_user_token_not_found(self, mock_get_keystone_client):
ks = mock.MagicMock()
ks.tokens.validate.side_effect = tokens.v3_client.exceptions.NotFound()
mock_get_keystone_client.return_value = ks
conf = tokens.TokenConf(*('3',)*5)
self.assertIsNone(tokens.get_token_user('a', conf, 'c', 'd'))
@mock.patch.object(tokens, '_get_keystone_client')
def test_get_token_user_success(self, mock_get_keystone_client):
token_info = mock.MagicMock()
token_info.token = 'a'
token_info.user = 'test_user'
ks = mock.MagicMock()
ks.tokens.validate.return_value = token_info
mock_get_keystone_client.return_value = ks
conf = tokens.TokenConf(*('2.0',)*5)
result = tokens.get_token_user('a', conf, 'c', 'd')
self.assertEqual(result.token, 'a')
self.assertEqual(result.user, 'test_user')

View File

@ -0,0 +1,278 @@
"""Token utility module."""
import logging
import requests
from keystoneclient.v2_0 import client as v2_client
from keystoneclient.v3 import client as v3_client
from orm_common.utils import dictator
_verify = False
OK_CODE = 200
_KEYSTONES = {}
logger = logging.getLogger(__name__)
class KeystoneNotFoundError(Exception):
"""Indicates that the Keystone EP of a certain LCP was not found."""
pass
class TokenConf(object):
"""The Token Validator configuration class."""
def __init__(self, mech_id, password, rms_url, tenant_name, version):
"""Initialize the Token Validator configuration.
:param mech_id: Username for Keystone
:param password: Password for Keystone
:param rms_url: The entire RMS URL, e.g. 'http://1.3.3.7:8080'
:param tenant_name: The ORM tenant name
:param version: Keystone version to use (a string: '3' or '2.0')
"""
self.mech_id = mech_id
self.password = password
self.rms_url = rms_url
self.tenant_name = tenant_name
self.version = version
class TokenUser(object):
"""Class with details about the token user."""
def __init__(self, token):
"""Initialize the Token User.
:param token: The token object (returned by tokens.validate)
"""
self.token = token.token
self.user = token.user
self.tenant = getattr(token, 'tenant', None)
self.domain = getattr(token, 'domain', None)
def get_token_user(token, conf, lcp_id=None, keystone_ep=None):
"""Get a token user.
:param token: The token to validate
:param conf: A TokenConf object
:param lcp_id: The ID of the LCP associated with the Keystone instance
with which the token was created. Ignored if keystone_ep is not None
:param keystone_ep: The Keystone endpoint, in case we already have it
:return: False if one of the tokens received (or more) is invalid,
True otherwise.
"""
# Not using logger.error/exception because in some cases, these flows
# can be completely valid
if keystone_ep is None:
if lcp_id is None:
message = 'Received None for both keystone_ep and lcp_id!'
logger.debug(message)
raise ValueError(message)
keystone_ep = _find_keystone_ep(conf.rms_url, lcp_id)
if keystone_ep is None:
message = 'Keystone EP of LCP %s not found in RMS' % (lcp_id,)
logger.debug(message)
logger.critical(
'CRITICAL|CON{}KEYSTONE002|X-Auth-Region: {} is not '
'reachable (not found in RMS)'.format(
dictator.get('service_name', 'ORM'), lcp_id))
raise KeystoneNotFoundError(message)
if conf.version == '3':
client = v3_client
elif conf.version == '2.0':
client = v2_client
else:
message = 'Invalid Keystone version: %s' % (conf.version,)
logger.debug(message)
raise ValueError(message)
keystone = _get_keystone_client(client, conf, keystone_ep, lcp_id)
try:
token_info = keystone.tokens.validate(token)
logger.debug('User token found in Keystone')
return TokenUser(token_info)
# Other exceptions raised by validate() are critical errors,
# so instead of returning False, we'll just let them propagate
except client.exceptions.NotFound:
logger.debug('User token not found in Keystone! Make sure that it is '
'correct and that it has not expired yet')
return None
def _find_keystone_ep(rms_url, lcp_name):
"""Get the Keystone EP from RMS.
:param rms_url: RMS server URL
:param lcp_name: The LCP name
:return: Keystone EP (string), None if it was not found
"""
if not rms_url:
message = 'Invalid RMS URL: %s' % (rms_url,)
logger.debug(message)
raise ValueError(message)
logger.debug(
'Looking for Keystone EP of LCP {} using RMS URL {}'.format(
lcp_name, rms_url))
response = requests.get('%s/v2/orm/regions?regionname=%s' % (
rms_url, lcp_name, ), verify=_verify)
if response.status_code != OK_CODE:
# The LCP was not found in RMS
logger.debug('Received bad response code from RMS: {}'.format(
response.status_code))
return None
lcp = response.json()
try:
for endpoint in lcp['regions'][0]['endpoints']:
if endpoint['type'] == 'identity':
return endpoint['publicURL']
except KeyError:
logger.debug('Response from RMS came in an unsupported format. '
'Make sure that you are using RMS 3.5')
return None
# Keystone EP not found in the response
logger.debug('No identity endpoint was found in the response from RMS')
return None
def _does_user_have_role(keystone, version, user, role, location):
"""Check whether a user has a role.
:param keystone: The Keystone client to use
:param version: Keystone version
:param user: A dict that represents the user in question
:param role: The role to check whether the user has
:param location: Keystone role location
:return: True if the user has the requested role, False otherwise.
:raise: client.exceptions.NotFound when the requested role does not exist,
ValueError when the version is 2.0 but the location is not 'tenant'
"""
location = dict(location)
if version == '3':
role = keystone.roles.find(name=role)
try:
return keystone.roles.check(role, user=user['user']['id'],
**location)
except v3_client.exceptions.NotFound:
return False
except KeyError:
# Shouldn't be raised when using Keystone's v3/v2.0 API, but let's
# play on the safe side
logger.debug('The user parameter came in a wrong format!')
return False
elif version == '2.0':
# v2.0 supports tenants only
if location.keys()[0] != 'tenant':
raise ValueError(
'Using Keystone v2.0, expected "tenant", received: "%s"' % (
location.keys()[0],))
tenant = keystone.tenants.find(name=location['tenant'])
# v2.0 does not enable us to check for a specific role (unlike v3)
role_list = keystone.roles.roles_for_user(user.user['id'],
tenant=tenant)
return any([user_role.name == role for user_role in role_list])
def _get_keystone_client(client, conf, keystone_ep, lcp_id):
"""Get the Keystone client.
:param client: keystoneclient package to use
:param conf: Token conf
:param keystone_ep: The Keystone endpoint that RMS returned
:param lcp_id: The region ID
:return: The instance of Keystone client to use
"""
global _KEYSTONES
try:
if keystone_ep not in _KEYSTONES:
# Instantiate the Keystone client according to the configuration
_KEYSTONES[keystone_ep] = client.Client(
username=conf.mech_id,
password=conf.password,
tenant_name=conf.tenant_name,
auth_url=keystone_ep + '/v' + conf.version)
return _KEYSTONES[keystone_ep]
except Exception:
logger.critical(
'CRITICAL|CON{}KEYSTONE001|Cannot reach Keystone EP: {} of '
'region {}. Please contact Keystone team.'.format(
dictator.get('service_name', 'ORM'), keystone_ep, lcp_id))
raise
def is_token_valid(token_to_validate, lcp_id, conf, required_role=None,
role_location=None):
"""Validate a token.
:param token_to_validate: The token to validate
:param lcp_id: The ID of the LCP associated with the Keystone instance
with which the token was created
:param conf: A TokenConf object
:param required_role: The required role for privileged actions,
e.g. 'admin' (optional).
:param role_location: The Keystone role location (a dict whose single
key is either 'domain' or 'tenant', whose value is the location name)
:return: False if one of the tokens received (or more) is invalid,
True otherwise.
:raise: KeystoneNotFoundError when the Keystone EP for the required LCP
was not found in RMS output,
client.exceptions.AuthorizationFailure when the connection with the
Keystone EP could not be established,
client.exceptions.EndpointNotFound when _our_ authentication
(as an admin) with Keystone failed,
ValueError when an invalid Keystone version was specified,
ValueError when a role or a tenant was not found,
ValueError when a role is required but role_location is None.
"""
keystone_ep = _find_keystone_ep(conf.rms_url, lcp_id)
if keystone_ep is None:
raise KeystoneNotFoundError('Keystone EP of LCP %s not found in RMS' %
(lcp_id,))
if conf.version == '3':
client = v3_client
elif conf.version == '2.0':
client = v2_client
else:
raise ValueError('Invalid Keystone version: %s' % (conf.version,))
keystone = _get_keystone_client(client, conf, keystone_ep, lcp_id)
try:
user = keystone.tokens.validate(token_to_validate)
logger.debug('User token found in Keystone')
# Other exceptions raised by validate() are critical errors,
# so instead of returning False, we'll just let them propagate
except client.exceptions.NotFound:
logger.debug('User token not found in Keystone! Make sure that it is'
'correct and that it has not expired yet')
return False
if required_role is not None:
if role_location is None:
raise ValueError(
'A role is required but no role location was specified!')
try:
logger.debug('Checking role...')
return _does_user_have_role(keystone, conf.version, user,
required_role, role_location)
except client.exceptions.NotFound:
raise ValueError('Role %s or tenant %s not found!' % (
required_role, role_location,))
else:
# We know that the token is valid and there's no need to enforce a
# policy on this operation, so we can let the user pass
logger.debug('No role to check, authentication finished successfully')
return True

View File

@ -0,0 +1,2 @@
class NotFound(Exception):
pass

View File

@ -0,0 +1,6 @@
from keystoneclient import exceptions
class Client(object):
def __init__(*args, **kwargs):
pass

View File

@ -0,0 +1,6 @@
from keystoneclient import exceptions
class Client(object):
def __init__(*args, **kwargs):
pass

View File

@ -0,0 +1,10 @@
def get(*args, **kwargs):
pass
def set(*args, **kwargs):
pass
def soft_set(*args, **kwargs):
pass

View File

@ -0,0 +1,5 @@
# 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.
requests==2.2.1
python-keystoneclient==1.3.1

View File

@ -0,0 +1,46 @@
[metadata]
name = keystone_utils
summary = keyKeystone utils
description-file =
README.rst
author = OpenStack
author-email = openstack-dev@lists.openstack.org
home-page = http://www.openstack.org/
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.3
Programming Language :: Python :: 3.4
[files]
packages =
keystone_utils
[build_sphinx]
source-dir = doc/source
build-dir = doc/build
all_files = 1
[upload_sphinx]
upload-dir = doc/build/html
[compile_catalog]
directory = keystone_utils/locale
domain = keystone_utils
[update_catalog]
domain = keystone_utils
output_dir = keystone_utils/locale
input_file = keystone_utils/locale/keystone_utils.pot
[extract_messages]
keywords = _ gettext ngettext l_ lazy_gettext
mapping_file = babel.cfg
output_file = keystone_utils/locale/keystone_utils.pot

View File

@ -0,0 +1,14 @@
from setuptools import setup, find_packages
setup(
name='keystone_utils',
version='0.1',
description='',
author='',
author_email='',
zip_safe=False,
include_package_data=True,
packages=find_packages(),
test_suite='keystone_utils/tests'
)

View File

@ -0,0 +1,15 @@
# 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.
oslo.i18n==3.9.0
oslo.serialization==2.13.0
oslo.utils==3.16.0
hacking<0.11,>=0.10.0
mock<1.1.0,>=1.0
coverage>=3.6
python-subunit>=0.0.18
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2
testrepository>=0.0.18
testscenarios==0.4
testtools==1.4.0

View File

@ -0,0 +1,24 @@
[tox]
envlist = py27,cover
skipsdist = True
[testenv]
install_command =
# constraints: {[testenv:common-constraints]install_command}
pip install -U --force-reinstall {opts} {packages}
setenv = VIRTUAL_ENV={envdir}
OS_TEST_PATH=./keystone_utils/tests/unit
PYTHONPATH = {toxinidir}/mock_keystone/:/usr/local/lib/python2.7/dist-packages/
deps = -r{toxinidir}/test-requirements.txt
-r{toxinidir}/requirements.txt
[testenv:cover]
commands =
coverage erase
python setup.py testr --coverage
coverage report --omit="keystone_utils/tests/*"
coverage html --omit="keystone_utils/tests/*"
[testenv:pep8]
commands=
py.test --pep8 -m pep8

View File

View File

@ -0,0 +1,6 @@
def audit(*args, **kwargs):
pass
def init(*args, **kwargs):
pass

View File

@ -0,0 +1,2 @@
def get_token_user(*a, **k):
pass

View File

View File

@ -0,0 +1,70 @@
import json
import logging
from pecan.hooks import PecanHook
from orm_common.utils import api_error_utils as err_utils
logger = logging.getLogger(__name__)
class APIErrorHook(PecanHook):
def after(self, state):
# Handle http errors. reformat returned body and header.
status_code = state.response.status_code
transaction_id = str(getattr(state.request,
'transaction_id',
'N/A'))
tracking_id = str(getattr(state.request,
'tracking_id',
'N/A'))
result_json = {}
if 400 <= status_code <= 500:
if status_code == 401:
result_json = err_utils.get_error_dict(401,
transaction_id,
None)
else:
dict_body = None
try:
logger.debug('error: {}'.format(state.response))
dict_body = json.loads(state.response.body)
if 'line' in str(state.response.body) and 'column' in str(
state.response.body):
result_json = dict_body
status_code = 400
if 'faultstring' in dict_body:
result_json = err_utils.get_error_dict(status_code,
transaction_id,
dict_body['faultstring'],
"")
else:
result_json = json.loads(dict_body['faultstring'])
logger.debug('Received faultstring: {}'.format(result_json))
# make sure status code in header and in body are the same
if 'code' in result_json:
status_code = result_json['code']
logger.info('Received status code: {}, transaction_id: {}, tracking_id: {}'.
format(status_code, transaction_id, tracking_id))
except ValueError:
msg = 'Could not read faultstring from response body!'
logger.error('{} {}'.format(msg, state.response.body))
if 'faultstring' in state.response.headers:
msg = state.response.headers['faultstring']
elif dict_body and 'faultstring' in dict_body:
msg = dict_body['faultstring']
result_json = err_utils.get_error_dict(status_code,
transaction_id,
msg,
"")
setattr(state.response, 'body', json.dumps(result_json))
state.response.status_code = status_code
state.response.headers.add('X-RANGER-Request-Id', tracking_id)

View File

@ -0,0 +1,18 @@
import logging
from pecan.hooks import PecanHook
logger = logging.getLogger(__name__)
class SecurityHeadersHook(PecanHook):
def after(self, state):
security_headers = {'X-Frame-Options': 'DENY',
'X-Content-Type-Options': 'nosniff',
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
'Content-Security-Policy': 'default-src \'self\'',
'X-Permitted-Cross-Domain-Policies': 'none',
'X-XSS-Protection': '1; mode=block'}
# Add all the security headers
for header, value in security_headers.items():
state.response.headers.add(header, value)

View File

@ -0,0 +1,17 @@
from pecan import abort
from pecan.hooks import PecanHook
from orm_common.utils import utils
class TransactionIdHook(PecanHook):
def before(self, state):
try:
transaction_id = utils.make_transid()
except Exception as exc:
abort(500, headers={'faultstring': exc.message})
tracking_id = state.request.headers['X-RANGER-Tracking-Id'] \
if 'X-RANGER-Tracking-Id' in state.request.headers else transaction_id
setattr(state.request, 'transaction_id', transaction_id)
setattr(state.request, 'tracking_id', tracking_id)

View File

@ -0,0 +1,7 @@
'''
'''
from .di import Di
from .dependency_register import DependencyRegister
from .resource_provider_register import ResourceProviderRegister
from .resolver import DependencyResolver

Some files were not shown because too many files have changed in this diff Show More