Retire project

In Queens development cycle, openstack_auth code was merged
into the horizon repository.

blueprint merge-openstack-auth

Change-Id: I74b10a90fe79fc768cfb8de6f68d3cd2f4938e51
This commit is contained in:
Akihiro Motoki 2017-11-30 01:45:01 +09:00
parent 1fa9ae26cc
commit 2baea728dd
72 changed files with 8 additions and 8265 deletions

14
.gitignore vendored
View File

@ -1,14 +0,0 @@
*.pyc
*.egg
*.egg-info
*.mo
.DS_STORE
doc/build
build
dist
.tox
AUTHORS
ChangeLog
.coverage
reports
coverage.xml

View File

@ -1,4 +0,0 @@
[gerrit]
host=review.openstack.org
port=29418
project=openstack/django_openstack_auth.git

View File

@ -1,5 +0,0 @@
<david.lyle@hp.com> <david-lyle@davidlyle-VirtualBox.(none)>
<lin-hua.cheng@hp.com> <lin_hua_cheng@yahoo.com>
Eric Peterson <ericpeterson@hp.com> ericpeterson-l <ericpeterson@hp.com>
Eric Peterson <ericpeterson@hp.com> erpet <ericpeterson@hp.com>
Lin Hua Cheng <lin-hua.cheng@hp.com> linhuacheng <lin-hua.cheng@hp.com>

View File

@ -1,17 +0,0 @@
If you would like to contribute to the development of OpenStack,
you must follow the steps documented at:
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/django-openstack-auth

176
LICENSE
View File

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

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

View File

@ -1,27 +1,10 @@
========================
Team and repository tags
========================
The code has been merged into openstack/horizon.
.. image:: http://governance.openstack.org/badges/django_openstack_auth.svg
:target: http://governance.openstack.org/reference/tags/index.html
The contents of this repository are still available in the Git
source code management system. To see the contents of this
repository before it was merged into the horizon repo,
please check out the previous commit with "git checkout HEAD^1".
.. Change things from this point on
=====================
Django OpenStack Auth
=====================
Django OpenStack Auth is a pluggable Django authentication backend that
works with Django's ``contrib.auth`` framework to authenticate a user against
OpenStack's Keystone Identity API.
The current version is designed to work with the Keystone v2.0 and v3 API.
You can `view the installation instructions`_ on Read The Docs.
.. _view the installation instructions: http://docs.openstack.org/developer/django_openstack_auth/
* License: Apache License, Version 2.0
* Documentation: http://django-openstack-auth.readthedocs.org/en/latest/
* Source: http://git.openstack.org/cgit/openstack/django_openstack_auth/
* Bugs: https://bugs.launchpad.net/django-openstack-auth
For any further questions, please email
openstack-dev@lists.openstack.org or
join #openstack-horizon on Freenode.

View File

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

View File

@ -1,170 +0,0 @@
# -*- coding: utf-8 -*-
#
# Django OpenStack Auth documentation build configuration file, created by
# sphinx-quickstart on Sun Jul 8 15:13:36 2012.
#
# 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.
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'openstack_auth.tests.settings')
django.setup()
# 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.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# 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.viewcode', 'openstackdocstheme']
# openstackdocstheme options
repository_name = 'openstack/django_openstack_auth'
bug_project = 'django-openstack-auth'
bug_tag = ''
html_last_updated_fmt = '%Y-%m-%d %H:%M'
# 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-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Django OpenStack Auth'
copyright = u'2012, Gabriel Hurley'
# 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 patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# 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 = ['openstack_auth.']
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'openstackdocs'
# 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 = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# 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_domain_indices = 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, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = 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 = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'DjangoOpenStackAuthdoc'

View File

@ -1,442 +0,0 @@
=============
Configuration
=============
Django OpenStack Auth is configured through Django ``settings.py`` file.
In most cases it is used combined with the OpenStack Dashboard,
so the settings file will be ``local/local_settings.py`` file
in your OpenStack Dashboard deployment.
This page covers the configuration options referred by Django OpenStack Auth.
:ref:`Some settings <settings-shared-with-horizon>` are also referred to
by Horizon. Configure them carefully.
General settings
================
``AUTHENTICATION_PLUGINS``
--------------------------
Default: ``['openstack_auth.plugin.password.PasswordPlugin', 'openstack_auth.plugin.token.TokenPlugin']``
A list of authentication plugins to be used.
In most cases, there is no need to configure this.
``AVAILABLE_REGIONS``
---------------------
Default: ``None``
A list of tuples which define multiple regions. The tuple format is
``('http://{{ keystone_host }}:5000/v2.0', '{{ region_name }}')``. If any regions
are specified the login form will have a dropdown selector for authenticating
to the appropriate region, and there will be a region switcher dropdown in
the site header when logged in.
You should also define ``OPENSTACK_KEYSTONE_URL`` to indicate which of
the regions is the default one.
``DEFAULT_SERVICE_REGIONS``
---------------------------
Default: ``{}``
The default service region is set on a per-endpoint basis, meaning that once
the user logs into some Keystone endpoint, if a default service region is
defined for it in this setting and exists within Keystone catalog, it will be
set as the initial service region in this endpoint. By default it is an empty
dictionary because upstream can neither predict service region names in a
specific deployment, nor tell whether this behavior is desired. The key of the
dictionary is a full url of a Keystone endpoint with version suffix, the value
is a region name.
Example::
DEFAULT_SERVICE_REGIONS = {
OPENSTACK_KEYSTONE_URL: 'RegionOne'
}
``OPENSTACK_API_VERSIONS``
--------------------------
Default::
{
"identity": 2.0,
...,
}
Overrides for OpenStack API versions. Use this setting to force the
OpenStack dashboard to use a specific API version for a given service API.
Django OpenStack Auth refers to only the ``"identity"`` entry.
The current valid values are "2.0" or "3".
.. note::
See `Horizon settings
<https://docs.openstack.org/developer/horizon/install/settings.html#openstack-api-versions>`__
for the full description of this setting.
``OPENSTACK_ENDPOINT_TYPE``
---------------------------
Default: ``"publicURL"``
A string which specifies the endpoint type to use for the endpoints in the
Keystone service catalog. The default value for all services except for
identity is ``"publicURL"``. The default value for the identity service is
``"internalURL"``.
``OPENSTACK_KEYSTONE_ADMIN_ROLES``
----------------------------------
Default: ``["admin"]``
The list of roles that have administrator privileges in this OpenStack
installation. This check is very basic and essentially only works with
keystone v2.0 and v3 with the default policy file. The setting assumes there
is a common ``admin`` like role(s) across services. Example uses of this
setting are:
* to rename the ``admin`` role to ``cloud-admin``
* allowing multiple roles to have administrative privileges, like
``["admin", "cloud-admin", "net-op"]``
``OPENSTACK_KEYSTONE_DEFAULT_DOMAIN``
-------------------------------------
Default: ``"Default"``
Overrides the default domain used when running on single-domain model
with Keystone V3. All entities will be created in the default domain.
.. note::
This value must be the name of the default domain, NOT the ID.
Also, you will most likely have a value in the keystone policy file like
``"cloud_admin": "rule:admin_required and domain_id:<your domain id>"``.
This value must be the name of the domain whose ID is specified there.
``OPENSTACK_KEYSTONE_DOMAIN_CHOICES``
-------------------------------------
.. versionadded:: 12.0.0(Pike)
Default::
(
('Default', 'Default'),
)
If OPENSTACK_KEYSTONE_DOMAIN_DROPDOWN is enabled, this option can be used to
set the available domains to choose from. This is a list of pairs whose first
value is the domain name and the second is the display name.
``OPENSTACK_KEYSTONE_DOMAIN_DROPDOWN``
--------------------------------------
.. versionadded:: 12.0.0(Pike)
Default: ``False``
Set this to True if you want available domains displayed as a dropdown menu on
the login screen. It is strongly advised NOT to enable this for public clouds,
as advertising enabled domains to unauthenticated customers irresponsibly
exposes private information. This should only be used for private clouds where
the dashboard sits behind a corporate firewall.
``OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT``
------------------------------------------
Default: ``False``
Set this to True if running on multi-domain model. When this is enabled, it
will require user to enter the Domain name in addition to username for login.
``OPENSTACK_KEYSTONE_URL``
--------------------------
Default: ``"http://%s:5000/v2.0" % OPENSTACK_HOST``
The full URL for the Keystone endpoint used for authentication. Unless you
are using HTTPS, running your Keystone server on a nonstandard port, or using
a nonstandard URL scheme you shouldn't need to touch this setting.
``OPENSTACK_SSL_CACERT``
------------------------
Default: ``None``
When unset or set to ``None`` the default CA certificate on the system is used
for SSL verification.
When set with the path to a custom CA certificate file, this overrides use of
the default system CA certificate. This custom certificate is used to verify all
connections to openstack services when making API calls.
``OPENSTACK_SSL_NO_VERIFY``
---------------------------
Default: ``False``
Disable SSL certificate checks in the OpenStack clients (useful for self-signed
certificates).
``OPENSTACK_TOKEN_HASH_ALGORITHM``
----------------------------------
Default: ``"md5"``
The hash algorithm to use for authentication tokens. This must match the hash
algorithm that the identity (Keystone) server and the auth_token middleware
are using. Allowed values are the algorithms supported by Python's hashlib
library.
``OPENSTACK_TOKEN_HASH_ENABLED``
--------------------------------
(Deprecated)
Default: ``True``
Hashing tokens from Keystone keeps the Horizon session data smaller, but it
doesn't work in some cases when using PKI tokens. Uncomment this value and
set it to False if using PKI tokens and there are 401 errors due to token
hashing.
This option is now marked as "deprecated" and will be removed in Ocata or a
later release. PKI tokens currently work with hashing, and Keystone will soon
deprecate usage of PKI tokens.
``PASSWORD_EXPIRES_WARNING_THRESHOLD_DAYS``
-------------------------------------------
Default: ``-1``
Password will have an expiration date when using keystone v3 and enabling the
feature. This setting allows you to set the number of days that the user will
be alerted prior to the password expiration. Once the password expires keystone
will deny the access and users must contact an admin to change their password.
Setting this value to ``N`` days means the user will be alerted when the
password expires in less than ``N+1`` days. ``-1`` disables the feature.
``POLICY_DIRS``
----------------
Default: ``{}``
Specifies a list of policy directories per service types. The directories
are relative to ``POLICY_FILES_PATH``. Services whose additional policies
are defined here must be defined in ``POLICY_FILES`` too. Otherwise,
additional policies specified in ``POLICY_DIRS`` are not loaded.
Example::
POLICY_DIRS = {
'identity': 'keystone_policy.d',
'compute': 'nova_policy.d'
}
``POLICY_FILES``
----------------
Default: ``{'identity': 'keystone_policy.json', 'compute': 'nova_policy.json'}``
This should essentially be the mapping of the contents of ``POLICY_FILES_PATH``
to service types. When policy.json files are added to ``POLICY_FILES_PATH``,
they should be included here too.
``POLICY_FILES_PATH``
---------------------
Default: ``os.path.join(ROOT_PATH, "conf")``
Specifies where service based policy files are located. These are used to
define the policy rules actions are verified against.
``SECURE_PROXY_ADDR_HEADER``
----------------------------
Default: ``False``
If horizon is behind a proxy server and the proxy is configured, the IP address
from request is passed using header variables inside the request. The header
name depends on a proxy or a load-balancer. This setting specifies the name of
the header with remote IP address. The main use is for authentication log
(success or fail) displaing the IP address of the user.
The commom value for this setting is ``HTTP_X_REAL_IP`` or
``HTTP_X_FORWARDED_FOR``.
If not present, then ``REMOTE_ADDR`` header is used. (``REMOTE_ADDR`` is the
field of Django HttpRequest object which contains IP address of the client.)
``SESSION_TIMEOUT``
-------------------
Default: ``"3600"``
This ``SESSION_TIMEOUT`` is a method to supercede the token timeout with a
shorter horizon session timeout (in seconds). So if your token expires in
60 minutes, a value of 1800 will log users out after 30 minutes.
``TOKEN_DELETION_DISABLED``
---------------------------
Default: ``False``
This setting allows deployers to control whether a token is deleted on log out.
This can be helpful when there are often long running processes being run
in the Horizon environment.
``TOKEN_TIMEOUT_MARGIN``
------------------------
Default: ``0``
A time margin in seconds to subtract from the real token's validity.
An example usage is that the token can be valid once the middleware
passed, and invalid (timed-out) during a view rendering and this
generates authorization errors during the view rendering.
By setting this value to some smaller seconds, you can avoid token
expiration during a view rendering.
``WEBROOT``
-----------
Default: ``"/"``
Specifies the location where the access to the dashboard is configured in
the web server.
For example, if you're accessing the Dashboard via
https://<your server>/dashboard, you would set this to ``"/dashboard/"``.
.. note::
Additional settings may be required in the config files of your webserver
of choice. For example to make ``"/dashboard/"`` the web root in Apache,
the ``"sites-available/horizon.conf"`` requires a couple of additional
aliases set::
Alias /dashboard/static %HORIZON_DIR%/static
Alias /dashboard/media %HORIZON_DIR%/openstack_dashboard/static
Apache also requires changing your WSGIScriptAlias to reflect the desired
path. For example, you'd replace ``/`` with ``/dashboard`` for the
alias.
Web SSO (Single Sign On) settings
=================================
``WEBSSO_ENABLED``
------------------
Default: ``False``
Enables keystone web single-sign-on if set to True. For this feature to work,
make sure that you are using Keystone V3 and Django OpenStack Auth V1.2.0 or
later.
``WEBSSO_INITIAL_CHOICE``
-------------------------
Default: ``"credentials"``
Determines the default authentication mechanism. When user lands on the login
page, this is the first choice they will see.
``WEBSSO_CHOICES``
------------------
Default::
(
("credentials", _("Keystone Credentials")),
("oidc", _("OpenID Connect")),
("saml2", _("Security Assertion Markup Language"))
)
This is the list of authentication mechanisms available to the user. It
includes Keystone federation protocols such as OpenID Connect and SAML, and
also keys that map to specific identity provider and federation protocol
combinations (as defined in ``WEBSSO_IDP_MAPPING``). The list of choices is
completely configurable, so as long as the id remains intact. Do not remove
the credentials mechanism unless you are sure. Once removed, even admins will
have no way to log into the system via the dashboard.
``WEBSSO_IDP_MAPPING``
----------------------
Default: ``{}``
A dictionary of specific identity provider and federation protocol combinations.
From the selected authentication mechanism, the value will be looked up as keys
in the dictionary. If a match is found, it will redirect the user to a identity
provider and federation protocol specific WebSSO endpoint in keystone, otherwise
it will use the value as the protocol_id when redirecting to the WebSSO by
protocol endpoint.
Example::
WEBSSO_CHOICES = (
("credentials", _("Keystone Credentials")),
("oidc", _("OpenID Connect")),
("saml2", _("Security Assertion Markup Language")),
("acme_oidc", "ACME - OpenID Connect"),
("acme_saml2", "ACME - SAML2")
)
WEBSSO_IDP_MAPPING = {
"acme_oidc": ("acme", "oidc"),
"acme_saml2": ("acme", "saml2")
}
.. note::
The value is expected to be a tuple formatted as: (<idp_id>, <protocol_id>).
K2K (Keystone to Keystone) Federation settings
==============================================
``KEYSTONE_PROVIDER_IDP_NAME``
------------------------------
Default: ``Local Keystone``
The Keystone Provider drop down uses Keystone to Keystone federation
to switch between Keystone service providers.
This sets display name for Identity Provider (dropdown display name).
``KEYSTONE_PROVIDER_IDP_ID``
----------------------------
Default:: ``localkeystone``
This ID is used for only for comparison with the service provider IDs.
This ID should not match any service provider IDs.
.. _settings-shared-with-horizon:
Settings shared with Horizon
============================
The following settings in Django OpenStack Auth are also used by Horizon.
* ``AVAILABLE_REGIONS``
* ``OPENSTACK_API_VERSIONS``
* ``OPENSTACK_KEYSTONE_URL``
* ``OPENSTACK_ENDPOINT_TYPE``
* ``OPENSTACK_SSL_CACERT``
* ``OPENSTACK_SSL_NO_VERIFY``
* ``WEBROOT``
Django OpenStack Auth also refers to the following Django settings.
For more detail, see `Django settings documentation
<https://docs.djangoproject.com/en/1.11/ref/settings/#auth>`__.
They are usually configured as part of Horizon settings.
* ``LOGIN_REDIRECT_URL``
* ``LOGIN_URL``
* ``SESSION_ENGINE``
* ``USE_TZ``

View File

@ -1,21 +0,0 @@
=====================
Django OpenStack Auth
=====================
Django OpenStack Auth is a pluggable Django authentication backend that
works with Django's ``contrib.auth`` framework to authenticate a user against
OpenStack's Keystone Identity API.
The current version is designed to work with the Keystone V2 or V3 API.
.. toctree::
:maxdepth: 2
install/index
configuration/index
reference/index
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -1,63 +0,0 @@
===============
Getting Started
===============
Installation
============
Installing is quick and easy:
#. Run ``pip install django_openstack_auth``.
#. Add ``openstack_auth`` to ``settings.INSTALLED_APPS``.
#. Add ``'openstack_auth.backend.KeystoneBackend'`` to your
``settings.AUTHENTICATION_BACKENDS``, e.g.::
AUTHENTICATION_BACKENDS = ('openstack_auth.backend.KeystoneBackend',)
#. Configure your API endpoint(s) in ``settings.py``::
OPENSTACK_KEYSTONE_URL = "http://example.com:5000/v3"
#. Include ``'openstack_auth.urls'`` somewhere in your ``urls.py`` file.
#. Use it as you would any other Django auth backend.
Running Tests
=============
Before running tests, you should have ``tox`` installed and available in your
environment:
.. code-block:: bash
$ pip install tox
.. NOTE::
You may need to perform both the above operation and the next inside a
python virtualenv, or prefix the above command with ``sudo``, depending on
your preference.
To execute the full suite of tests maintained within the project, simply run:
.. code-block:: bash
$ tox
.. NOTE::
The first time you run ``tox``, it will take additional time to build
virtualenvs. You can later use the ``-r`` option with ``tox`` to rebuild
your virtualenv in a similar manner.
To run tests for one or more specific test environments (for example, the most
common configuration of Python 2.7 and PEP-8), list the environments with the
``-e`` option, separated by spaces:
.. code-block:: bash
$ tox -e py27,pep8
See ``tox.ini`` for the full list of available test environments.

View File

@ -1,6 +0,0 @@
==================
The Backend Module
==================
.. automodule:: openstack_auth.backend
:members:

View File

@ -1,6 +0,0 @@
================
The Forms Module
================
.. automodule:: openstack_auth.forms
:members:

View File

@ -1,13 +0,0 @@
=====================================
Django OpenStack Auth API Reference
=====================================
.. toctree::
:maxdepth: 2
user
views
forms
backend
utils

View File

@ -1,6 +0,0 @@
==============
The User Class
==============
.. automodule:: openstack_auth.user
:members:

View File

@ -1,6 +0,0 @@
================
The Utils Module
================
.. automodule:: openstack_auth.utils
:members:

View File

@ -1,6 +0,0 @@
================
The Views Module
================
.. automodule:: openstack_auth.views
:members:

View File

@ -1,17 +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 pbr.version
__version__ = pbr.version.VersionInfo('django_openstack_auth').version_string()

View File

@ -1,282 +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.
""" Module defining the Django auth backend class for the Keystone API. """
import datetime
import logging
import pytz
from django.conf import settings
from django.utils.module_loading import import_string
from django.utils.translation import ugettext_lazy as _
from openstack_auth import exceptions
from openstack_auth import user as auth_user
from openstack_auth import utils
LOG = logging.getLogger(__name__)
KEYSTONE_CLIENT_ATTR = "_keystoneclient"
class KeystoneBackend(object):
"""Django authentication backend for use with ``django.contrib.auth``."""
def __init__(self):
self._auth_plugins = None
@property
def auth_plugins(self):
if self._auth_plugins is None:
plugins = getattr(
settings,
'AUTHENTICATION_PLUGINS',
['openstack_auth.plugin.password.PasswordPlugin',
'openstack_auth.plugin.token.TokenPlugin'])
self._auth_plugins = [import_string(p)() for p in plugins]
return self._auth_plugins
def check_auth_expiry(self, auth_ref, margin=None):
if not utils.is_token_valid(auth_ref, margin):
msg = _("The authentication token issued by the Identity service "
"has expired.")
LOG.warning("The authentication token issued by the Identity "
"service appears to have expired before it was "
"issued. This may indicate a problem with either your "
"server or client configuration.")
raise exceptions.KeystoneAuthException(msg)
return True
def get_user(self, user_id):
"""Returns the current user from the session data.
If authenticated, this return the user object based on the user ID
and session data.
.. note::
This required monkey-patching the ``contrib.auth`` middleware
to make the ``request`` object available to the auth backend class.
"""
if (hasattr(self, 'request') and
user_id == self.request.session["user_id"]):
token = self.request.session['token']
endpoint = self.request.session['region_endpoint']
services_region = self.request.session['services_region']
user = auth_user.create_user_from_token(self.request, token,
endpoint, services_region)
return user
else:
return None
def authenticate(self, auth_url=None, **kwargs):
"""Authenticates a user via the Keystone Identity API."""
LOG.debug('Beginning user authentication')
if not auth_url:
auth_url = settings.OPENSTACK_KEYSTONE_URL
auth_url, url_fixed = utils.fix_auth_url_version_prefix(auth_url)
if url_fixed:
LOG.warning("The OPENSTACK_KEYSTONE_URL setting points to a v2.0 "
"Keystone endpoint, but v3 is specified as the API "
"version to use by Horizon. Using v3 endpoint for "
"authentication.")
for plugin in self.auth_plugins:
unscoped_auth = plugin.get_plugin(auth_url=auth_url, **kwargs)
if unscoped_auth:
break
else:
msg = _('No authentication backend could be determined to '
'handle the provided credentials.')
LOG.warning('No authentication backend could be determined to '
'handle the provided credentials. This is likely a '
'configuration error that should be addressed.')
raise exceptions.KeystoneAuthException(msg)
# the recent project id a user might have set in a cookie
recent_project = None
request = kwargs.get('request')
if request:
# Grab recent_project found in the cookie, try to scope
# to the last project used.
recent_project = request.COOKIES.get('recent_project')
unscoped_auth_ref = plugin.get_access_info(unscoped_auth)
# Check expiry for our unscoped auth ref.
self.check_auth_expiry(unscoped_auth_ref)
domain_name = kwargs.get('user_domain_name', None)
domain_auth, domain_auth_ref = plugin.get_domain_scoped_auth(
unscoped_auth, unscoped_auth_ref, domain_name)
scoped_auth, scoped_auth_ref = plugin.get_project_scoped_auth(
unscoped_auth, unscoped_auth_ref, recent_project=recent_project)
# Abort if there are no projects for this user and a valid domain
# token has not been obtained
#
# The valid use cases for a user login are:
# Keystone v2: user must have a role on a project and be able
# to obtain a project scoped token
# Keystone v3: 1) user can obtain a domain scoped token (user
# has a role on the domain they authenticated to),
# only, no roles on a project
# 2) user can obtain a domain scoped token and has
# a role on a project in the domain they
# authenticated to (and can obtain a project scoped
# token)
# 3) user cannot obtain a domain scoped token, but can
# obtain a project scoped token
if not scoped_auth_ref and domain_auth_ref:
# if the user can't obtain a project scoped token, set the scoped
# token to be the domain token, if valid
scoped_auth = domain_auth
scoped_auth_ref = domain_auth_ref
elif not scoped_auth_ref and not domain_auth_ref:
msg = _('You are not authorized for any projects.')
if utils.get_keystone_version() >= 3:
msg = _('You are not authorized for any projects or domains.')
raise exceptions.KeystoneAuthException(msg)
# Check expiry for our new scoped token.
self.check_auth_expiry(scoped_auth_ref)
# We want to try to use the same region we just logged into
# which may or may not be the default depending upon the order
# keystone uses
region_name = None
id_endpoints = scoped_auth_ref.service_catalog.\
get_endpoints(service_type='identity')
for id_endpoint in [cat for cat in id_endpoints['identity']]:
if auth_url in id_endpoint.values():
region_name = id_endpoint['region']
break
interface = getattr(settings, 'OPENSTACK_ENDPOINT_TYPE', 'public')
endpoint, url_fixed = utils.fix_auth_url_version_prefix(
scoped_auth_ref.service_catalog.url_for(
service_type='identity',
interface=interface,
region_name=region_name))
if url_fixed:
LOG.warning("The Keystone URL in service catalog points to a v2.0 "
"Keystone endpoint, but v3 is specified as the API "
"version to use by Horizon. Using v3 endpoint for "
"authentication.")
# If we made it here we succeeded. Create our User!
unscoped_token = unscoped_auth_ref.auth_token
user = auth_user.create_user_from_token(
request,
auth_user.Token(scoped_auth_ref, unscoped_token=unscoped_token),
endpoint,
services_region=region_name)
if request is not None:
# if no k2k providers exist then the function returns quickly
utils.store_initial_k2k_session(auth_url, request, scoped_auth_ref,
unscoped_auth_ref)
request.session['unscoped_token'] = unscoped_token
if domain_auth_ref:
# check django session engine, if using cookies, this will not
# work, as it will overflow the cookie so don't add domain
# scoped token to the session and put error in the log
if utils.using_cookie_backed_sessions():
LOG.error('Using signed cookies as SESSION_ENGINE with '
'OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT is '
'enabled. This disables the ability to '
'perform identity operations due to cookie size '
'constraints.')
else:
request.session['domain_token'] = domain_auth_ref
request.user = user
timeout = getattr(settings, "SESSION_TIMEOUT", 3600)
token_life = user.token.expires - datetime.datetime.now(pytz.utc)
session_time = min(timeout, int(token_life.total_seconds()))
request.session.set_expiry(session_time)
keystone_client_class = utils.get_keystone_client().Client
session = utils.get_session()
scoped_client = keystone_client_class(session=session,
auth=scoped_auth)
# Support client caching to save on auth calls.
setattr(request, KEYSTONE_CLIENT_ATTR, scoped_client)
LOG.debug('Authentication completed.')
return user
def get_group_permissions(self, user, obj=None):
"""Returns an empty set since Keystone doesn't support "groups"."""
# Keystone V3 added "groups". The Auth token response includes the
# roles from the user's Group assignment. It should be fine just
# returning an empty set here.
return set()
def get_all_permissions(self, user, obj=None):
"""Returns a set of permission strings that the user has.
This permission available to the user is derived from the user's
Keystone "roles".
The permissions are returned as ``"openstack.{{ role.name }}"``.
"""
if user.is_anonymous() or obj is not None:
return set()
# TODO(gabrielhurley): Integrate policy-driven RBAC
# when supported by Keystone.
role_perms = {utils.get_role_permission(role['name'])
for role in user.roles}
services = []
for service in user.service_catalog:
try:
service_type = service['type']
except KeyError:
continue
service_regions = [utils.get_endpoint_region(endpoint) for endpoint
in service.get('endpoints', [])]
if user.services_region in service_regions:
services.append(service_type.lower())
service_perms = {"openstack.services.%s" % service
for service in services}
return role_perms | service_perms
def has_perm(self, user, perm, obj=None):
"""Returns True if the given user has the specified permission."""
if not user.is_active:
return False
return perm in self.get_all_permissions(user, obj)
def has_module_perms(self, user, app_label):
"""Returns True if user has any permissions in the given app_label.
Currently this matches for the app_label ``"openstack"``.
"""
if not user.is_active:
return False
for perm in self.get_all_permissions(user):
if perm[:perm.index('.')] == app_label:
return True
return False

View File

@ -1,17 +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 KeystoneAuthException(Exception):
"""Generic error class to identify and catch our own errors."""
pass

View File

@ -1,155 +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 collections
import logging
from django.conf import settings
from django.contrib.auth import authenticate
from django.contrib.auth import forms as django_auth_forms
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.debug import sensitive_variables
from openstack_auth import exceptions
from openstack_auth import utils
LOG = logging.getLogger(__name__)
class Login(django_auth_forms.AuthenticationForm):
"""Form used for logging in a user.
Handles authentication with Keystone by providing the domain name, username
and password. A scoped token is fetched after successful authentication.
A domain name is required if authenticating with Keystone V3 running
multi-domain configuration.
If the user authenticated has a default project set, the token will be
automatically scoped to their default project.
If the user authenticated has no default project set, the authentication
backend will try to scope to the projects returned from the user's assigned
projects. The first successful project scoped will be returned.
Inherits from the base ``django.contrib.auth.forms.AuthenticationForm``
class for added security features.
"""
use_required_attribute = False
region = forms.ChoiceField(label=_("Region"), required=False)
username = forms.CharField(
label=_("User Name"),
widget=forms.TextInput(attrs={"autofocus": "autofocus"}))
password = forms.CharField(label=_("Password"),
widget=forms.PasswordInput(render_value=False))
def __init__(self, *args, **kwargs):
super(Login, self).__init__(*args, **kwargs)
fields_ordering = ['username', 'password', 'region']
if getattr(settings,
'OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT',
False):
last_domain = self.request.COOKIES.get('login_domain', None)
if getattr(settings,
'OPENSTACK_KEYSTONE_DOMAIN_DROPDOWN',
False):
self.fields['domain'] = forms.ChoiceField(
label=_("Domain"),
initial=last_domain,
required=True,
choices=getattr(settings,
'OPENSTACK_KEYSTONE_DOMAIN_CHOICES',
()))
else:
self.fields['domain'] = forms.CharField(
initial=last_domain,
label=_("Domain"),
required=True,
widget=forms.TextInput(attrs={"autofocus": "autofocus"}))
self.fields['username'].widget = forms.widgets.TextInput()
fields_ordering = ['domain', 'username', 'password', 'region']
self.fields['region'].choices = self.get_region_choices()
if len(self.fields['region'].choices) == 1:
self.fields['region'].initial = self.fields['region'].choices[0][0]
self.fields['region'].widget = forms.widgets.HiddenInput()
elif len(self.fields['region'].choices) > 1:
self.fields['region'].initial = self.request.COOKIES.get(
'login_region')
# if websso is enabled and keystone version supported
# prepend the websso_choices select input to the form
if utils.is_websso_enabled():
initial = getattr(settings, 'WEBSSO_INITIAL_CHOICE', 'credentials')
self.fields['auth_type'] = forms.ChoiceField(
label=_("Authenticate using"),
choices=getattr(settings, 'WEBSSO_CHOICES', ()),
required=False,
initial=initial)
# add auth_type to the top of the list
fields_ordering.insert(0, 'auth_type')
# websso is enabled, but keystone version is not supported
elif getattr(settings, 'WEBSSO_ENABLED', False):
msg = ("Websso is enabled but horizon is not configured to work " +
"with keystone version 3 or above.")
LOG.warning(msg)
self.fields = collections.OrderedDict(
(key, self.fields[key]) for key in fields_ordering)
@staticmethod
def get_region_choices():
default_region = (settings.OPENSTACK_KEYSTONE_URL, "Default Region")
regions = getattr(settings, 'AVAILABLE_REGIONS', [])
if not regions:
regions = [default_region]
return regions
@sensitive_variables()
def clean(self):
default_domain = getattr(settings,
'OPENSTACK_KEYSTONE_DEFAULT_DOMAIN',
'Default')
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
region = self.cleaned_data.get('region')
domain = self.cleaned_data.get('domain', default_domain)
if not (username and password):
# Don't authenticate, just let the other validators handle it.
return self.cleaned_data
try:
self.user_cache = authenticate(request=self.request,
username=username,
password=password,
user_domain_name=domain,
auth_url=region)
msg = 'Login successful for user "%(username)s", remote address '\
'%(remote_ip)s.' % {
'username': username,
'remote_ip': utils.get_client_ip(self.request)
}
LOG.info(msg)
except exceptions.KeystoneAuthException as exc:
msg = 'Login failed for user "%(username)s", remote address '\
'%(remote_ip)s.' % {
'username': username,
'remote_ip': utils.get_client_ip(self.request)
}
LOG.warning(msg)
raise forms.ValidationError(exc)
if hasattr(self, 'check_for_test_cookie'): # Dropped in django 1.7
self.check_for_test_cookie()
return self.cleaned_data

View File

@ -1,74 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Zbyněk Schwarz <zbynek.schwarz@gmail.com>, 2014-2015
# Stanislav Ulrych <stanislav.ulrych@ultimum.io>, 2016. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.1.1.dev1\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-01-25 19:41+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2016-06-09 07:46+0000\n"
"Last-Translator: Lenka Husáková <lenka.husakova@ultimum.io>\n"
"Language: cs\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.3\n"
"Language-Team: Czech\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "Při ověřování se vyskytla chyba. Zkuste to prosím znovu později."
msgid "Authenticate using"
msgstr "Přihlásit se pomocí"
msgid "Domain"
msgstr "Doména"
msgid "Invalid credentials."
msgstr "Neplatné přihlašovací údaje."
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr ""
"Nebyl rozpoznán žádný vhodný autentizační backend pro ověření zadaných "
"přihlašovacích údajů."
msgid "Password"
msgstr "Heslo"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "Změna projektu selhala u uživatele \"%(username)s\"."
msgid "Region"
msgstr "Region"
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "Změna projektu \"%(project_name)s\" byla úspěšná."
msgid "The authentication token issued by the Identity service has expired."
msgstr "Autentizační token poskytnutý službou identit vypršel."
msgid "Unable to establish connection to keystone endpoint."
msgstr "Nelze se připojit ke keystone endpointu."
msgid "Unable to retrieve authorized projects."
msgstr "Nelze získat oprávněné projekty."
msgid "User Name"
msgstr "Uživatelské jméno"
msgid "You are not authorized for any projects or domains."
msgstr "Nemáte oprávnění k žádným projektům či doménám."
msgid "You are not authorized for any projects."
msgstr "Nemáte oprávnění k žádným projektům."

View File

@ -1,103 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Andreas Jaeger <jaegerandi@gmail.com>, 2014
# Robert Simai, 2015
# Robert Simai, 2015
# Frank Kloeker <eumel@arcor.de>, 2016. #zanata
# Andreas Jaeger <jaegerandi@gmail.com>, 2017. #zanata
# Robert Simai <robert.simai@suse.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.1.2.dev14\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-04-07 13:52+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-03-28 08:35+0000\n"
"Last-Translator: Robert Simai <robert.simai@suse.com>\n"
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.9.6\n"
"Language-Team: German\n"
msgid "An error occurred authenticating. Please try again later."
msgstr ""
"Während der Authentifizierung ist ein Fehler aufgetreten. Bitte versuchen "
"Sie es später noch einmal."
msgid "Authenticate using"
msgstr "Authentifizieren mit"
msgid "Could not find service provider ID on Keystone."
msgstr "Dienstanbieter ID in Keystone nicht gefunden."
msgid "Domain"
msgstr "Domäne"
msgid "Invalid credentials."
msgstr "Unzureichende Berechtigung."
msgid "K2K Federation not setup for this session"
msgstr "K2K Verbund ist für diese Sitzung nicht eingerichtet"
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr ""
"Es konnte kein Authentifizierungsbackend für die angegebene Legitimierung "
"gefunden werden."
msgid "Password"
msgstr "Passwort"
#, python-format
msgid "Please consider changing your password, it will expire in %s minutes"
msgstr "Bitte ändern Sie Ihr Passwort. Es läuft in %s Minuten ab."
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "Projektumschaltung für Benutzer \"%(username)s\" fehlgeschlagen."
msgid "Region"
msgstr "Region"
#, python-format
msgid "Service provider authentication failed. %s"
msgstr "Dienstanbieter Authentifizierung fehlgeschlagen. %s"
#, python-format
msgid "Switch to Keystone Provider \"%(keystone_provider)s\"successful."
msgstr ""
"Umschalten zum Keystone Anbieter \"%(keystone_provider)s\" erfolgreich."
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "Umschalten zum Projekt \"%(project_name)s\" erfolgreich."
msgid "The authentication token issued by the Identity service has expired."
msgstr ""
"Das vom Identitätsdienst ausgegebene Authentifizierungs-Token ist abgelaufen."
msgid "Unable to establish connection to keystone endpoint."
msgstr "Es kann keine Verbindung zum Keystone Endpunkt aufgebaut werden."
msgid "Unable to retrieve authorized domains."
msgstr "Die authorisierten Domänen können nicht abgerufen werden."
msgid "Unable to retrieve authorized projects."
msgstr "Authorisierte Projekte können nicht abgerufen werden."
msgid "User Name"
msgstr "Benutzername"
msgid "You are not authorized for any projects or domains."
msgstr "Sie sind nicht autorisiert für irgendein Projekt oder eine Domäne."
msgid "You are not authorized for any projects."
msgstr "Sie sind für kein Projekt berechtigt."

View File

@ -1,75 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Tom Fifield <tom@openstack.org>, 2015
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Tom Fifield <tom@openstack.org>, 2016. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.1.1.dev1\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-01-25 19:41+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2016-09-19 04:53+0000\n"
"Last-Translator: Tom Fifield <tom@openstack.org>\n"
"Language: en-AU\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.3\n"
"Language-Team: English (Australia)\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "An error occurred authenticating. Please try again later."
msgid "Authenticate using"
msgstr "Authenticate using"
msgid "Domain"
msgstr "Domain"
msgid "Invalid credentials."
msgstr "Invalid credentials."
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgid "Password"
msgstr "Password"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "Project switch failed for user \"%(username)s\"."
msgid "Region"
msgstr "Region"
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "Switch to project \"%(project_name)s\" successful."
msgid "The authentication token issued by the Identity service has expired."
msgstr "The authentication token issued by the Identity service has expired."
msgid "Unable to establish connection to keystone endpoint."
msgstr "Unable to establish connection to keystone endpoint."
msgid "Unable to retrieve authorized projects."
msgstr "Unable to retrieve authorized projects."
msgid "User Name"
msgstr "User Name"
msgid "You are not authorized for any projects or domains."
msgstr "You are not authorised for any projects or domains."
msgid "You are not authorized for any projects."
msgstr "You are not authorized for any projects."

View File

@ -1,97 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Rob Cresswell <robert.cresswell@outlook.com>, 2015
# Andi Chandler <andi@gowling.com>, 2016. #zanata
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Andi Chandler <andi@gowling.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.5.1.dev13\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-09-21 00:53+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-10-05 03:49+0000\n"
"Last-Translator: Andi Chandler <andi@gowling.com>\n"
"Language: en-GB\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.9.6\n"
"Language-Team: English (United Kingdom)\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "An error occurred authenticating. Please try again later."
msgid "Authenticate using"
msgstr "Authenticate using"
msgid "Could not find service provider ID on Keystone."
msgstr "Could not find service provider ID on Keystone."
msgid "Domain"
msgstr "Domain"
msgid "Invalid credentials."
msgstr "Invalid credentials."
msgid "K2K Federation not setup for this session"
msgstr "K2K Federation not setup for this session"
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgid "Password"
msgstr "Password"
#, python-format
msgid "Please consider changing your password, it will expire in %s minutes"
msgstr "Please consider changing your password, it will expire in %s minutes"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "Project switch failed for user \"%(username)s\"."
msgid "Region"
msgstr "Region"
#, python-format
msgid "Service provider authentication failed. %s"
msgstr "Service provider authentication failed. %s"
#, python-format
msgid "Switch to Keystone Provider \"%(keystone_provider)s\"successful."
msgstr "Switch to Keystone Provider \"%(keystone_provider)s\"successful."
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "Switch to project \"%(project_name)s\" successful."
msgid "The authentication token issued by the Identity service has expired."
msgstr "The authentication token issued by the Identity service has expired."
msgid "Unable to establish connection to keystone endpoint."
msgstr "Unable to establish connection to keystone endpoint."
msgid "Unable to retrieve authorized domains."
msgstr "Unable to retrieve authorised domains."
msgid "Unable to retrieve authorized projects."
msgstr "Unable to retrieve authorised projects."
msgid "User Name"
msgstr "User Name"
msgid "You are not authorized for any projects or domains."
msgstr "You are not authorised for any projects or domains."
msgid "You are not authorized for any projects."
msgstr "You are not authorised for any projects."

View File

@ -1,97 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Adriana Chisco Landazábal <achisco94@gmail.com>, 2015
# Alberto Molina Coballes <alb.molina@gmail.com>, 2014
# dario hereñu <magallania@gmail.com>, 2015
# luis gil, 2015
# Marian Tort <marian.tort@gmail.com>, 2014
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Zeus Arias Lucero <zeusariaslucero@gmail.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.5.1.dev10\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-09-12 23:53+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-08-24 09:49+0000\n"
"Last-Translator: Zeus Arias Lucero <zeusariaslucero@gmail.com>\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.9.6\n"
"Language-Team: Spanish\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "Se produjo un error de autenticación. Inténtelo de nuevo más tarde."
msgid "Authenticate using"
msgstr "Autenticación con"
msgid "Could not find service provider ID on Keystone."
msgstr "No se ha podido encontrar el ID del proveedor de servicios de Keystone"
msgid "Domain"
msgstr "Dominio"
msgid "Invalid credentials."
msgstr "Credenciales no válidas"
msgid "K2K Federation not setup for this session"
msgstr "K2K Federation no esta configurada para esta sesión"
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr ""
"No se ha podido determinar un backend de autenticación para gestionar las "
"credenciales proporcionadas."
msgid "Password"
msgstr "Contraseña"
#, python-format
msgid "Please consider changing your password, it will expire in %s minutes"
msgstr "Por favor considera cambiar su contraseña, va a expirar en %s minutos"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "Intercambio de projecto fracasó para el usuario \"%(username)s\"."
msgid "Region"
msgstr "Región"
#, python-format
msgid "Switch to Keystone Provider \"%(keystone_provider)s\"successful."
msgstr ""
"Cambio al proveedor de Keystone \"%(keystone_provider)s\" de manera exitosa."
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "Cambio al proyecto \"%(project_name)s\" de manera exitosa."
msgid "The authentication token issued by the Identity service has expired."
msgstr "El token de autenticación emitido por Identity Service ha expirado."
msgid "Unable to establish connection to keystone endpoint."
msgstr "No ha sido posible establecer conexión con el endpoint de keystone."
msgid "Unable to retrieve authorized domains."
msgstr "No ha sido posible recuperar los dominios autorizados."
msgid "Unable to retrieve authorized projects."
msgstr "No ha sido posible obtener los proyectos autorizados."
msgid "User Name"
msgstr "Usuario"
msgid "You are not authorized for any projects or domains."
msgstr "No tiene autorización para ningún proyecto ni dominio."
msgid "You are not authorized for any projects."
msgstr "No está autorizado en ningún proyecto."

View File

@ -1,74 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Heleno Jimenez de la Cruz <heleno.jimenez@gmail.com>, 2015
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.1.1.dev1\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-01-25 19:41+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2015-09-18 03:50+0000\n"
"Last-Translator: Heleno Jimenez de la Cruz <heleno.jimenez@gmail.com>\n"
"Language: es-MX\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.3\n"
"Language-Team: Spanish (Mexico)\n"
msgid "An error occurred authenticating. Please try again later."
msgstr ""
"Se ha producido un error de autenticación. Por favor inténtelo de nuevo más "
"tarde."
msgid "Authenticate using"
msgstr "Autentificar usando"
msgid "Domain"
msgstr "Dominio"
msgid "Invalid credentials."
msgstr "Credenciales inválidas."
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr ""
"Autentificación de soporte no puede ser determinada para manejar las "
"credenciales proveidas."
msgid "Password"
msgstr "Contraseña"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "Cambio de proyecto fallido para el usuario \"%(username)s\"."
msgid "Region"
msgstr "Región."
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "Cambio al proyecto \"%(project_name)s\" satisfactorio."
msgid "The authentication token issued by the Identity service has expired."
msgstr ""
"El token de autenticación otorgado por el servicio de identidad ha expirado."
msgid "Unable to establish connection to keystone endpoint."
msgstr "No es posible establecer conexión a punto final de la clave base."
msgid "Unable to retrieve authorized projects."
msgstr "No se pueden recuperar los proyectos autorizados."
msgid "User Name"
msgstr "Nombre de Usuario"
msgid "You are not authorized for any projects."
msgstr "No estás autorizado para algunos proyectos."

View File

@ -1,105 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Cédric Savignan <liced@liced.fr>, 2015
# Corinne Verheyde <cverheyd@hotmail.com>, 2015
# François Bureau, 2015
# Maxime COQUEREL <max.coquerel@gmail.com>, 2015
# Patte D <pattedeph@gmail.com>, 2015
# Xavier Gauvrit <xavier.gauvrit@cloudwatt.com>, 2014
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Gérald LONLAS <g.lonlas@gmail.com>, 2016. #zanata
# JF Taltavull <jftalta@gmail.com>, 2017. #zanata
# Loic Nicolle <loic.nicolle@orange.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.4.1.dev1\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-07-19 17:16+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-07-19 09:06+0000\n"
"Last-Translator: Loic Nicolle <loic.nicolle@orange.com>\n"
"Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.9.6\n"
"Language-Team: French\n"
msgid "An error occurred authenticating. Please try again later."
msgstr ""
"Une erreur s'est produite pendant l'authentification. Veuillez réessayer "
"ultérieurement."
msgid "Authenticate using"
msgstr "Mode d'authentification"
msgid "Could not find service provider ID on Keystone."
msgstr "Impossible de trouver l'ID du fournisseur de services sur Keystone."
msgid "Domain"
msgstr "Domaine"
msgid "Invalid credentials."
msgstr "Informations d'authentification non valides."
msgid "K2K Federation not setup for this session"
msgstr "La fédération K2K n'a pas été configurée pour cette session"
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr "Aucun backend d'authentification pour gérer les informations fournies."
msgid "Password"
msgstr "Mot de passe"
#, python-format
msgid "Please consider changing your password, it will expire in %s minutes"
msgstr "Merci de changer votre mot de passe, il va expirer dans %s minutes"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "La bascule de projet a échoué pour l'utilisateur \"%(username)s\"."
msgid "Region"
msgstr "Région"
#, python-format
msgid "Service provider authentication failed. %s"
msgstr "L'authentification du fournisseur de services a échoué. %s"
#, python-format
msgid "Switch to Keystone Provider \"%(keystone_provider)s\"successful."
msgstr ""
"Bascule vers le fournisseur Keystone \"%(keystone_provider)s\" réussie."
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "Bascule vers le projet \"%(project_name)s\" réussie. "
msgid "The authentication token issued by the Identity service has expired."
msgstr ""
"Le jeton d'authentification délivré par le service d'Identité a expiré."
msgid "Unable to establish connection to keystone endpoint."
msgstr "Impossible d'établir la connexion avec le endpoint keystone."
msgid "Unable to retrieve authorized domains."
msgstr "Impossible de récupérer les domaines autorisés."
msgid "Unable to retrieve authorized projects."
msgstr "Impossible de récupérer les projets autorisés."
msgid "User Name"
msgstr "Nom d'utilisateur"
msgid "You are not authorized for any projects or domains."
msgstr "Vous n'êtes autorisé sur aucun projet ou domaine."
msgid "You are not authorized for any projects."
msgstr "Vous n'êtes autorisé sur aucun projet."

View File

@ -1,98 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# suhartono <cloudsuhartono@gmail.com>, 2016. #zanata
# suhartono <cloudsuhartono@gmail.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.1.2.dev15\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-04-10 01:40+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-04-11 03:47+0000\n"
"Last-Translator: suhartono <cloudsuhartono@gmail.com>\n"
"Language: id\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.9.6\n"
"Language-Team: Indonesian\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "Terjadi kesalahan otentikasi. Silakan coba lagi nanti."
msgid "Authenticate using"
msgstr "Otentikasi penggunaan"
msgid "Could not find service provider ID on Keystone."
msgstr "Tidak dapat menemukan provider layanan ID di Keystone."
msgid "Domain"
msgstr "Domain"
msgid "Invalid credentials."
msgstr "Kredensial tidak valid."
msgid "K2K Federation not setup for this session"
msgstr "K2K Federation tidak menyiapkan untuk sesi ini"
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr ""
"Tidak ada otentikasi backend dapat ditentukan untuk menangani kredensial "
"yang disediakan."
msgid "Password"
msgstr "Password"
#, python-format
msgid "Please consider changing your password, it will expire in %s minutes"
msgstr ""
"Silakan mempertimbangkan mengubah sandi Anda, inu akan berakhir pada %s menit"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "Switch proyek gagal untuk pengguna \"%(username)s\"."
msgid "Region"
msgstr "Region"
#, python-format
msgid "Service provider authentication failed. %s"
msgstr "Ootentikasi provider layanan gagal. %s"
#, python-format
msgid "Switch to Keystone Provider \"%(keystone_provider)s\"successful."
msgstr "Switch ke Keystone Provider \"%(keystone_provider)s\" berhasil."
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "Switch proyek \"%(project_name)s\" sukses."
msgid "The authentication token issued by the Identity service has expired."
msgstr ""
"Token otentikasi yang dikeluarkan oleh layanan Identity telah berakhir."
msgid "Unable to establish connection to keystone endpoint."
msgstr "Tidak dapat melakukan koneksi ke endpoint keystone."
msgid "Unable to retrieve authorized domains."
msgstr "Tidak dapat mengambil domain yang berwenang."
msgid "Unable to retrieve authorized projects."
msgstr "Tidak dapat mengambil proyek yang berwenang (authorized)"
msgid "User Name"
msgstr "nama pengguna"
msgid "You are not authorized for any projects or domains."
msgstr "Anda tidak berwenang untuk setiap proyek atau domain."
msgid "You are not authorized for any projects."
msgstr "Anda tidak berwenang untuk setiap proyek."

View File

@ -1,76 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Salvatore Davide Rapisarda <sdrapisarda@gmail.com>, 2014
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.1.1.dev1\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-01-25 19:41+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2016-03-26 09:13+0000\n"
"Last-Translator: Remo Mattei <remo@rm.ht>\n"
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.3\n"
"Language-Team: Italian\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "Si è verificato un errore. Riprova più tardi."
msgid "Authenticate using"
msgstr "Usando l'autenticazione "
msgid "Domain"
msgstr "Dominio"
msgid "Invalid credentials."
msgstr "Le credenziali non sono valide "
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr ""
"Non è possibile comunicare con nessuno dei back-end di autenticazione per "
"verificare le credenziali. "
msgid "Password"
msgstr "Password"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr ""
"Il passaggio al progetto non è riuscito per l'utente \"%(username)s\". "
msgid "Region"
msgstr "Regione"
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr ""
"Il passaggio al progetto \"%(project_name)s\" è riuscito con successo. "
msgid "The authentication token issued by the Identity service has expired."
msgstr "Il token di autenticazione che stai usando è scaduto."
msgid "Unable to establish connection to keystone endpoint."
msgstr "Impossibile stabilire una connessione con gli endpoint di keystone. "
msgid "Unable to retrieve authorized projects."
msgstr "Impossibile ottenere l'accesso ai progetti."
msgid "User Name"
msgstr "Nome Utente"
msgid "You are not authorized for any projects or domains."
msgstr "Non sei autorizzato ad entrare a nessuno dei progetti o domini. "
msgid "You are not authorized for any projects."
msgstr "Non sei abilitato a nessun progetto."

View File

@ -1,101 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Akihiro Motoki <amotoki@gmail.com>, 2015
# Shu Muto <shu-mutou@rf.jp.nec.com>, 2015
# ykatabam <ykatabam@redhat.com>, 2015
# ykatabam <ykatabam@redhat.com>, 2015
# Mie Yamamoto <myamamot@redhat.com>, 2016. #zanata
# Yuko Katabami <yukokatabami@gmail.com>, 2016. #zanata
# Yuko Katabami <yukokatabami@gmail.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.5.1.dev5\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-07-27 23:17+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-08-07 09:39+0000\n"
"Last-Translator: Yuko Katabami <yukokatabami@gmail.com>\n"
"Language: ja\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.9.6\n"
"Language-Team: Japanese\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "認証中にエラーが発生しました。後ほどもう一度お試しください。"
msgid "Authenticate using"
msgstr "使用する認証方法"
msgid "Could not find service provider ID on Keystone."
msgstr "Keystone でサービスプロバイダー ID を見つけることができませんでした。"
msgid "Domain"
msgstr "ドメイン"
msgid "Invalid credentials."
msgstr "無効な認証情報です。"
msgid "K2K Federation not setup for this session"
msgstr "このセッションには K2K フェデレーションは設定されていません。"
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr "指定された認証情報を処理する認証バックエンドが決定できませんでした。"
msgid "Password"
msgstr "パスワード"
#, python-format
msgid "Please consider changing your password, it will expire in %s minutes"
msgstr ""
"パスワードの変更をお勧めします。今のパスワードはあと %s 分で無効になります。"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "ユーザー \"%(username)s\" のプロジェクト切り替えに失敗しました。"
msgid "Region"
msgstr "リージョン"
#, python-format
msgid "Service provider authentication failed. %s"
msgstr "サービスプロバイダーの認証に失敗しました。%s"
#, python-format
msgid "Switch to Keystone Provider \"%(keystone_provider)s\"successful."
msgstr ""
"Keystone プロバイダー \"%(keystone_provider)s\" への切り替えが正常に完了しま"
"した。"
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "プロジェクト \"%(project_name)s\" へ正常に切り替えました。"
msgid "The authentication token issued by the Identity service has expired."
msgstr "Identity サービスにより発行された認証トークンの期限が切れました。"
msgid "Unable to establish connection to keystone endpoint."
msgstr "Keystone エンドポイントへの接続を確立できません。"
msgid "Unable to retrieve authorized domains."
msgstr "認証されたドメインを取得できません。"
msgid "Unable to retrieve authorized projects."
msgstr "権限を持っているプロジェクトの情報を取得できません。"
msgid "User Name"
msgstr "ユーザー名"
msgid "You are not authorized for any projects or domains."
msgstr "どのプロジェクトやドメインに対しても権限がありません。"
msgid "You are not authorized for any projects."
msgstr "どのプロジェクトに対しても権限がありません。"

View File

@ -1,98 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Ian Y. Choi <ianyrchoi@gmail.com>, 2015
# Sungjin Kang <potopro@gmail.com>, 2015
# Andrea Young Oak Li <youli@redhat.com>, 2016. #zanata
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Jun-Sik Shin <jsshin@smartx.kr>, 2017. #zanata
# Sungjin Kang <gang.sungjin@gmail.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.2.1.dev2\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-06-07 17:46+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-06-08 01:53+0000\n"
"Last-Translator: Jun-Sik Shin <jsshin@smartx.kr>\n"
"Language: ko-KR\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.9.6\n"
"Language-Team: Korean (South Korea)\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "인증 중 오류가 발생했습니다. 잠시 후 다시 시도하세요."
msgid "Authenticate using"
msgstr "인증 방법"
msgid "Could not find service provider ID on Keystone."
msgstr "Keystone 에서 서비스 프로바이더 ID 를 찾지 못하였습니다."
msgid "Domain"
msgstr "도메인"
msgid "Invalid credentials."
msgstr "올바르지 않은 인증정보입니다."
msgid "K2K Federation not setup for this session"
msgstr "이 세션에는 K2K Federation 이 설정되지 않았습니다."
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr ""
"제공된 인증정보에 대한 처리를 할 수 있는 인증 백엔드가 존재하지 않습니다."
msgid "Password"
msgstr "암호"
#, python-format
msgid "Please consider changing your password, it will expire in %s minutes"
msgstr "암호는 %s 분 후에 만료되므로 변경해 주시기 바랍니다."
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "사용자 \"%(username)s\" 에 대한 프로젝트 전환에 실패했습니다."
msgid "Region"
msgstr "지역"
#, python-format
msgid "Service provider authentication failed. %s"
msgstr "서비스 프로바이더 인증에 실패했습니다. %s"
#, python-format
msgid "Switch to Keystone Provider \"%(keystone_provider)s\"successful."
msgstr "Keystone 프로바이더 \"%(keystone_provider)s\" 로 변경하였습니다."
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "프로젝트 \"%(project_name)s\" 로 전환에 성공하였습니다."
msgid "The authentication token issued by the Identity service has expired."
msgstr "Identity 서비스에서 발급한 인증 토큰이 만료되었습니다."
msgid "Unable to establish connection to keystone endpoint."
msgstr "Keystone 엔드포인트에 접속할 수 없습니다."
msgid "Unable to retrieve authorized domains."
msgstr "인증된 도메인을 찾지 못했습니다."
msgid "Unable to retrieve authorized projects."
msgstr "인증된 프로젝트를 가져올 수 없습니다."
msgid "User Name"
msgstr "사용자 이름"
msgid "You are not authorized for any projects or domains."
msgstr "프로젝트나 도메인에 대한 권한이 없습니다."
msgid "You are not authorized for any projects."
msgstr "모든 프로젝트에 대한 권한이 없습니다."

View File

@ -1,52 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Evelijn Saaltink <evelijnsaaltink@gmail.com>, 2015
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.1.1.dev1\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-01-25 19:41+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2015-08-17 09:33+0000\n"
"Last-Translator: Evelijn Saaltink <evelijnsaaltink@gmail.com>\n"
"Language: nl-NL\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.3\n"
"Language-Team: Dutch (Netherlands)\n"
msgid "An error occurred authenticating. Please try again later."
msgstr ""
"Er is een fout opgetreden bij de verificatie. Probeert u het later nog eens."
msgid "Authenticate using"
msgstr "Gebruik authentificeren"
msgid "Domain"
msgstr "Domein"
msgid "Password"
msgstr "Wachtwoord"
msgid "Region"
msgstr "Regio"
msgid "The authentication token issued by the Identity service has expired."
msgstr ""
"De door de identiteitsdienst verstrekte authenticatietoken is verlopen."
msgid "Unable to retrieve authorized projects."
msgstr "Niet in staat om de geauthentificeerde projecten op te halen."
msgid "User Name"
msgstr "Gebruikersnaam"
msgid "You are not authorized for any projects."
msgstr "U bent voor geen enkel project gemachtigd."

View File

@ -1,71 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.1.1.dev1\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-01-25 19:41+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2015-12-28 03:33+0000\n"
"Last-Translator: A S Alam <aalam@fedoraproject.org>\n"
"Language: pa-IN\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.3\n"
"Language-Team: Punjabi (India)\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "ਪ੍ਰਮਾਣਿਕਤਾ ਵੇਲੇ ਇੱਕ ਗਲਤੀ ਵਾਪਰੀ। ਕਿਰਪਾ ਕਰ ਕੇ ਬਾਅਦ ਵਿੱਚ ਮੁੜ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"
msgid "Authenticate using"
msgstr "ਇਹ ਵਰਤ ਕੇ ਪ੍ਰਮਾਣਿਤ ਕਰੋ"
msgid "Domain"
msgstr "ਡੋਮੇਨ"
msgid "Invalid credentials."
msgstr "ਗਲਤ ਵੇਰਵੇ।"
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr "ਦਿੱਤੀਆਂ ਸਨਦਾਂ ਨੂੰ ਨਿਪਟਾਉਣ ਲਈ ਕੋਈ ਪਰਮਾਣਕਿਤਾ ਬੈਕਐਂਡ ਪਤਾ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ।"
msgid "Password"
msgstr "ਪਾਸਵਰਡ"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "\"%(username)s\" ਵਰਤੋਂ ਕਾਰ ਲਈ ਪ੍ਰੋਜੈਕਟ ਬਦਲਣਾ ਫੇਲ੍ਹ ਹੈ।"
msgid "Region"
msgstr "ਖੇਤਰ"
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "\"%(project_name)s\" ਪ੍ਰੋਜੈਕਟ ਲਈ ਬਦਲਣਾ ਕਾਮਯਾਬ ਹੈ।"
msgid "The authentication token issued by the Identity service has expired."
msgstr "ਪਛਾਣ ਸੇਵਾ ਵਲੋਂ ਜਾਰੀ ਕੀਤੇ ਪਰਮਾਣਕਿਤਾ ਟੋਕਨ ਦੀ ਮਿਆਦ ਪੁੱਗ ਚੁੱਕੀ ਹੈ।"
msgid "Unable to establish connection to keystone endpoint."
msgstr "ਕੀਅਸਟੋਨ ਅੰਤ ਬਿੰਦੂ ਨਾਲ ਸੰਬੰਧ ਸਥਾਪਤ ਕਰਨ ਤੋਂ ਅਸਮਰੱਥ।"
msgid "Unable to retrieve authorized projects."
msgstr "ਅਧਿਕਾਰਤ ਪ੍ਰੋਜੈਕਟਾਂ ਨੂੰ ਪ੍ਰਾਪਤ ਕਰਨ ਤੋਂ ਅਸਮਰੱਥ।"
msgid "User Name"
msgstr "ਵਰਤੋਂਕਾਰ ਨਾਂ"
msgid "You are not authorized for any projects or domains."
msgstr "ਤੁਸੀਂ ਕਿਸੇ ਵੀ ਪ੍ਰੋਜੈਕਟ ਜਾਂ ਡੋਮੇਨ ਲਈ ਅਧਿਕਾਰਿਤ ਨਹੀਂ ਹੋ।"
msgid "You are not authorized for any projects."
msgstr "ਤੁਸੀਂ ਕੋਈ ਵੀ ਪ੍ਰਾਜੈਕਟਾਂ ਲਈ ਅਧਿਕਾਰਤ ਨਹੀਂ ਹੋ।"

View File

@ -1,75 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Łukasz Jernaś <deejay1@srem.org>, 2015
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.1.1.dev1\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-01-25 19:41+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2016-03-21 09:03+0000\n"
"Last-Translator: Łukasz Jernas <deejay1@srem.org>\n"
"Language: pl-PL\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.3\n"
"Language-Team: Polish (Poland)\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "Wystąpił błąd w trakcie uwierzytelniania. Proszę spróbować później."
msgid "Authenticate using"
msgstr "Uwierzytelnij się pużywając"
msgid "Domain"
msgstr "Domena"
msgid "Invalid credentials."
msgstr "Błędne dane logowania."
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr ""
"Nie można określić silnika uwierzytelniania, który by mógł obsłużyć podane "
"dane uwierzytelniające."
msgid "Password"
msgstr "Hasło"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "Nie można przełączyć projektu dla użytkownika „%(username)s”."
msgid "Region"
msgstr "Region"
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "Przełączono na projekt „%(project_name)s”."
msgid "The authentication token issued by the Identity service has expired."
msgstr "Token uwierzytelniania wydany przez usługę uwierzytelniania wygasł."
msgid "Unable to establish connection to keystone endpoint."
msgstr "Nie można nawiązać połączenia z usługą keystone."
msgid "Unable to retrieve authorized projects."
msgstr "Nie można pobrać uwierzytelnionych projektów."
msgid "User Name"
msgstr "Nazwa użytkownika"
msgid "You are not authorized for any projects or domains."
msgstr "Brak upoważnień dla projektów lub domen."
msgid "You are not authorized for any projects."
msgstr "Nie upoważniono do żadnego projektu."

View File

@ -1,100 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Andre Campos Bezerra <andrecbezerra@gmail.com>, 2015
# Gabriel Wainer, 2015
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Fernando Pimenta <fernando.c.pimenta@gmail.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.2.1.dev5\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-06-28 12:08+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-06-28 12:37+0000\n"
"Last-Translator: Fernando Pimenta <fernando.c.pimenta@gmail.com>\n"
"Language: pt-BR\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.9.6\n"
"Language-Team: Portuguese (Brazil)\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "Um erro ocorreu autenticando. Por favor tente novamente mais tarde."
msgid "Authenticate using"
msgstr "Autenticar usando"
msgid "Could not find service provider ID on Keystone."
msgstr "Não consegui encontrar o ID do provedor de serviço no Keystone."
msgid "Domain"
msgstr "Domínio"
msgid "Invalid credentials."
msgstr "Credencial Inválida"
msgid "K2K Federation not setup for this session"
msgstr "K2K Federation não está configurada para esta sessão"
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr ""
"Nenhuma autenticação poderia ser determinada para lidar com as credenciais "
"fornecidas."
msgid "Password"
msgstr "Senha"
#, python-format
msgid "Please consider changing your password, it will expire in %s minutes"
msgstr ""
"Por favor, considere a alteração de sua senha, ela irá expirar em %s minutos"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "A troca de projeto falhou para o usuário \"%(username)s\"."
msgid "Region"
msgstr "Região"
#, python-format
msgid "Service provider authentication failed. %s"
msgstr "Autenticação do provedor de serviço falhou. %s"
#, python-format
msgid "Switch to Keystone Provider \"%(keystone_provider)s\"successful."
msgstr ""
"Troca para o Provedor Keystone \"%(keystone_provider)s\" realizada com "
"sucesso."
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "Troca para o projeto \"%(project_name)s\" realizada com sucesso."
msgid "The authentication token issued by the Identity service has expired."
msgstr "O token de autenticação emitido pelo serviço de identidade expirou."
msgid "Unable to establish connection to keystone endpoint."
msgstr "Não foi possível estabelecer conexão com o endpoint do Keystone."
msgid "Unable to retrieve authorized domains."
msgstr "Não foi possível recuperar domínios autorizados."
msgid "Unable to retrieve authorized projects."
msgstr "Não foi possível obter os projetos autorizados."
msgid "User Name"
msgstr "Nome do Usuário"
msgid "You are not authorized for any projects or domains."
msgstr "Você não está autorizado para nenhum projeto ou domínio."
msgid "You are not authorized for any projects."
msgstr "Você não está autorizado para nenhum projeto."

View File

@ -1,87 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Alexander Vasiliev <avasiliev@asdco.ru>, 2015
# Fedor Tarasenko <feodor.tarasenko@gmail.com>, 2015
# Ilya Alekseyev <ilyaalekseyev@acm.org>, 2015
# Ilya Shakhat <shakhat@gmail.com>, 2015
# Nikita Burtsev, 2015
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Artem <amikhalev90@gmail.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.1.1.dev1\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-01-25 19:41+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-01-23 12:43+0000\n"
"Last-Translator: Artem <amikhalev90@gmail.com>\n"
"Language: ru\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3);\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.3\n"
"Language-Team: Russian\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "Произошла ошибка аутентификации. Пожалуйста, повторите попытку позже."
msgid "Authenticate using"
msgstr "Аутентификация с использованием"
msgid "Could not find service provider ID on Keystone."
msgstr "Не удалось найти ИД поставщика служб в Keystone."
msgid "Domain"
msgstr "Домен"
msgid "Invalid credentials."
msgstr "Неправильные учётные данные."
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr ""
"Невозможно определить backend для обработки предоставленных учётных данных."
msgid "Password"
msgstr "Пароль"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "Не удалось переключить проект для пользователя \"%(username)s\"."
msgid "Region"
msgstr "Регион"
#, python-format
msgid "Service provider authentication failed. %s"
msgstr "Неудачная аутентикация поставщика службы. %s"
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "Переключение на проект \"%(project_name)s\" выполнено успешно."
msgid "The authentication token issued by the Identity service has expired."
msgstr "Время действия токена, выданного сервисом идентификации, истекло."
msgid "Unable to establish connection to keystone endpoint."
msgstr "Невозможно установить соединение с точкой доступа keystone."
msgid "Unable to retrieve authorized projects."
msgstr "Невозможно получить авторизованные проекты"
msgid "User Name"
msgstr "Имя пользователя"
msgid "You are not authorized for any projects or domains."
msgstr "Вы не авторизованы ни в одном проекте или домене."
msgid "You are not authorized for any projects."
msgstr "Вы не авторизованы ни в одном проекте."

View File

@ -1,99 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# İşbaran Akçayır <isbaran@gmail.com>, 2015
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# işbaran akçayır <isbaran@gmail.com>, 2017. #zanata
# yasemin demiral <yasemin.demiral@tubitak.gov.tr>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.5.1.dev8\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-08-20 11:30+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-08-21 08:33+0000\n"
"Last-Translator: yasemin demiral <yasemin.demiral@tubitak.gov.tr>\n"
"Language: tr-TR\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.9.6\n"
"Language-Team: Turkish (Turkey)\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "Bilinmeyen bir hata oluştu. Lütfen daha sonra tekrar deneyin."
msgid "Authenticate using"
msgstr "Kimlik doğrulama"
msgid "Could not find service provider ID on Keystone."
msgstr "Keystone için servis sağlayıcı ID'si bulunamadı."
msgid "Domain"
msgstr "Domain"
msgid "Invalid credentials."
msgstr "Geçersiz giriş bilgileri."
msgid "K2K Federation not setup for this session"
msgstr "K2K Birleşimi bu oturum için kurulmamış"
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr ""
"Sağlanan kimlik bilgilerini işleyecek kimlik doğrulama uygulaması tespit "
"edilemedi."
msgid "Password"
msgstr "Parola"
#, python-format
msgid "Please consider changing your password, it will expire in %s minutes"
msgstr ""
"Lütfen parolanızı değiştirmeyin düşünün, %s dakikada süresini dolduracak"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "\"%(username)s\" kullanıcısı için proje geçişi başarısız."
msgid "Region"
msgstr "Bölge"
#, python-format
msgid "Service provider authentication failed. %s"
msgstr "Servis sağlayıcı kimlik doğrulama başarısız. %s"
#, python-format
msgid "Switch to Keystone Provider \"%(keystone_provider)s\"successful."
msgstr "\"%(keystone_provider)s\" Keystone Sağlayıcısına geçiş başarılı."
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "\"%(project_name)s\" projesine geçiş başarılı."
msgid "The authentication token issued by the Identity service has expired."
msgstr ""
"Kimlik servisi tarafından verilen kimlik doğrulama belirtecinin süresi doldu."
msgid "Unable to establish connection to keystone endpoint."
msgstr "Keystone uç noktasına bağlantı kurulamadı."
msgid "Unable to retrieve authorized domains."
msgstr "Yetkili alanlar alınamadı."
msgid "Unable to retrieve authorized projects."
msgstr "Yetkiniz bulunan projeler alınamadı."
msgid "User Name"
msgstr "Kullanıcı Adı"
msgid "You are not authorized for any projects or domains."
msgstr "Herhangi bir proje veya domain için yetkili değilsiniz."
msgid "You are not authorized for any projects."
msgstr "Herhangi bir proje için yetkili değilsiniz."

View File

@ -1,50 +0,0 @@
# Ukrainian translations for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: Horizon\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2015-08-04 06:25+0000\n"
"PO-Revision-Date: 2015-07-16 01:34+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
"Language-Team: Ukrainian (http://www.transifex.com/openstack/horizon/"
"language/uk/)\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.0\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "Помилка у автентифікації. Будь-ласка, спробуйте пізніше."
msgid "Domain"
msgstr "Домен"
msgid "Password"
msgstr "Пароль"
msgid "Region"
msgstr "Регіон"
msgid "The authentication token issued by the Identity service has expired."
msgstr ""
"Автентифікаційний токен, виданий Ідентифікаційним сервісом, більше не "
"дійсний."
msgid "Unable to authenticate to any available projects."
msgstr "Неможливо автентифікуватися щодо жодного проекту."
msgid "Unable to retrieve authorized projects."
msgstr "Неможливо отримати авторизовані проекти."
msgid "User Name"
msgstr "Ім’я Користувача"
msgid "You are not authorized for any projects."
msgstr "Ви не авторизовані до жодного проекту."

View File

@ -1,99 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Allerson Yao, 2015
# johnwoo_lee <lijiangsheng1@gmail.com>, 2015
# LIU Yulong <dragon889@163.com>, 2015
# Ying Chun Guo <daisy.ycguo@gmail.com>, 2015
# 刘俊朋 <liujunpeng@inspur.com>, 2015
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Bin <liubin@glab.cn>, 2017. #zanata
# liujunpeng <liujunpeng@inspur.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.4.1.dev6\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-07-20 16:28+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-07-24 02:52+0000\n"
"Last-Translator: Bin <liubin@glab.cn>\n"
"Language: zh-CN\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.9.6\n"
"Language-Team: Chinese (China)\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "认证出现错误。请稍后重试。"
msgid "Authenticate using"
msgstr "使用认证"
msgid "Could not find service provider ID on Keystone."
msgstr "在Keystone上不能找到服务提供者ID。"
msgid "Domain"
msgstr "域"
msgid "Invalid credentials."
msgstr "凭据无效."
msgid "K2K Federation not setup for this session"
msgstr "会话没有建立K2K联邦"
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr "没有认证后端可处理提供的凭据。"
msgid "Password"
msgstr "密码"
#, python-format
msgid "Please consider changing your password, it will expire in %s minutes"
msgstr "请考虑修改你的密码,它将于%s分钟后过期"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "为用户“%(username)s”切换项目失败"
msgid "Region"
msgstr "区域"
#, python-format
msgid "Service provider authentication failed. %s"
msgstr "服务提供者认证失败。%s"
#, python-format
msgid "Switch to Keystone Provider \"%(keystone_provider)s\"successful."
msgstr "成功切换到 Keystone 提供者\"%(keystone_provider)s\"."
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "成功切换到项目\"%(project_name)s\""
msgid "The authentication token issued by the Identity service has expired."
msgstr "身份认证令牌已过期。"
msgid "Unable to establish connection to keystone endpoint."
msgstr "无法连接keystone端点。"
msgid "Unable to retrieve authorized domains."
msgstr "无法获取授权域。"
msgid "Unable to retrieve authorized projects."
msgstr "无法获取授权的项目。"
msgid "User Name"
msgstr "用户名"
msgid "You are not authorized for any projects or domains."
msgstr "您未被授权访问任何项目或域。"
msgid "You are not authorized for any projects."
msgstr "您未被授权访问任何项目。"

View File

@ -1,90 +0,0 @@
# Translations template for django_openstack_auth.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the
# django_openstack_auth project.
#
# Translators:
# Zhang Xiaowei <zero00072@gmail.com>, 2015
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Ching Kuo <gene@openstack.org>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: django_openstack_auth 3.1.1.dev12\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-02-02 16:33+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-02-02 07:53+0000\n"
"Last-Translator: Ching Kuo <gene@openstack.org>\n"
"Language: zh-TW\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.3\n"
"Language-Team: Chinese (Taiwan)\n"
msgid "An error occurred authenticating. Please try again later."
msgstr "認證發生錯誤。請稍後再試。"
msgid "Authenticate using"
msgstr "認證使用"
msgid "Could not find service provider ID on Keystone."
msgstr "在Keystone找不到服務提供者ID"
msgid "Domain"
msgstr "地域"
msgid "Invalid credentials."
msgstr "無效的認證。"
msgid "K2K Federation not setup for this session"
msgstr "這個session並未設定K2K聯合"
msgid ""
"No authentication backend could be determined to handle the provided "
"credentials."
msgstr "沒有選擇認證後端來處理提供的憑證。"
msgid "Password"
msgstr "密碼"
#, python-format
msgid "Project switch failed for user \"%(username)s\"."
msgstr "使用者 \"%(username)s\" 的專案切換失敗。"
msgid "Region"
msgstr "區域"
#, python-format
msgid "Service provider authentication failed. %s"
msgstr "服務來源認證錯誤。%s"
#, python-format
msgid "Switch to Keystone Provider \"%(keystone_provider)s\"successful."
msgstr "成功切換認證來源到 \"%(keystone_provider)s\""
#, python-format
msgid "Switch to project \"%(project_name)s\" successful."
msgstr "成功切換至專案 \"%(project_name)s\"。"
msgid "The authentication token issued by the Identity service has expired."
msgstr "認證伺服器發佈的門票已經過期。"
msgid "Unable to establish connection to keystone endpoint."
msgstr "無法建立與 Keystone 端點的連線。"
msgid "Unable to retrieve authorized domains."
msgstr "無法獲得認證過的地域。"
msgid "Unable to retrieve authorized projects."
msgstr "無法取回已授權的專案。"
msgid "User Name"
msgstr "用戶名稱"
msgid "You are not authorized for any projects or domains."
msgstr "您未獲授權對任何專案或網域執行動作。"
msgid "You are not authorized for any projects."
msgstr "沒有授權您任何專案。"

View File

@ -1,18 +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 the User model in here so Django can find it
from openstack_auth.user import User
__all__ = ['User']

View File

@ -1,22 +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 openstack_auth.plugin.base import BasePlugin
from openstack_auth.plugin.k2k import K2KAuthPlugin
from openstack_auth.plugin.password import PasswordPlugin
from openstack_auth.plugin.token import TokenPlugin
__all__ = ['BasePlugin',
'PasswordPlugin',
'TokenPlugin',
'K2KAuthPlugin']

View File

@ -1,241 +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 abc
import logging
from django.utils.translation import ugettext_lazy as _
from keystoneauth1 import exceptions as keystone_exceptions
from keystoneclient.v2_0 import client as v2_client
from keystoneclient.v3 import client as v3_client
import six
from openstack_auth import exceptions
from openstack_auth import utils
LOG = logging.getLogger(__name__)
__all__ = ['BasePlugin']
@six.add_metaclass(abc.ABCMeta)
class BasePlugin(object):
"""Base plugin to provide ways to log in to dashboard.
Provides a framework for keystoneclient plugins that can be used with the
information provided to return an unscoped token.
"""
@abc.abstractmethod
def get_plugin(self, auth_url=None, **kwargs):
"""Create a new plugin to attempt to authenticate.
Given the information provided by the login providers attempt to create
an authentication plugin that can be used to authenticate the user.
If the provided login information does not contain enough information
for this plugin to proceed then it should return None.
:param str auth_url: The URL to authenticate against.
:returns: A plugin that will be used to authenticate or None if the
plugin cannot authenticate with the data provided.
:rtype: keystoneclient.auth.BaseAuthPlugin
"""
return None
@property
def keystone_version(self):
"""The Identity API version as specified in the settings file."""
return utils.get_keystone_version()
def list_projects(self, session, auth_plugin, auth_ref=None):
"""List the projects that are accessible to this plugin.
Query the keystone server for all projects that this authentication
token can be rescoped to.
This function is overrideable by plugins if they use a non-standard
mechanism to determine projects.
:param session: A session object for communication:
:type session: keystoneclient.session.Session
:param auth_plugin: The auth plugin returned by :py:meth:`get_plugin`.
:type auth_plugin: keystoneclient.auth.BaseAuthPlugin
:param auth_ref: The current authentication data. This is optional as
future auth plugins may not have auth_ref data and all
the required information should be available via the
auth_plugin.
:type auth_ref: keystoneclient.access.AccessInfo` or None.
:raises: exceptions.KeystoneAuthException on lookup failure.
:returns: A list of projects. This currently accepts returning both v2
or v3 keystoneclient projects objects.
"""
try:
if self.keystone_version >= 3:
client = v3_client.Client(session=session, auth=auth_plugin)
if auth_ref.is_federated:
return client.federation.projects.list()
else:
return client.projects.list(user=auth_ref.user_id)
else:
client = v2_client.Client(session=session, auth=auth_plugin)
return client.tenants.list()
except (keystone_exceptions.ClientException,
keystone_exceptions.AuthorizationFailure):
msg = _('Unable to retrieve authorized projects.')
raise exceptions.KeystoneAuthException(msg)
def list_domains(self, session, auth_plugin, auth_ref=None):
try:
if self.keystone_version >= 3:
client = v3_client.Client(session=session, auth=auth_plugin)
return client.auth.domains()
else:
return []
except (keystone_exceptions.ClientException,
keystone_exceptions.AuthorizationFailure):
msg = _('Unable to retrieve authorized domains.')
raise exceptions.KeystoneAuthException(msg)
def get_access_info(self, keystone_auth):
"""Get the access info from an unscoped auth
This function provides the base functionality that the
plugins will use to authenticate and get the access info object.
:param keystone_auth: keystoneauth1 identity plugin
:raises: exceptions.KeystoneAuthException on auth failure
:returns: keystoneclient.access.AccessInfo
"""
session = utils.get_session()
try:
unscoped_auth_ref = keystone_auth.get_access(session)
except keystone_exceptions.ConnectFailure as exc:
LOG.error(str(exc))
msg = _('Unable to establish connection to keystone endpoint.')
raise exceptions.KeystoneAuthException(msg)
except (keystone_exceptions.Unauthorized,
keystone_exceptions.Forbidden,
keystone_exceptions.NotFound) as exc:
LOG.debug(str(exc))
raise exceptions.KeystoneAuthException(_('Invalid credentials.'))
except (keystone_exceptions.ClientException,
keystone_exceptions.AuthorizationFailure) as exc:
msg = _("An error occurred authenticating. "
"Please try again later.")
LOG.debug(str(exc))
raise exceptions.KeystoneAuthException(msg)
return unscoped_auth_ref
def get_project_scoped_auth(self, unscoped_auth, unscoped_auth_ref,
recent_project=None):
"""Get the project scoped keystone auth and access info
This function returns a project scoped keystone token plugin
and AccessInfo object.
:param unscoped_auth: keystone auth plugin
:param unscoped_auth_ref: keystoneclient.access.AccessInfo` or None.
:param recent_project: project that we should try to scope to
:return: keystone token auth plugin, AccessInfo object
"""
auth_url = unscoped_auth.auth_url
session = utils.get_session()
projects = self.list_projects(
session, unscoped_auth, unscoped_auth_ref)
# Attempt to scope only to enabled projects
projects = [project for project in projects if project.enabled]
# if a most recent project was found, try using it first
if recent_project:
for pos, project in enumerate(projects):
if project.id == recent_project:
# move recent project to the beginning
projects.pop(pos)
projects.insert(0, project)
break
scoped_auth = None
scoped_auth_ref = None
for project in projects:
token = unscoped_auth_ref.auth_token
scoped_auth = utils.get_token_auth_plugin(auth_url,
token=token,
project_id=project.id)
try:
scoped_auth_ref = scoped_auth.get_access(session)
except (keystone_exceptions.ClientException,
keystone_exceptions.AuthorizationFailure):
LOG.info('Attempted scope to project %s failed, will attempt'
'to scope to another project.' % project.name)
pass
else:
break
return scoped_auth, scoped_auth_ref
def get_domain_scoped_auth(self, unscoped_auth, unscoped_auth_ref,
domain_name=None):
"""Get the domain scoped keystone auth and access info
This function returns a domain scoped keystone token plugin
and AccessInfo object.
:param unscoped_auth: keystone auth plugin
:param unscoped_auth_ref: keystoneclient.access.AccessInfo` or None.
:param domain_name: domain that we should try to scope to
:return: keystone token auth plugin, AccessInfo object
"""
session = utils.get_session()
auth_url = unscoped_auth.auth_url
if utils.get_keystone_version() < 3:
return None, None
if domain_name:
domains = [domain_name]
else:
domains = self.list_domains(session,
unscoped_auth,
unscoped_auth_ref)
domains = [domain.name for domain in domains if domain.enabled]
# domain support can require domain scoped tokens to perform
# identity operations depending on the policy files being used
# for keystone.
domain_auth = None
domain_auth_ref = None
for domain_name in domains:
token = unscoped_auth_ref.auth_token
domain_auth = utils.get_token_auth_plugin(
auth_url,
token,
domain_name=domain_name)
try:
domain_auth_ref = domain_auth.get_access(session)
except (keystone_exceptions.ClientException,
keystone_exceptions.AuthorizationFailure):
LOG.info('Attempted scope to domain %s failed, will attempt'
'to scope to another domain.' % domain_name)
pass
else:
if len(domains) > 1:
LOG.info("More than one valid domain found for user %s,"
" scoping to %s" %
(unscoped_auth_ref.user_id, domain_name))
break
return domain_auth, domain_auth_ref

View File

@ -1,107 +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 django.conf import settings
from django.utils.translation import ugettext_lazy as _
from keystoneauth1.identity import v3 as v3_auth
from openstack_auth import exceptions
from openstack_auth.plugin import base
from openstack_auth import utils
LOG = logging.getLogger(__name__)
__all__ = ['K2KAuthPlugin']
class K2KAuthPlugin(base.BasePlugin):
def get_plugin(self, service_provider=None, auth_url=None, plugins=None,
**kwargs):
"""Authenticate using keystone to keystone federation.
This plugin uses other v3 plugins to authenticate a user to a
identity provider in order to authenticate the user to a service
provider
:param service_provider: service provider ID
:param auth_url: Keystone auth url
:param plugins: list of openstack_auth plugins to check
:returns Keystone2Keystone keystone auth plugin
"""
# Avoid mutable default arg for plugins
plugins = plugins or []
# service_provider being None prevents infinite recursion
if utils.get_keystone_version() < 3 or not service_provider:
return None
keystone_idp_id = getattr(settings, 'KEYSTONE_PROVIDER_IDP_ID',
'localkeystone')
if service_provider == keystone_idp_id:
return None
for plugin in plugins:
unscoped_idp_auth = plugin.get_plugin(plugins=plugins,
auth_url=auth_url, **kwargs)
if unscoped_idp_auth:
break
else:
LOG.debug('Could not find base authentication backend for '
'K2K plugin with the provided credentials.')
return None
idp_exception = None
scoped_idp_auth = None
unscoped_auth_ref = base.BasePlugin.get_access_info(
self, unscoped_idp_auth)
try:
scoped_idp_auth, __ = self.get_project_scoped_auth(
unscoped_idp_auth, unscoped_auth_ref)
except exceptions.KeystoneAuthException as idp_excp:
idp_exception = idp_excp
if not scoped_idp_auth or idp_exception:
msg = 'Identity provider authentication Failed.'
raise exceptions.KeystoneAuthException(msg)
session = utils.get_session()
if scoped_idp_auth.get_sp_auth_url(session, service_provider) is None:
msg = _('Could not find service provider ID on Keystone.')
raise exceptions.KeystoneAuthException(msg)
unscoped_auth = v3_auth.Keystone2Keystone(
base_plugin=scoped_idp_auth,
service_provider=service_provider)
return unscoped_auth
def get_access_info(self, unscoped_auth):
"""Get the access info object
We attempt to get the auth ref. If it fails and if the K2K auth plugin
was being used then we will prepend a message saying that the error was
on the service provider side.
:param: unscoped_auth: Keystone auth plugin for unscoped user
:returns: keystoneclient.access.AccessInfo object
"""
try:
unscoped_auth_ref = base.BasePlugin.get_access_info(
self, unscoped_auth)
except exceptions.KeystoneAuthException as excp:
msg = _('Service provider authentication failed. %s')
raise exceptions.KeystoneAuthException(msg % str(excp))
return unscoped_auth_ref

View File

@ -1,51 +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 keystoneauth1.identity import v2 as v2_auth
from keystoneauth1.identity import v3 as v3_auth
from openstack_auth.plugin import base
from openstack_auth import utils
LOG = logging.getLogger(__name__)
__all__ = ['PasswordPlugin']
class PasswordPlugin(base.BasePlugin):
"""Authenticate against keystone given a username and password.
This is the default login mechanism. Given a username and password inputted
from a login form returns a v2 or v3 keystone Password plugin for
authentication.
"""
def get_plugin(self, auth_url=None, username=None, password=None,
user_domain_name=None, **kwargs):
if not all((auth_url, username, password)):
return None
LOG.debug('Attempting to authenticate for %s', username)
if utils.get_keystone_version() >= 3:
return v3_auth.Password(auth_url=auth_url,
username=username,
password=password,
user_domain_name=user_domain_name,
unscoped=True)
else:
return v2_auth.Password(auth_url=auth_url,
username=username,
password=password)

View File

@ -1,41 +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 keystoneauth1.identity import v2 as v2_auth
from keystoneauth1.identity import v3 as v3_auth
from openstack_auth.plugin import base
from openstack_auth import utils
__all__ = ['TokenPlugin']
class TokenPlugin(base.BasePlugin):
"""Authenticate against keystone with an existing token."""
def get_plugin(self, auth_url=None, token=None, project_id=None,
**kwargs):
if not all((auth_url, token)):
return None
if utils.get_keystone_version() >= 3:
return v3_auth.Token(auth_url=auth_url,
token=token,
project_id=project_id,
reauthenticate=False)
else:
return v2_auth.Token(auth_url=auth_url,
token=token,
tenant_id=project_id,
reauthenticate=False)

View File

@ -1,231 +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.
"""Policy engine for openstack_auth"""
import logging
import os.path
from django.conf import settings
from oslo_config import cfg
from oslo_policy import opts as policy_opts
from oslo_policy import policy
from openstack_auth import user as auth_user
from openstack_auth import utils as auth_utils
LOG = logging.getLogger(__name__)
_ENFORCER = None
_BASE_PATH = getattr(settings, 'POLICY_FILES_PATH', '')
def _get_policy_conf(policy_file, policy_dirs=None):
conf = cfg.ConfigOpts()
# Passing [] is required. Otherwise oslo.config looks up sys.argv.
conf([])
policy_opts.set_defaults(conf)
policy_file = os.path.join(_BASE_PATH, policy_file)
conf.set_default('policy_file', policy_file, 'oslo_policy')
# Policy Enforcer has been updated to take in a policy directory
# as a config option. However, the default value in is set to
# ['policy.d'] which causes the code to break. Set the default
# value to empty list for now.
if policy_dirs is None:
policy_dirs = []
policy_dirs = [os.path.join(_BASE_PATH, policy_dir)
for policy_dir in policy_dirs]
conf.set_default('policy_dirs', policy_dirs, 'oslo_policy')
return conf
def _get_enforcer():
global _ENFORCER
if not _ENFORCER:
_ENFORCER = {}
policy_files = getattr(settings, 'POLICY_FILES', {})
policy_dirs = getattr(settings, 'POLICY_DIRS', {})
for service in policy_files.keys():
conf = _get_policy_conf(policy_file=policy_files[service],
policy_dirs=policy_dirs.get(service, []))
enforcer = policy.Enforcer(conf)
# Ensure enforcer.policy_path is populated.
enforcer.load_rules()
if os.path.isfile(enforcer.policy_path):
LOG.debug("adding enforcer for service: %s" % service)
_ENFORCER[service] = enforcer
else:
LOG.warning("policy file for service: %s not found at %s" %
(service, enforcer.policy_path))
return _ENFORCER
def reset():
global _ENFORCER
_ENFORCER = None
def check(actions, request, target=None):
"""Check user permission.
Check if the user has permission to the action according
to policy setting.
:param actions: list of scope and action to do policy checks on,
the composition of which is (scope, action). Multiple actions
are treated as a logical AND.
* scope: service type managing the policy for action
* action: string representing the action to be checked
this should be colon separated for clarity.
i.e.
| compute:create_instance
| compute:attach_volume
| volume:attach_volume
for a policy action that requires a single action, actions
should look like
| "(("compute", "compute:create_instance"),)"
for a multiple action check, actions should look like
| "(("identity", "identity:list_users"),
| ("identity", "identity:list_roles"))"
:param request: django http request object. If not specified, credentials
must be passed.
:param target: dictionary representing the object of the action
for object creation this should be a dictionary
representing the location of the object e.g.
{'project_id': object.project_id}
:returns: boolean if the user has permission or not for the actions.
"""
if target is None:
target = {}
user = auth_utils.get_user(request)
# Several service policy engines default to a project id check for
# ownership. Since the user is already scoped to a project, if a
# different project id has not been specified use the currently scoped
# project's id.
#
# The reason is the operator can edit the local copies of the service
# policy file. If a rule is removed, then the default rule is used. We
# don't want to block all actions because the operator did not fully
# understand the implication of editing the policy file. Additionally,
# the service APIs will correct us if we are too permissive.
if target.get('project_id') is None:
target['project_id'] = user.project_id
if target.get('tenant_id') is None:
target['tenant_id'] = target['project_id']
# same for user_id
if target.get('user_id') is None:
target['user_id'] = user.id
domain_id_keys = [
'domain_id',
'project.domain_id',
'user.domain_id',
'group.domain_id'
]
# populates domain id keys with user's current domain id
for key in domain_id_keys:
if target.get(key) is None:
target[key] = user.user_domain_id
credentials = _user_to_credentials(user)
domain_credentials = _domain_to_credentials(request, user)
# if there is a domain token use the domain_id instead of the user's domain
if domain_credentials:
credentials['domain_id'] = domain_credentials.get('domain_id')
enforcer = _get_enforcer()
for action in actions:
scope, action = action[0], action[1]
if scope in enforcer:
# this is for handling the v3 policy file and will only be
# needed when a domain scoped token is present
if scope == 'identity' and domain_credentials:
# use domain credentials
if not _check_credentials(enforcer[scope],
action,
target,
domain_credentials):
return False
# use project credentials
if not _check_credentials(enforcer[scope],
action, target, credentials):
return False
# if no policy for scope, allow action, underlying API will
# ultimately block the action if not permitted, treat as though
# allowed
return True
def _check_credentials(enforcer_scope, action, target, credentials):
is_valid = True
if not enforcer_scope.enforce(action, target, credentials):
# to match service implementations, if a rule is not found,
# use the default rule for that service policy
#
# waiting to make the check because the first call to
# enforce loads the rules
if action not in enforcer_scope.rules:
if not enforcer_scope.enforce('default', target, credentials):
is_valid = False
else:
is_valid = False
return is_valid
def _user_to_credentials(user):
if not hasattr(user, "_credentials"):
roles = [role['name'] for role in user.roles]
user._credentials = {'user_id': user.id,
'token': user.token,
'username': user.username,
'project_id': user.project_id,
'tenant_id': user.project_id,
'project_name': user.project_name,
'domain_id': user.user_domain_id,
'is_admin': user.is_superuser,
'roles': roles}
return user._credentials
def _domain_to_credentials(request, user):
if not hasattr(user, "_domain_credentials"):
try:
domain_auth_ref = request.session.get('domain_token')
# no domain role or not running on V3
if not domain_auth_ref:
return None
domain_user = auth_user.create_user_from_token(
request, auth_user.Token(domain_auth_ref),
domain_auth_ref.service_catalog.url_for(interface=None))
user._domain_credentials = _user_to_credentials(domain_user)
# uses the domain_id associated with the domain_user
user._domain_credentials['domain_id'] = domain_user.domain_id
except Exception:
LOG.warning("Failed to create user from domain scoped token.")
return None
return user._domain_credentials

View File

@ -1,146 +0,0 @@
{
"admin_required": "role:admin or is_admin:1",
"service_role": "role:service",
"service_or_admin": "rule:admin_required or rule:service_role",
"owner" : "user_id:%(user_id)s",
"admin_or_owner": "rule:admin_required or rule:owner",
"default": "rule:admin_required",
"identity:get_region": "",
"identity:list_regions": "",
"identity:create_region": "rule:admin_required",
"identity:update_region": "rule:admin_required",
"identity:delete_region": "rule:admin_required",
"identity:get_service": "rule:admin_required",
"identity:list_services": "rule:admin_required",
"identity:create_service": "rule:admin_required",
"identity:update_service": "rule:admin_required",
"identity:delete_service": "rule:admin_required",
"identity:get_endpoint": "rule:admin_required",
"identity:list_endpoints": "rule:admin_required",
"identity:create_endpoint": "rule:admin_required",
"identity:update_endpoint": "rule:admin_required",
"identity:delete_endpoint": "rule:admin_required",
"identity:get_catalog": "",
"identity:get_domain": "rule:admin_required",
"identity:list_domains": "rule:admin_required",
"identity:create_domain": "rule:admin_required",
"identity:update_domain": "rule:admin_required",
"identity:delete_domain": "rule:admin_required",
"identity:get_project": "rule:admin_required",
"identity:list_projects": "rule:admin_required",
"identity:list_user_projects": "rule:admin_or_owner",
"identity:create_project": "rule:admin_required",
"identity:update_project": "rule:admin_required",
"identity:delete_project": "rule:admin_required",
"identity:get_user": "rule:admin_required",
"identity:list_users": "rule:admin_required",
"identity:create_user": "rule:admin_required",
"identity:update_user": "rule:admin_required",
"identity:delete_user": "rule:admin_required",
"identity:change_password": "rule:admin_or_owner",
"identity:get_group": "rule:admin_required",
"identity:list_groups": "rule:admin_required",
"identity:list_groups_for_user": "rule:admin_or_owner",
"identity:create_group": "rule:admin_required",
"identity:update_group": "rule:admin_required",
"identity:delete_group": "rule:admin_required",
"identity:list_users_in_group": "rule:admin_required",
"identity:remove_user_from_group": "rule:admin_required",
"identity:check_user_in_group": "rule:admin_required",
"identity:add_user_to_group": "rule:admin_required",
"identity:get_credential": "rule:admin_required",
"identity:list_credentials": "rule:admin_required",
"identity:create_credential": "rule:admin_required",
"identity:update_credential": "rule:admin_required",
"identity:delete_credential": "rule:admin_required",
"identity:ec2_get_credential": "rule:admin_or_owner",
"identity:ec2_list_credentials": "rule:admin_or_owner",
"identity:ec2_create_credential": "rule:admin_or_owner",
"identity:ec2_delete_credential": "rule:admin_required or (rule:owner and user_id:%(target.credential.user_id)s)",
"identity:get_role": "rule:admin_required",
"identity:list_roles": "rule:admin_required",
"identity:create_role": "rule:admin_required",
"identity:update_role": "rule:admin_required",
"identity:delete_role": "rule:admin_required",
"identity:check_grant": "rule:admin_required",
"identity:list_grants": "rule:admin_required",
"identity:create_grant": "rule:admin_required",
"identity:revoke_grant": "rule:admin_required",
"identity:list_role_assignments": "rule:admin_required",
"identity:get_policy": "rule:admin_required",
"identity:list_policies": "rule:admin_required",
"identity:create_policy": "rule:admin_required",
"identity:update_policy": "rule:admin_required",
"identity:delete_policy": "rule:admin_required",
"identity:check_token": "rule:admin_required",
"identity:validate_token": "rule:service_or_admin",
"identity:validate_token_head": "rule:service_or_admin",
"identity:revocation_list": "rule:service_or_admin",
"identity:revoke_token": "rule:admin_or_owner",
"identity:create_trust": "user_id:%(trust.trustor_user_id)s",
"identity:get_trust": "rule:admin_or_owner",
"identity:list_trusts": "",
"identity:list_roles_for_trust": "",
"identity:check_role_for_trust": "",
"identity:get_role_for_trust": "",
"identity:delete_trust": "",
"identity:create_consumer": "rule:admin_required",
"identity:get_consumer": "rule:admin_required",
"identity:list_consumers": "rule:admin_required",
"identity:delete_consumer": "rule:admin_required",
"identity:update_consumer": "rule:admin_required",
"identity:authorize_request_token": "rule:admin_required",
"identity:list_access_token_roles": "rule:admin_required",
"identity:get_access_token_role": "rule:admin_required",
"identity:list_access_tokens": "rule:admin_required",
"identity:get_access_token": "rule:admin_required",
"identity:delete_access_token": "rule:admin_required",
"identity:list_projects_for_endpoint": "rule:admin_required",
"identity:add_endpoint_to_project": "rule:admin_required",
"identity:check_endpoint_in_project": "rule:admin_required",
"identity:list_endpoints_for_project": "rule:admin_required",
"identity:remove_endpoint_from_project": "rule:admin_required",
"identity:create_identity_provider": "rule:admin_required",
"identity:list_identity_providers": "rule:admin_required",
"identity:get_identity_providers": "rule:admin_required",
"identity:update_identity_provider": "rule:admin_required",
"identity:delete_identity_provider": "rule:admin_required",
"identity:create_protocol": "rule:admin_required",
"identity:update_protocol": "rule:admin_required",
"identity:get_protocol": "rule:admin_required",
"identity:list_protocols": "rule:admin_required",
"identity:delete_protocol": "rule:admin_required",
"identity:create_mapping": "rule:admin_required",
"identity:get_mapping": "rule:admin_required",
"identity:list_mappings": "rule:admin_required",
"identity:delete_mapping": "rule:admin_required",
"identity:update_mapping": "rule:admin_required",
"identity:list_projects_for_groups": "",
"identity:list_domains_for_groups": "",
"identity:list_revoke_events": ""
}

View File

@ -1,274 +0,0 @@
{
"context_is_admin": "role:admin",
"admin_or_owner": "is_admin:True or project_id:%(project_id)s",
"default": "rule:admin_or_owner",
"cells_scheduler_filter:TargetCellFilter": "is_admin:True",
"compute:create": "",
"compute:create:attach_network": "",
"compute:create:attach_volume": "",
"compute:create:forced_host": "is_admin:True",
"compute:delete": "rule:default",
"compute:get_all": "",
"compute:get_all_tenants": "",
"compute:reboot": "rule:default",
"compute:rebuild": "rule:default",
"compute:snapshot": "rule:default",
"compute:start": "rule:default",
"compute:stop": "rule:default",
"compute:unlock_override": "rule:admin_api",
"compute:attach_volume" : "rule:default",
"compute:detach_volume" : "rule:default",
"compute:update": "rule:default",
"compute:resize": "rule:default",
"compute:confirm_resize": "rule:default",
"compute:revert_resize": "rule:default",
"compute:shelve": "",
"compute:shelve_offload": "",
"compute:unshelve": "",
"admin_api": "is_admin:True",
"compute_extension:accounts": "rule:admin_api",
"compute_extension:admin_actions": "rule:admin_api",
"compute_extension:admin_actions:pause": "rule:admin_or_owner",
"compute_extension:admin_actions:unpause": "rule:admin_or_owner",
"compute_extension:admin_actions:suspend": "rule:admin_or_owner",
"compute_extension:admin_actions:resume": "rule:admin_or_owner",
"compute_extension:admin_actions:lock": "rule:admin_or_owner",
"compute_extension:admin_actions:unlock": "rule:admin_or_owner",
"compute_extension:admin_actions:resetNetwork": "rule:admin_api",
"compute_extension:admin_actions:injectNetworkInfo": "rule:admin_api",
"compute_extension:admin_actions:createBackup": "rule:admin_or_owner",
"compute_extension:admin_actions:migrateLive": "rule:admin_api",
"compute_extension:admin_actions:resetState": "rule:admin_api",
"compute_extension:admin_actions:migrate": "rule:admin_api",
"compute_extension:v3:os-admin-actions": "rule:admin_api",
"compute_extension:v3:os-admin-actions:pause": "rule:admin_or_owner",
"compute_extension:v3:os-admin-actions:unpause": "rule:admin_or_owner",
"compute_extension:v3:os-admin-actions:suspend": "rule:admin_or_owner",
"compute_extension:v3:os-admin-actions:resume": "rule:admin_or_owner",
"compute_extension:v3:os-admin-actions:lock": "rule:admin_or_owner",
"compute_extension:v3:os-admin-actions:unlock": "rule:admin_or_owner",
"compute_extension:v3:os-admin-actions:reset_network": "rule:admin_api",
"compute_extension:v3:os-admin-actions:inject_network_info": "rule:admin_api",
"compute_extension:v3:os-admin-actions:create_backup": "rule:admin_or_owner",
"compute_extension:v3:os-admin-actions:migrate_live": "rule:admin_api",
"compute_extension:v3:os-admin-actions:reset_state": "rule:admin_api",
"compute_extension:v3:os-admin-actions:migrate": "rule:admin_api",
"compute_extension:v3:os-admin-password": "",
"compute_extension:aggregates": "rule:admin_api",
"compute_extension:v3:os-aggregates": "rule:admin_api",
"compute_extension:agents": "rule:admin_api",
"compute_extension:v3:os-agents": "rule:admin_api",
"compute_extension:attach_interfaces": "",
"compute_extension:v3:os-attach-interfaces": "",
"compute_extension:baremetal_nodes": "rule:admin_api",
"compute_extension:v3:os-baremetal-nodes": "rule:admin_api",
"compute_extension:cells": "rule:admin_api",
"compute_extension:v3:os-cells": "rule:admin_api",
"compute_extension:certificates": "",
"compute_extension:v3:os-certificates": "",
"compute_extension:cloudpipe": "rule:admin_api",
"compute_extension:cloudpipe_update": "rule:admin_api",
"compute_extension:console_output": "",
"compute_extension:v3:consoles:discoverable": "",
"compute_extension:v3:os-console-output": "",
"compute_extension:consoles": "",
"compute_extension:v3:os-remote-consoles": "",
"compute_extension:coverage_ext": "rule:admin_api",
"compute_extension:v3:os-coverage": "rule:admin_api",
"compute_extension:createserverext": "",
"compute_extension:deferred_delete": "",
"compute_extension:v3:os-deferred-delete": "",
"compute_extension:disk_config": "",
"compute_extension:evacuate": "rule:admin_api",
"compute_extension:v3:os-evacuate": "rule:admin_api",
"compute_extension:extended_server_attributes": "rule:admin_api",
"compute_extension:v3:os-extended-server-attributes": "rule:admin_api",
"compute_extension:extended_status": "",
"compute_extension:v3:os-extended-status": "",
"compute_extension:extended_availability_zone": "",
"compute_extension:v3:os-extended-availability-zone": "",
"compute_extension:extended_ips": "",
"compute_extension:extended_ips_mac": "",
"compute_extension:extended_vif_net": "",
"compute_extension:v3:extension_info:discoverable": "",
"compute_extension:extended_volumes": "",
"compute_extension:v3:os-extended-volumes": "",
"compute_extension:v3:os-extended-volumes:attach": "",
"compute_extension:v3:os-extended-volumes:detach": "",
"compute_extension:fixed_ips": "rule:admin_api",
"compute_extension:v3:os-fixed-ips:discoverable": "",
"compute_extension:v3:os-fixed-ips": "rule:admin_api",
"compute_extension:flavor_access": "",
"compute_extension:v3:os-flavor-access": "",
"compute_extension:flavor_disabled": "",
"compute_extension:v3:os-flavor-disabled": "",
"compute_extension:flavor_rxtx": "",
"compute_extension:v3:os-flavor-rxtx": "",
"compute_extension:flavor_swap": "",
"compute_extension:flavorextradata": "",
"compute_extension:flavorextraspecs:index": "",
"compute_extension:flavorextraspecs:show": "",
"compute_extension:flavorextraspecs:create": "rule:admin_api",
"compute_extension:flavorextraspecs:update": "rule:admin_api",
"compute_extension:flavorextraspecs:delete": "rule:admin_api",
"compute_extension:v3:flavor-extra-specs:index": "",
"compute_extension:v3:flavor-extra-specs:show": "",
"compute_extension:v3:flavor-extra-specs:create": "rule:admin_api",
"compute_extension:v3:flavor-extra-specs:update": "rule:admin_api",
"compute_extension:v3:flavor-extra-specs:delete": "rule:admin_api",
"compute_extension:flavormanage": "rule:admin_api",
"compute_extension:floating_ip_dns": "",
"compute_extension:floating_ip_pools": "",
"compute_extension:floating_ips": "",
"compute_extension:floating_ips_bulk": "rule:admin_api",
"compute_extension:fping": "",
"compute_extension:fping:all_tenants": "rule:admin_api",
"compute_extension:hide_server_addresses": "is_admin:False",
"compute_extension:v3:os-hide-server-addresses": "is_admin:False",
"compute_extension:hosts": "rule:admin_api",
"compute_extension:v3:os-hosts": "rule:admin_api",
"compute_extension:hypervisors": "rule:admin_api",
"compute_extension:v3:os-hypervisors": "rule:admin_api",
"compute_extension:image_size": "",
"compute_extension:v3:os-image-metadata": "",
"compute_extension:v3:os-images": "",
"compute_extension:instance_actions": "",
"compute_extension:v3:os-instance-actions": "",
"compute_extension:instance_actions:events": "rule:admin_api",
"compute_extension:v3:os-instance-actions:events": "rule:admin_api",
"compute_extension:instance_usage_audit_log": "rule:admin_api",
"compute_extension:v3:os-instance-usage-audit-log": "rule:admin_api",
"compute_extension:v3:ips:discoverable": "",
"compute_extension:keypairs": "",
"compute_extension:keypairs:index": "",
"compute_extension:keypairs:show": "",
"compute_extension:keypairs:create": "",
"compute_extension:keypairs:delete": "",
"compute_extension:v3:os-keypairs:discoverable": "",
"compute_extension:v3:os-keypairs": "",
"compute_extension:v3:os-keypairs:index": "",
"compute_extension:v3:os-keypairs:show": "",
"compute_extension:v3:os-keypairs:create": "",
"compute_extension:v3:os-keypairs:delete": "",
"compute_extension:multinic": "",
"compute_extension:v3:os-multinic": "",
"compute_extension:networks": "rule:admin_api",
"compute_extension:networks:view": "",
"compute_extension:networks_associate": "rule:admin_api",
"compute_extension:quotas:show": "",
"compute_extension:quotas:update": "rule:admin_api",
"compute_extension:quotas:delete": "rule:admin_api",
"compute_extension:v3:os-quota-sets:show": "",
"compute_extension:v3:os-quota-sets:update": "rule:admin_api",
"compute_extension:v3:os-quota-sets:delete": "rule:admin_api",
"compute_extension:quota_classes": "",
"compute_extension:v3:os-quota-class-sets": "",
"compute_extension:rescue": "",
"compute_extension:v3:os-rescue": "",
"compute_extension:security_group_default_rules": "rule:admin_api",
"compute_extension:security_groups": "",
"compute_extension:v3:os-security-groups": "",
"compute_extension:server_diagnostics": "rule:admin_api",
"compute_extension:v3:os-server-diagnostics": "rule:admin_api",
"compute_extension:server_password": "",
"compute_extension:v3:os-server-password": "",
"compute_extension:server_usage": "",
"compute_extension:v3:os-server-usage": "",
"compute_extension:services": "rule:admin_api",
"compute_extension:v3:os-services": "rule:admin_api",
"compute_extension:v3:servers:discoverable": "",
"compute_extension:shelve": "",
"compute_extension:shelveOffload": "rule:admin_api",
"compute_extension:v3:os-shelve:shelve": "",
"compute_extension:v3:os-shelve:shelve_offload": "rule:admin_api",
"compute_extension:simple_tenant_usage:show": "rule:admin_or_owner",
"compute_extension:v3:os-simple-tenant-usage:show": "rule:admin_or_owner",
"compute_extension:simple_tenant_usage:list": "rule:admin_api",
"compute_extension:v3:os-simple-tenant-usage:list": "rule:admin_api",
"compute_extension:unshelve": "",
"compute_extension:v3:os-shelve:unshelve": "",
"compute_extension:users": "rule:admin_api",
"compute_extension:virtual_interfaces": "",
"compute_extension:virtual_storage_arrays": "",
"compute_extension:volumes": "",
"compute_extension:volume_attachments:index": "",
"compute_extension:volume_attachments:show": "",
"compute_extension:volume_attachments:create": "",
"compute_extension:volume_attachments:update": "",
"compute_extension:volume_attachments:delete": "",
"compute_extension:volumetypes": "",
"compute_extension:availability_zone:list": "",
"compute_extension:v3:os-availability-zone:list": "",
"compute_extension:availability_zone:detail": "rule:admin_api",
"compute_extension:v3:os-availability-zone:detail": "rule:admin_api",
"compute_extension:used_limits_for_admin": "rule:admin_api",
"compute_extension:v3:os-used-limits": "",
"compute_extension:v3:os-used-limits:tenant": "rule:admin_api",
"compute_extension:migrations:index": "rule:admin_api",
"compute_extension:v3:os-migrations:index": "rule:admin_api",
"volume:create": "",
"volume:get_all": "",
"volume:get_volume_metadata": "",
"volume:get_snapshot": "",
"volume:get_all_snapshots": "",
"volume_extension:types_manage": "rule:admin_api",
"volume_extension:types_extra_specs": "rule:admin_api",
"volume_extension:volume_admin_actions:reset_status": "rule:admin_api",
"volume_extension:snapshot_admin_actions:reset_status": "rule:admin_api",
"volume_extension:volume_admin_actions:force_delete": "rule:admin_api",
"network:get_all": "",
"network:get": "",
"network:create": "",
"network:delete": "",
"network:associate": "",
"network:disassociate": "",
"network:get_vifs_by_instance": "",
"network:allocate_for_instance": "",
"network:deallocate_for_instance": "",
"network:validate_networks": "",
"network:get_instance_uuids_by_ip_filter": "",
"network:get_instance_id_by_floating_address": "",
"network:setup_networks_on_host": "",
"network:get_backdoor_port": "",
"network:get_floating_ip": "",
"network:get_floating_ip_pools": "",
"network:get_floating_ip_by_address": "",
"network:get_floating_ips_by_project": "",
"network:get_floating_ips_by_fixed_address": "",
"network:allocate_floating_ip": "",
"network:deallocate_floating_ip": "",
"network:associate_floating_ip": "",
"network:disassociate_floating_ip": "",
"network:release_floating_ip": "",
"network:migrate_instance_start": "",
"network:migrate_instance_finish": "",
"network:get_fixed_ip": "",
"network:get_fixed_ip_by_address": "",
"network:add_fixed_ip_to_instance": "",
"network:remove_fixed_ip_from_instance": "",
"network:add_network_to_project": "",
"network:get_instance_nw_info": "",
"network:get_dns_domains": "",
"network:add_dns_entry": "",
"network:modify_dns_entry": "",
"network:delete_dns_entry": "",
"network:get_dns_entries_by_address": "",
"network:get_dns_entries_by_name": "",
"network:create_private_dns_domain": "",
"network:create_public_dns_domain": "",
"network:delete_dns_domain": ""
}

View File

@ -1,195 +0,0 @@
{
"admin_required": "role:admin",
"cloud_admin": "rule:admin_required and domain_id:admin_domain_id",
"service_role": "role:service",
"service_or_admin": "rule:admin_required or rule:service_role",
"owner" : "user_id:%(user_id)s or user_id:%(target.token.user_id)s",
"admin_or_owner": "(rule:admin_required and domain_id:%(target.token.user.domain.id)s) or rule:owner",
"admin_or_cloud_admin": "rule:admin_required or rule:cloud_admin",
"admin_and_matching_domain_id": "rule:admin_required and domain_id:%(domain_id)s",
"service_admin_or_owner": "rule:service_or_admin or rule:owner",
"default": "rule:admin_required",
"identity:get_region": "",
"identity:list_regions": "",
"identity:create_region": "rule:cloud_admin",
"identity:update_region": "rule:cloud_admin",
"identity:delete_region": "rule:cloud_admin",
"identity:get_service": "rule:admin_or_cloud_admin",
"identity:list_services": "rule:admin_or_cloud_admin",
"identity:create_service": "rule:cloud_admin",
"identity:update_service": "rule:cloud_admin",
"identity:delete_service": "rule:cloud_admin",
"identity:get_endpoint": "rule:admin_or_cloud_admin",
"identity:list_endpoints": "rule:admin_or_cloud_admin",
"identity:create_endpoint": "rule:cloud_admin",
"identity:update_endpoint": "rule:cloud_admin",
"identity:delete_endpoint": "rule:cloud_admin",
"identity:get_domain": "rule:cloud_admin or rule:admin_and_matching_domain_id",
"identity:list_domains": "rule:cloud_admin",
"identity:create_domain": "rule:cloud_admin",
"identity:update_domain": "rule:cloud_admin",
"identity:delete_domain": "rule:cloud_admin",
"admin_and_matching_target_project_domain_id": "rule:admin_required and domain_id:%(target.project.domain_id)s",
"admin_and_matching_project_domain_id": "rule:admin_required and domain_id:%(project.domain_id)s",
"identity:get_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id",
"identity:list_projects": "rule:cloud_admin or rule:admin_and_matching_domain_id",
"identity:list_user_projects": "rule:owner or rule:admin_and_matching_domain_id",
"identity:create_project": "rule:cloud_admin or rule:admin_and_matching_project_domain_id",
"identity:update_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id",
"identity:delete_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id",
"admin_and_matching_target_user_domain_id": "rule:admin_required and domain_id:%(target.user.domain_id)s",
"admin_and_matching_user_domain_id": "rule:admin_required and domain_id:%(user.domain_id)s",
"identity:get_user": "rule:cloud_admin or rule:admin_and_matching_target_user_domain_id",
"identity:list_users": "rule:cloud_admin or rule:admin_and_matching_domain_id",
"identity:create_user": "rule:cloud_admin or rule:admin_and_matching_user_domain_id",
"identity:update_user": "rule:cloud_admin or rule:admin_and_matching_target_user_domain_id",
"identity:delete_user": "rule:cloud_admin or rule:admin_and_matching_target_user_domain_id",
"admin_and_matching_target_group_domain_id": "rule:admin_required and domain_id:%(target.group.domain_id)s",
"admin_and_matching_group_domain_id": "rule:admin_required and domain_id:%(group.domain_id)s",
"identity:get_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
"identity:list_groups": "rule:cloud_admin or rule:admin_and_matching_domain_id",
"identity:list_groups_for_user": "rule:owner or rule:admin_and_matching_domain_id",
"identity:create_group": "rule:cloud_admin or rule:admin_and_matching_group_domain_id",
"identity:update_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
"identity:delete_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
"identity:list_users_in_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
"identity:remove_user_from_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
"identity:check_user_in_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
"identity:add_user_to_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
"identity:get_credential": "rule:admin_required",
"identity:list_credentials": "rule:admin_required or user_id:%(user_id)s",
"identity:create_credential": "rule:admin_required",
"identity:update_credential": "rule:admin_required",
"identity:delete_credential": "rule:admin_required",
"identity:ec2_get_credential": "rule:admin_or_cloud_admin or (rule:owner and user_id:%(target.credential.user_id)s)",
"identity:ec2_list_credentials": "rule:admin_or_cloud_admin or rule:owner",
"identity:ec2_create_credential": "rule:admin_or_cloud_admin or rule:owner",
"identity:ec2_delete_credential": "rule:admin_or_cloud_admin or (rule:owner and user_id:%(target.credential.user_id)s)",
"identity:get_role": "rule:admin_or_cloud_admin",
"identity:list_roles": "rule:admin_or_cloud_admin",
"identity:create_role": "rule:cloud_admin",
"identity:update_role": "rule:cloud_admin",
"identity:delete_role": "rule:cloud_admin",
"domain_admin_for_grants": "rule:admin_required and (domain_id:%(domain_id)s or domain_id:%(target.project.domain_id)s)",
"project_admin_for_grants": "rule:admin_required and project_id:%(project_id)s",
"identity:check_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants",
"identity:list_grants": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants",
"identity:create_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants",
"identity:revoke_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants",
"admin_on_domain_filter" : "rule:admin_required and domain_id:%(scope.domain.id)s",
"admin_on_project_filter" : "rule:admin_required and project_id:%(scope.project.id)s",
"identity:list_role_assignments": "rule:cloud_admin or rule:admin_on_domain_filter or rule:admin_on_project_filter",
"identity:get_policy": "rule:cloud_admin",
"identity:list_policies": "rule:cloud_admin",
"identity:create_policy": "rule:cloud_admin",
"identity:update_policy": "rule:cloud_admin",
"identity:delete_policy": "rule:cloud_admin",
"identity:change_password": "rule:owner",
"identity:check_token": "rule:admin_or_owner",
"identity:validate_token": "rule:service_admin_or_owner",
"identity:validate_token_head": "rule:service_or_admin",
"identity:revocation_list": "rule:service_or_admin",
"identity:revoke_token": "rule:admin_or_owner",
"identity:create_trust": "user_id:%(trust.trustor_user_id)s",
"identity:list_trusts": "",
"identity:list_roles_for_trust": "",
"identity:get_role_for_trust": "",
"identity:delete_trust": "",
"identity:create_consumer": "rule:admin_required",
"identity:get_consumer": "rule:admin_required",
"identity:list_consumers": "rule:admin_required",
"identity:delete_consumer": "rule:admin_required",
"identity:update_consumer": "rule:admin_required",
"identity:authorize_request_token": "rule:admin_required",
"identity:list_access_token_roles": "rule:admin_required",
"identity:get_access_token_role": "rule:admin_required",
"identity:list_access_tokens": "rule:admin_required",
"identity:get_access_token": "rule:admin_required",
"identity:delete_access_token": "rule:admin_required",
"identity:list_projects_for_endpoint": "rule:admin_required",
"identity:add_endpoint_to_project": "rule:admin_required",
"identity:check_endpoint_in_project": "rule:admin_required",
"identity:list_endpoints_for_project": "rule:admin_required",
"identity:remove_endpoint_from_project": "rule:admin_required",
"identity:create_endpoint_group": "rule:admin_required",
"identity:list_endpoint_groups": "rule:admin_required",
"identity:get_endpoint_group": "rule:admin_required",
"identity:update_endpoint_group": "rule:admin_required",
"identity:delete_endpoint_group": "rule:admin_required",
"identity:list_projects_associated_with_endpoint_group": "rule:admin_required",
"identity:list_endpoints_associated_with_endpoint_group": "rule:admin_required",
"identity:get_endpoint_group_in_project": "rule:admin_required",
"identity:list_endpoint_groups_for_project": "rule:admin_required",
"identity:add_endpoint_group_to_project": "rule:admin_required",
"identity:remove_endpoint_group_from_project": "rule:admin_required",
"identity:create_identity_provider": "rule:cloud_admin",
"identity:list_identity_providers": "rule:cloud_admin",
"identity:get_identity_providers": "rule:cloud_admin",
"identity:update_identity_provider": "rule:cloud_admin",
"identity:delete_identity_provider": "rule:cloud_admin",
"identity:create_protocol": "rule:cloud_admin",
"identity:update_protocol": "rule:cloud_admin",
"identity:get_protocol": "rule:cloud_admin",
"identity:list_protocols": "rule:cloud_admin",
"identity:delete_protocol": "rule:cloud_admin",
"identity:create_mapping": "rule:cloud_admin",
"identity:get_mapping": "rule:cloud_admin",
"identity:list_mappings": "rule:cloud_admin",
"identity:delete_mapping": "rule:cloud_admin",
"identity:update_mapping": "rule:cloud_admin",
"identity:create_service_provider": "rule:cloud_admin",
"identity:list_service_providers": "rule:cloud_admin",
"identity:get_service_provider": "rule:cloud_admin",
"identity:update_service_provider": "rule:cloud_admin",
"identity:delete_service_provider": "rule:cloud_admin",
"identity:get_auth_catalog": "",
"identity:get_auth_projects": "",
"identity:get_auth_domains": "",
"identity:list_projects_for_groups": "",
"identity:list_domains_for_groups": "",
"identity:list_revoke_events": "",
"identity:create_policy_association_for_endpoint": "rule:cloud_admin",
"identity:check_policy_association_for_endpoint": "rule:cloud_admin",
"identity:delete_policy_association_for_endpoint": "rule:cloud_admin",
"identity:create_policy_association_for_service": "rule:cloud_admin",
"identity:check_policy_association_for_service": "rule:cloud_admin",
"identity:delete_policy_association_for_service": "rule:cloud_admin",
"identity:create_policy_association_for_region_and_service": "rule:cloud_admin",
"identity:check_policy_association_for_region_and_service": "rule:cloud_admin",
"identity:delete_policy_association_for_region_and_service": "rule:cloud_admin",
"identity:get_policy_for_endpoint": "rule:cloud_admin",
"identity:list_endpoints_for_policy": "rule:cloud_admin",
"identity:create_domain_config": "rule:cloud_admin",
"identity:get_domain_config": "rule:cloud_admin",
"identity:update_domain_config": "rule:cloud_admin",
"identity:delete_domain_config": "rule:cloud_admin"
}

View File

@ -1,143 +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 django.utils import datetime_safe
from keystoneauth1.access import access
from keystoneauth1.access import service_catalog
from keystoneclient.v2_0 import roles
from keystoneclient.v2_0 import tenants
from keystoneclient.v2_0 import users
class TestDataContainer(object):
"""Arbitrary holder for test data in an object-oriented fashion."""
pass
def generate_test_data():
'''Builds a set of test_data data as returned by Keystone V2.'''
test_data = TestDataContainer()
keystone_service = {
'type': 'identity',
'name': 'keystone',
'endpoints_links': [],
'endpoints': [
{
'region': 'RegionOne',
'adminURL': 'http://admin.localhost:35357/v2.0',
'internalURL': 'http://internal.localhost:5000/v2.0',
'publicURL': 'http://public.localhost:5000/v2.0'
}
]
}
# Users
user_dict = {'id': uuid.uuid4().hex,
'name': 'gabriel',
'email': 'gabriel@example.com',
'password': 'swordfish',
'token': '',
'enabled': True}
test_data.user = users.User(None, user_dict, loaded=True)
# Tenants
tenant_dict_1 = {'id': uuid.uuid4().hex,
'name': 'tenant_one',
'description': '',
'enabled': True}
tenant_dict_2 = {'id': uuid.uuid4().hex,
'name': 'tenant_two',
'description': '',
'enabled': False}
test_data.tenant_one = tenants.Tenant(None, tenant_dict_1, loaded=True)
test_data.tenant_two = tenants.Tenant(None, tenant_dict_2, loaded=True)
nova_service = {
'type': 'compute',
'name': 'nova',
'endpoint_links': [],
'endpoints': [
{
'region': 'RegionOne',
'adminURL': ('http://nova-admin.localhost:8774/v2.0/%s'
% (tenant_dict_1['id'])),
'internalURL': ('http://nova-internal.localhost:8774/v2.0/%s'
% (tenant_dict_1['id'])),
'publicURL': ('http://nova-public.localhost:8774/v2.0/%s'
% (tenant_dict_1['id']))
},
{
'region': 'RegionTwo',
'adminURL': ('http://nova2-admin.localhost:8774/v2.0/%s'
% (tenant_dict_1['id'])),
'internalURL': ('http://nova2-internal.localhost:8774/v2.0/%s'
% (tenant_dict_1['id'])),
'publicURL': ('http://nova2-public.localhost:8774/v2.0/%s'
% (tenant_dict_1['id']))
}
]
}
# Roles
role_dict = {'id': uuid.uuid4().hex,
'name': 'Member'}
test_data.role = roles.Role(roles.RoleManager, role_dict)
# Tokens
tomorrow = datetime_safe.datetime.now() + datetime.timedelta(days=1)
expiration = datetime_safe.datetime.isoformat(tomorrow)
scoped_token_dict = {
'access': {
'token': {
'id': uuid.uuid4().hex,
'expires': expiration,
'tenant': tenant_dict_1,
'tenants': [tenant_dict_1, tenant_dict_2]},
'user': {
'id': user_dict['id'],
'name': user_dict['name'],
'roles': [role_dict]},
'serviceCatalog': [keystone_service, nova_service]
}
}
test_data.scoped_access_info = access.create(
resp=None,
body=scoped_token_dict)
unscoped_token_dict = {
'access': {
'token': {
'id': uuid.uuid4().hex,
'expires': expiration},
'user': {
'id': user_dict['id'],
'name': user_dict['name'],
'roles': [role_dict]},
'serviceCatalog': [keystone_service]
}
}
test_data.unscoped_access_info = access.create(
resp=None,
body=unscoped_token_dict)
# Service Catalog
test_data.service_catalog = service_catalog.ServiceCatalogV2(
[keystone_service, nova_service])
return test_data

View File

@ -1,361 +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 django.utils import datetime_safe
from keystoneauth1.access import access
from keystoneauth1.access import service_catalog
from keystoneclient.common import cms
from keystoneclient.v3 import domains
from keystoneclient.v3 import projects
from keystoneclient.v3 import roles
from keystoneclient.v3 import users
import requests
class TestDataContainer(object):
"""Arbitrary holder for test data in an object-oriented fashion."""
pass
class TestResponse(requests.Response):
"""Class used to wrap requests.Response.
It also provides 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)
self.headers = data.get('headers', None)
# Fake the text attribute to streamline Response creation
self._text = data.get('text', None)
else:
self.status_code = data
def __eq__(self, other):
return self.__dict__ == other.__dict__
@property
def text(self):
return self._text
def generate_test_data(pki=False, service_providers=False,
endpoint='localhost'):
'''Builds a set of test_data data as returned by Keystone V2.'''
test_data = TestDataContainer()
keystone_service = {
'type': 'identity',
'id': uuid.uuid4().hex,
'endpoints': [
{
'url': 'http://admin.%s:35357/v3' % endpoint,
'region': 'RegionOne',
'interface': 'admin',
'id': uuid.uuid4().hex,
},
{
'url': 'http://internal.%s:5000/v3' % endpoint,
'region': 'RegionOne',
'interface': 'internal',
'id': uuid.uuid4().hex
},
{
'url': 'http://public.%s:5000/v3' % endpoint,
'region': 'RegionOne',
'interface': 'public',
'id': uuid.uuid4().hex
}
]
}
# Domains
domain_dict = {'id': uuid.uuid4().hex,
'name': 'domain',
'description': '',
'enabled': True}
test_data.domain = domains.Domain(domains.DomainManager(None),
domain_dict, loaded=True)
# Users
user_dict = {'id': uuid.uuid4().hex,
'name': 'gabriel',
'email': 'gabriel@example.com',
'password': 'swordfish',
'domain_id': domain_dict['id'],
'token': '',
'enabled': True}
test_data.user = users.User(users.UserManager(None),
user_dict, loaded=True)
# Projects
project_dict_1 = {'id': uuid.uuid4().hex,
'name': 'tenant_one',
'description': '',
'domain_id': domain_dict['id'],
'enabled': True}
project_dict_2 = {'id': uuid.uuid4().hex,
'name': 'tenant_two',
'description': '',
'domain_id': domain_dict['id'],
'enabled': False}
test_data.project_one = projects.Project(projects.ProjectManager(None),
project_dict_1,
loaded=True)
test_data.project_two = projects.Project(projects.ProjectManager(None),
project_dict_2,
loaded=True)
# Roles
role_dict = {'id': uuid.uuid4().hex,
'name': 'Member'}
test_data.role = roles.Role(roles.RoleManager, role_dict)
nova_service = {
'type': 'compute',
'id': uuid.uuid4().hex,
'endpoints': [
{
'url': ('http://nova-admin.%s:8774/v2.0/%s'
% (endpoint, project_dict_1['id'])),
'region': 'RegionOne',
'interface': 'admin',
'id': uuid.uuid4().hex,
},
{
'url': ('http://nova-internal.%s:8774/v2.0/%s'
% (endpoint, project_dict_1['id'])),
'region': 'RegionOne',
'interface': 'internal',
'id': uuid.uuid4().hex
},
{
'url': ('http://nova-public.%s:8774/v2.0/%s'
% (endpoint, project_dict_1['id'])),
'region': 'RegionOne',
'interface': 'public',
'id': uuid.uuid4().hex
},
{
'url': ('http://nova2-admin.%s:8774/v2.0/%s'
% (endpoint, project_dict_1['id'])),
'region': 'RegionTwo',
'interface': 'admin',
'id': uuid.uuid4().hex,
},
{
'url': ('http://nova2-internal.%s:8774/v2.0/%s'
% (endpoint, project_dict_1['id'])),
'region': 'RegionTwo',
'interface': 'internal',
'id': uuid.uuid4().hex
},
{
'url': ('http://nova2-public.%s:8774/v2.0/%s'
% (endpoint, project_dict_1['id'])),
'region': 'RegionTwo',
'interface': 'public',
'id': uuid.uuid4().hex
}
]
}
# Tokens
tomorrow = datetime_safe.datetime.now() + datetime.timedelta(days=1)
expiration = datetime_safe.datetime.isoformat(tomorrow)
if pki:
# We don't need a real PKI token, but just the prefix to make the
# keystone client treat it as a PKI token
auth_token = cms.PKI_ASN1_PREFIX + uuid.uuid4().hex
else:
auth_token = uuid.uuid4().hex
auth_response_headers = {
'X-Subject-Token': auth_token
}
auth_response = TestResponse({
"headers": auth_response_headers
})
scoped_token_dict = {
'token': {
'methods': ['password'],
'expires_at': expiration,
'project': {
'id': project_dict_1['id'],
'name': project_dict_1['name'],
'domain': {
'id': domain_dict['id'],
'name': domain_dict['name']
}
},
'user': {
'id': user_dict['id'],
'name': user_dict['name'],
'domain': {
'id': domain_dict['id'],
'name': domain_dict['name']
}
},
'roles': [role_dict],
'catalog': [keystone_service, nova_service]
}
}
sp_list = None
if service_providers:
test_data.sp_auth_url = 'http://service_provider_endp:5000/v3'
test_data.service_provider_id = 'k2kserviceprovider'
# The access info for the identity provider
# should return a list of service providers
sp_list = [
{'auth_url': test_data.sp_auth_url,
'id': test_data.service_provider_id,
'sp_url': 'https://k2kserviceprovider/sp_url'}
]
scoped_token_dict['token']['service_providers'] = sp_list
test_data.scoped_access_info = access.create(
resp=auth_response,
body=scoped_token_dict
)
domain_token_dict = {
'token': {
'methods': ['password'],
'expires_at': expiration,
'domain': {
'id': domain_dict['id'],
'name': domain_dict['name'],
},
'user': {
'id': user_dict['id'],
'name': user_dict['name'],
'domain': {
'id': domain_dict['id'],
'name': domain_dict['name']
}
},
'roles': [role_dict],
'catalog': [keystone_service, nova_service]
}
}
test_data.domain_scoped_access_info = access.create(
resp=auth_response,
body=domain_token_dict
)
unscoped_token_dict = {
'token': {
'methods': ['password'],
'expires_at': expiration,
'user': {
'id': user_dict['id'],
'name': user_dict['name'],
'domain': {
'id': domain_dict['id'],
'name': domain_dict['name']
}
},
'catalog': [keystone_service]
}
}
if service_providers:
unscoped_token_dict['token']['service_providers'] = sp_list
test_data.unscoped_access_info = access.create(
resp=auth_response,
body=unscoped_token_dict
)
# Service Catalog
test_data.service_catalog = service_catalog.ServiceCatalogV3(
[keystone_service, nova_service])
# federated user
federated_scoped_token_dict = {
'token': {
'methods': ['password'],
'expires_at': expiration,
'project': {
'id': project_dict_1['id'],
'name': project_dict_1['name'],
'domain': {
'id': domain_dict['id'],
'name': domain_dict['name']
}
},
'user': {
'id': user_dict['id'],
'name': user_dict['name'],
'domain': {
'id': domain_dict['id'],
'name': domain_dict['name']
},
'OS-FEDERATION': {
'identity_provider': 'ACME',
'protocol': 'OIDC',
'groups': [
{'id': uuid.uuid4().hex},
{'id': uuid.uuid4().hex}
]
}
},
'roles': [role_dict],
'catalog': [keystone_service, nova_service]
}
}
test_data.federated_scoped_access_info = access.create(
resp=auth_response,
body=federated_scoped_token_dict
)
federated_unscoped_token_dict = {
'token': {
'methods': ['password'],
'expires_at': expiration,
'user': {
'id': user_dict['id'],
'name': user_dict['name'],
'domain': {
'id': domain_dict['id'],
'name': domain_dict['name']
},
'OS-FEDERATION': {
'identity_provider': 'ACME',
'protocol': 'OIDC',
'groups': [
{'id': uuid.uuid4().hex},
{'id': uuid.uuid4().hex}
]
}
},
'catalog': [keystone_service]
}
}
test_data.federated_unscoped_access_info = access.create(
resp=auth_response,
body=federated_unscoped_token_dict
)
return test_data

View File

@ -1,42 +0,0 @@
#!/usr/bin/env 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 django
from django.test.runner import DiscoverRunner as test_runner
import os
import sys
os.environ['DJANGO_SETTINGS_MODULE'] = 'openstack_auth.tests.settings'
if hasattr(django, 'setup'):
django.setup()
def run(*test_args):
if not test_args:
test_args = ['tests']
parent = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
"..",
"..",
)
sys.path.insert(0, parent)
failures = test_runner().run_tests(test_args)
sys.exit(failures)
if __name__ == '__main__':
run(*sys.argv[1:])

View File

@ -1,76 +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
ALLOWED_HOSTS = ['*']
DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3'}}
INSTALLED_APPS = [
'django',
'django.contrib.contenttypes',
'django.contrib.auth',
'django.contrib.sessions',
'django.contrib.messages',
'openstack_auth',
'openstack_auth.tests'
]
MIDDLEWARE_CLASSES = [
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware'
]
AUTHENTICATION_BACKENDS = ['openstack_auth.backend.KeystoneBackend']
OPENSTACK_KEYSTONE_URL = "http://localhost:5000/v3"
ROOT_URLCONF = 'openstack_auth.tests.urls'
LOGIN_REDIRECT_URL = '/'
SECRET_KEY = 'badcafe'
OPENSTACK_API_VERSIONS = {
"identity": 3
}
USE_TZ = True
OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = False
OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = 'domain'
# NOTE(saschpe): The openstack_auth.user.Token object isn't
# JSON-serializable ATM
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
TEST_DIR = os.path.dirname(os.path.abspath(__file__))
POLICY_FILES_PATH = os.path.join(TEST_DIR, "conf")
POLICY_FILES = {
'identity': 'keystone_policy.json',
'compute': 'nova_policy.json'
}
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'APP_DIRS': True,
},
]
AUTH_USER_MODEL = 'openstack_auth.User'

View File

@ -1,11 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<form action="." method="POST">{{ csrf_token }}
{{ form.as_p }}
</form>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +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 django.conf.urls import include
from django.conf.urls import url
from django.views import generic
from openstack_auth import utils
from openstack_auth import views
utils.patch_middleware_get_user()
urlpatterns = [
url(r"", include('openstack_auth.urls')),
url(r"^websso/$", views.websso, name='websso'),
url(r"^$", generic.TemplateView.as_view(template_name="auth/blank.html"))
]

View File

@ -1,36 +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 django.conf.urls import url
from openstack_auth import utils
from openstack_auth import views
utils.patch_middleware_get_user()
urlpatterns = [
url(r"^login/$", views.login, name='login'),
url(r"^logout/$", views.logout, name='logout'),
url(r'^switch/(?P<tenant_id>[^/]+)/$', views.switch,
name='switch_tenants'),
url(r'^switch_services_region/(?P<region_name>[^/]+)/$',
views.switch_region,
name='switch_services_region'),
url(r'^switch_keystone_provider/(?P<keystone_provider>[^/]+)/$',
views.switch_keystone_provider,
name='switch_keystone_provider')
]
if utils.is_websso_enabled():
urlpatterns.append(url(r"^websso/$", views.websso, name='websso'))

View File

@ -1,454 +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 hashlib
import logging
import django
from django.conf import settings
from django.contrib.auth import models
from django.db import models as db_models
from django.utils import deprecation
from keystoneauth1 import exceptions as keystone_exceptions
from keystoneclient.common import cms as keystone_cms
import six
from openstack_auth import utils
LOG = logging.getLogger(__name__)
_TOKEN_HASH_ENABLED = getattr(settings, 'OPENSTACK_TOKEN_HASH_ENABLED', True)
def set_session_from_user(request, user):
request.session['token'] = user.token
request.session['user_id'] = user.id
request.session['region_endpoint'] = user.endpoint
request.session['services_region'] = user.services_region
# Update the user object cached in the request
request._cached_user = user
request.user = user
def create_user_from_token(request, token, endpoint, services_region=None):
# if the region is provided, use that, otherwise use the preferred region
default_service_regions = getattr(settings, 'DEFAULT_SERVICE_REGIONS', {})
default_service_region = default_service_regions.get(endpoint)
svc_region = services_region or \
utils.default_services_region(token.serviceCatalog, request,
selected_region=default_service_region)
return User(id=token.user['id'],
token=token,
user=token.user['name'],
password_expires_at=token.user['password_expires_at'],
user_domain_id=token.user_domain_id,
# We need to consider already logged-in users with an old
# version of Token without user_domain_name.
user_domain_name=getattr(token, 'user_domain_name', None),
project_id=token.project['id'],
project_name=token.project['name'],
domain_id=token.domain['id'],
domain_name=token.domain['name'],
enabled=True,
service_catalog=token.serviceCatalog,
roles=token.roles,
endpoint=endpoint,
services_region=svc_region,
is_federated=getattr(token, 'is_federated', False),
unscoped_token=getattr(token, 'unscoped_token',
request.session.get('unscoped_token')))
class Token(object):
"""Encapsulates the AccessInfo object from keystoneclient.
Token object provides a consistent interface for accessing the keystone
token information and service catalog.
Added for maintaining backward compatibility with horizon that expects
Token object in the user object.
"""
def __init__(self, auth_ref, unscoped_token=None):
# User-related attributes
user = {'id': auth_ref.user_id, 'name': auth_ref.username}
data = getattr(auth_ref, '_data', {})
expiration_date = data.get('token', {}).get('user', {})\
.get('password_expires_at')
user['password_expires_at'] = expiration_date
self.user = user
self.user_domain_id = auth_ref.user_domain_id
self.user_domain_name = auth_ref.user_domain_name
# Token-related attributes
self.id = auth_ref.auth_token
self.unscoped_token = unscoped_token
if _TOKEN_HASH_ENABLED and self._is_pki_token(self.id):
algorithm = getattr(settings, 'OPENSTACK_TOKEN_HASH_ALGORITHM',
'md5')
hasher = hashlib.new(algorithm)
hasher.update(self.id.encode('utf-8'))
self.id = hasher.hexdigest()
# Only hash unscoped token if needed
if self._is_pki_token(self.unscoped_token):
hasher = hashlib.new(algorithm)
hasher.update(self.unscoped_token.encode('utf-8'))
self.unscoped_token = hasher.hexdigest()
self.expires = auth_ref.expires
# Project-related attributes
project = {}
project['id'] = auth_ref.project_id
project['name'] = auth_ref.project_name
project['is_admin_project'] = getattr(auth_ref, 'is_admin_project',
False)
project['domain_id'] = getattr(auth_ref, 'project_domain_id', None)
self.project = project
self.tenant = self.project
# Domain-related attributes
domain = {}
domain['id'] = auth_ref.domain_id
domain['name'] = auth_ref.domain_name
self.domain = domain
# Federation-related attributes
self.is_federated = auth_ref.is_federated
self.roles = [{'name': role} for role in auth_ref.role_names]
self.serviceCatalog = auth_ref.service_catalog.catalog
def _is_pki_token(self, token):
"""Determines if this is a pki-based token (pki or pkiz)"""
if token is None:
return False
return (keystone_cms.is_ans1_token(token)
or keystone_cms.is_pkiz(token))
class User(models.AbstractBaseUser, models.AnonymousUser):
"""A User class with some extra special sauce for Keystone.
In addition to the standard Django user attributes, this class also has
the following:
.. attribute:: token
The Keystone token object associated with the current user/tenant.
The token object is deprecated, user auth_ref instead.
.. attribute:: tenant_id
The id of the Keystone tenant for the current user/token.
The tenant_id keyword argument is deprecated, use project_id instead.
.. attribute:: tenant_name
The name of the Keystone tenant for the current user/token.
The tenant_name keyword argument is deprecated, use project_name
instead.
.. attribute:: project_id
The id of the Keystone project for the current user/token.
.. attribute:: project_name
The name of the Keystone project for the current user/token.
.. attribute:: service_catalog
The ``ServiceCatalog`` data returned by Keystone.
.. attribute:: roles
A list of dictionaries containing role names and ids as returned
by Keystone.
.. attribute:: services_region
A list of non-identity service endpoint regions extracted from the
service catalog.
.. attribute:: user_domain_id
The domain id of the current user.
.. attribute:: user_domain_name
The domain name of the current user.
.. attribute:: domain_id
The id of the Keystone domain scoped for the current user/token.
.. attribute:: is_federated
Whether user is federated Keystone user. (Boolean)
.. attribute:: unscoped_token
Unscoped Keystone token.
.. attribute:: password_expires_at
Password expiration date. This attribute could be None when using
keystone version < 3.0 or if the feature is not enabled in keystone.
"""
keystone_user_id = db_models.CharField(primary_key=True, max_length=255)
USERNAME_FIELD = 'keystone_user_id'
def __init__(self, id=None, token=None, user=None, tenant_id=None,
service_catalog=None, tenant_name=None, roles=None,
authorized_tenants=None, endpoint=None, enabled=False,
services_region=None, user_domain_id=None,
user_domain_name=None, domain_id=None, domain_name=None,
project_id=None, project_name=None, is_federated=False,
unscoped_token=None, password=None, password_expires_at=None):
self.id = id
self.pk = id
self.token = token
self.keystone_user_id = id
self.username = user
self.user_domain_id = user_domain_id
self.user_domain_name = user_domain_name
self.domain_id = domain_id
self.domain_name = domain_name
self.project_id = project_id or tenant_id
self.project_name = project_name or tenant_name
self.service_catalog = service_catalog
self._services_region = (
services_region
or utils.default_services_region(service_catalog)
)
self.roles = roles or []
self.endpoint = endpoint
self.enabled = enabled
self._authorized_tenants = authorized_tenants
self.is_federated = is_federated
self.password_expires_at = password_expires_at
# Unscoped token is used for listing user's project that works
# for both federated and keystone user.
self.unscoped_token = unscoped_token
# List of variables to be deprecated.
self.tenant_id = self.project_id
self.tenant_name = self.project_name
# Required by AbstractBaseUser
self.password = None
def __unicode__(self):
return self.username
def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, self.username)
def is_token_expired(self, margin=None):
"""Determine if the token is expired.
:returns:
``True`` if the token is expired, ``False`` if not, and
``None`` if there is no token set.
:param margin:
A security time margin in seconds before real expiration.
Will return ``True`` if the token expires in less than ``margin``
seconds of time.
A default margin can be set by the TOKEN_TIMEOUT_MARGIN in the
django settings.
"""
if self.token is None:
return None
return not utils.is_token_valid(self.token, margin)
if django.VERSION >= (1, 10):
@property
def is_authenticated(self):
"""Checks for a valid authentication."""
if (self.token is not None and utils.is_token_valid(self.token)):
return deprecation.CallableTrue
else:
return deprecation.CallableFalse
@property
def is_anonymous(self):
"""Return if the user is not authenticated.
:returns: ``True`` if not authenticated,``False`` otherwise.
"""
return deprecation.CallableBool(not self.is_authenticated)
else:
def is_authenticated(self, margin=None):
"""Checks for a valid authentication.
:param margin:
A security time margin in seconds before end of authentication.
Will return ``False`` if authentication ends in less than
``margin`` seconds of time.
A default margin can be set by the TOKEN_TIMEOUT_MARGIN in the
django settings.
"""
return (self.token is not None and
utils.is_token_valid(self.token, margin))
def is_anonymous(self, margin=None):
"""Return if the user is not authenticated.
:returns: ``True`` if not authenticated,``False`` otherwise.
:param margin:
A security time margin in seconds before end of an eventual
authentication.
Will return ``True`` even if authenticated but that
authentication ends in less than ``margin`` seconds of time.
A default margin can be set by the TOKEN_TIMEOUT_MARGIN in the
django settings.
"""
return not self.is_authenticated(margin)
@property
def is_active(self):
return self.enabled
@property
def is_superuser(self):
"""Evaluates whether this user has admin privileges.
:returns: ``True`` or ``False``.
"""
admin_roles = utils.get_admin_roles()
user_roles = {role['name'].lower() for role in self.roles}
return not admin_roles.isdisjoint(user_roles)
@property
def authorized_tenants(self):
"""Returns a memoized list of tenants this user may access."""
if self.is_authenticated() and self._authorized_tenants is None:
endpoint = self.endpoint
try:
self._authorized_tenants = utils.get_project_list(
user_id=self.id,
auth_url=endpoint,
token=self.unscoped_token,
is_federated=self.is_federated)
except (keystone_exceptions.ClientException,
keystone_exceptions.AuthorizationFailure):
LOG.exception('Unable to retrieve project list.')
return self._authorized_tenants or []
@authorized_tenants.setter
def authorized_tenants(self, tenant_list):
self._authorized_tenants = tenant_list
@property
def services_region(self):
return self._services_region
@services_region.setter
def services_region(self, region):
self._services_region = region
@property
def available_services_regions(self):
"""Returns list of unique region name values in service catalog."""
regions = []
if self.service_catalog:
for service in self.service_catalog:
service_type = service.get('type')
if service_type is None or service_type == 'identity':
continue
for endpoint in service.get('endpoints', []):
region = utils.get_endpoint_region(endpoint)
if region not in regions:
regions.append(region)
return regions
def save(*args, **kwargs):
# Presume we can't write to Keystone.
pass
def delete(*args, **kwargs):
# Presume we can't write to Keystone.
pass
# Check for OR'd permission rules, check that user has one of the
# required permission.
def has_a_matching_perm(self, perm_list, obj=None):
"""Returns True if the user has one of the specified permissions.
If object is passed, it checks if the user has any of the required
perms for this object.
"""
# If there are no permissions to check, just return true
if not perm_list:
return True
# Check that user has at least one of the required permissions.
for perm in perm_list:
if self.has_perm(perm, obj):
return True
return False
# Override the default has_perms method. Allowing for more
# complex combinations of permissions. Will check for logical AND of
# all top level permissions. Will use logical OR for all first level
# tuples (check that use has one permissions in the tuple)
#
# Examples:
# Checks for all required permissions
# ('openstack.roles.admin', 'openstack.roles.L3-support')
#
# Checks for admin AND (L2 or L3)
# ('openstack.roles.admin', ('openstack.roles.L3-support',
# 'openstack.roles.L2-support'),)
def has_perms(self, perm_list, obj=None):
"""Returns True if the user has all of the specified permissions.
Tuples in the list will possess the required permissions if
the user has a permissions matching one of the elements of
that tuple
"""
# If there are no permissions to check, just return true
if not perm_list:
return True
for perm in perm_list:
if isinstance(perm, six.string_types):
# check that the permission matches
if not self.has_perm(perm, obj):
return False
else:
# check that a permission in the tuple matches
if not self.has_a_matching_perm(perm, obj):
return False
return True
def time_until_expiration(self):
"""Returns the number of remaining days until user's password expires.
Calculates the number days until the user must change their password,
once the password expires the user will not able to log in until an
admin changes its password.
"""
if self.password_expires_at is not None:
expiration_date = datetime.datetime.strptime(
self.password_expires_at, "%Y-%m-%dT%H:%M:%S.%f")
return expiration_date - datetime.datetime.now()
class Meta(object):
app_label = 'openstack_auth'

View File

@ -1,562 +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 re
from django.conf import settings
from django.contrib import auth
from django.contrib.auth import models
from django.utils import timezone
from keystoneauth1.identity import v2 as v2_auth
from keystoneauth1.identity import v3 as v3_auth
from keystoneauth1 import session
from keystoneauth1 import token_endpoint
from keystoneclient.v2_0 import client as client_v2
from keystoneclient.v3 import client as client_v3
from six.moves.urllib import parse as urlparse
LOG = logging.getLogger(__name__)
_TOKEN_TIMEOUT_MARGIN = getattr(settings, 'TOKEN_TIMEOUT_MARGIN', 0)
"""
We need the request object to get the user, so we'll slightly modify the
existing django.contrib.auth.get_user method. To do so we update the
auth middleware to point to our overridden method.
Calling the "patch_middleware_get_user" method somewhere like our urls.py
file takes care of hooking it in appropriately.
"""
def middleware_get_user(request):
if not hasattr(request, '_cached_user'):
request._cached_user = get_user(request)
return request._cached_user
def get_user(request):
try:
user_id = request.session[auth.SESSION_KEY]
backend_path = request.session[auth.BACKEND_SESSION_KEY]
backend = auth.load_backend(backend_path)
backend.request = request
user = backend.get_user(user_id) or models.AnonymousUser()
except KeyError:
user = models.AnonymousUser()
return user
def patch_middleware_get_user():
# NOTE(adriant): We can't import middleware until our customer user model
# is actually registered, otherwise a call to get_user_model within the
# middleware module will fail.
from django.contrib.auth import middleware
middleware.get_user = middleware_get_user
auth.get_user = get_user
""" End Monkey-Patching. """
def is_token_valid(token, margin=None):
"""Timezone-aware checking of the auth token's expiration timestamp.
Returns ``True`` if the token has not yet expired, otherwise ``False``.
:param token: The openstack_auth.user.Token instance to check
:param margin:
A time margin in seconds to subtract from the real token's validity.
An example usage is that the token can be valid once the middleware
passed, and invalid (timed-out) during a view rendering and this
generates authorization errors during the view rendering.
A default margin can be set by the TOKEN_TIMEOUT_MARGIN in the
django settings.
"""
expiration = token.expires
# In case we get an unparseable expiration timestamp, return False
# so you can't have a "forever" token just by breaking the expires param.
if expiration is None:
return False
if margin is None:
margin = getattr(settings, 'TOKEN_TIMEOUT_MARGIN', 0)
expiration = expiration - datetime.timedelta(seconds=margin)
if settings.USE_TZ and timezone.is_naive(expiration):
# Presumes that the Keystone is using UTC.
expiration = timezone.make_aware(expiration, timezone.utc)
return expiration > timezone.now()
# From django.contrib.auth.views
# Added in Django 1.4.3, 1.5b2
# Vendored here for compatibility with old Django versions.
def is_safe_url(url, host=None):
"""Return ``True`` if the url is a safe redirection.
The safe redirection means that it doesn't point to a different host.
Always returns ``False`` on an empty url.
"""
if not url:
return False
netloc = urlparse.urlparse(url)[1]
return not netloc or netloc == host
# DEPRECATED -- Mitaka
# This method definition is included to prevent breaking backward compatibility
# The original functionality was problematic and has been removed.
def remove_project_cache(token):
pass
# Helper for figuring out keystone version
# Implementation will change when API version discovery is available
def get_keystone_version():
return getattr(settings, 'OPENSTACK_API_VERSIONS', {}).get('identity', 2.0)
def get_session():
insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
verify = getattr(settings, 'OPENSTACK_SSL_CACERT', True)
if insecure:
verify = False
return session.Session(verify=verify)
def get_keystone_client():
if get_keystone_version() < 3:
return client_v2
else:
return client_v3
def is_token_deletion_disabled():
LOG.warning("Deprecated TOKEN_DELETION_DISABLED setting is no longer used")
return getattr(settings, 'TOKEN_DELETION_DISABLED', False)
def is_websso_enabled():
"""Websso is supported in Keystone version 3."""
websso_enabled = getattr(settings, 'WEBSSO_ENABLED', False)
keystonev3_plus = (get_keystone_version() >= 3)
return websso_enabled and keystonev3_plus
def build_absolute_uri(request, relative_url):
"""Ensure absolute_uri are relative to WEBROOT."""
webroot = getattr(settings, 'WEBROOT', '')
if webroot.endswith("/") and relative_url.startswith("/"):
webroot = webroot[:-1]
return request.build_absolute_uri(webroot + relative_url)
def get_websso_url(request, auth_url, websso_auth):
"""Return the keystone endpoint for initiating WebSSO.
Generate the keystone WebSSO endpoint that will redirect the user
to the login page of the federated identity provider.
Based on the authentication type selected by the user in the login
form, it will construct the keystone WebSSO endpoint.
:param request: Django http request object.
:type request: django.http.HttpRequest
:param auth_url: Keystone endpoint configured in the horizon setting.
The value is derived from:
- OPENSTACK_KEYSTONE_URL
- AVAILABLE_REGIONS
:type auth_url: string
:param websso_auth: Authentication type selected by the user from the
login form. The value is derived from the horizon
setting WEBSSO_CHOICES.
:type websso_auth: string
Example of horizon WebSSO setting::
WEBSSO_CHOICES = (
("credentials", "Keystone Credentials"),
("oidc", "OpenID Connect"),
("saml2", "Security Assertion Markup Language"),
("acme_oidc", "ACME - OpenID Connect"),
("acme_saml2", "ACME - SAML2")
)
WEBSSO_IDP_MAPPING = {
"acme_oidc": ("acme", "oidc"),
"acme_saml2": ("acme", "saml2")
}
}
The value of websso_auth will be looked up in the WEBSSO_IDP_MAPPING
dictionary, if a match is found it will return a IdP specific WebSSO
endpoint using the values found in the mapping.
The value in WEBSSO_IDP_MAPPING is expected to be a tuple formatted as
(<idp_id>, <protocol_id>). Using the values found, a IdP/protocol
specific URL will be constructed:
/auth/OS-FEDERATION/identity_providers/<idp_id>
/protocols/<protocol_id>/websso
If no value is found from the WEBSSO_IDP_MAPPING dictionary, it will
treat the value as the global WebSSO protocol <protocol_id> and
construct the WebSSO URL by:
/auth/OS-FEDERATION/websso/<protocol_id>
:returns: Keystone WebSSO endpoint.
:rtype: string
"""
origin = build_absolute_uri(request, '/auth/websso/')
idp_mapping = getattr(settings, 'WEBSSO_IDP_MAPPING', {})
idp_id, protocol_id = idp_mapping.get(websso_auth,
(None, websso_auth))
if idp_id:
# Use the IDP specific WebSSO endpoint
url = ('%s/auth/OS-FEDERATION/identity_providers/%s'
'/protocols/%s/websso?origin=%s' %
(auth_url, idp_id, protocol_id, origin))
else:
# If no IDP mapping found for the identifier,
# perform WebSSO by protocol.
url = ('%s/auth/OS-FEDERATION/websso/%s?origin=%s' %
(auth_url, protocol_id, origin))
return url
def has_in_url_path(url, subs):
"""Test if any of `subs` strings is present in the `url` path."""
scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
return any([sub in path for sub in subs])
def url_path_replace(url, old, new, count=None):
"""Return a copy of url with replaced path.
Return a copy of url with all occurrences of old replaced by new in the url
path. If the optional argument count is given, only the first count
occurrences are replaced.
"""
args = []
scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
if count is not None:
args.append(count)
return urlparse.urlunsplit((
scheme, netloc, path.replace(old, new, *args), query, fragment))
def url_path_append(url, suffix):
scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
path = (path + suffix).replace('//', '/')
return urlparse.urlunsplit((scheme, netloc, path, query, fragment))
def _augment_url_with_version(auth_url):
"""Optionally augment auth_url path with version suffix.
Check if path component already contains version suffix and if it does
not, append version suffix to the end of path, not erasing the previous
path contents, since keystone web endpoint (like /identity) could be
there. Keystone version needs to be added to endpoint because as of Kilo,
the identity URLs returned by Keystone might no longer contain API
versions, leaving the version choice up to the user.
"""
if has_in_url_path(auth_url, ["/v2.0", "/v3"]):
return auth_url
if get_keystone_version() >= 3:
return url_path_append(auth_url, "/v3")
else:
return url_path_append(auth_url, "/v2.0")
# TODO(tsufiev): remove this legacy version as soon as Horizon switches to
# the new fix_auth_url_version_prefix() call
def fix_auth_url_version(auth_url):
"""Fix up the auth url if an invalid or no version prefix was given.
People still give a v2 auth_url even when they specify that they want v3
authentication. Fix the URL to say v3 in this case and add version if it is
missing entirely. This should be smarter and use discovery.
"""
auth_url = _augment_url_with_version(auth_url)
if get_keystone_version() >= 3 and has_in_url_path(auth_url, ["/v2.0"]):
LOG.warning("The Keystone URL (either in Horizon settings or in "
"service catalog) points to a v2.0 Keystone endpoint, "
"but v3 is specified as the API version to use by "
"Horizon. Using v3 endpoint for authentication.")
auth_url = url_path_replace(auth_url, "/v2.0", "/v3", 1)
return auth_url
def fix_auth_url_version_prefix(auth_url):
"""Fix up the auth url if an invalid or no version prefix was given.
People still give a v2 auth_url even when they specify that they want v3
authentication. Fix the URL to say v3 in this case and add version if it is
missing entirely. This should be smarter and use discovery.
"""
auth_url = _augment_url_with_version(auth_url)
url_fixed = False
if get_keystone_version() >= 3 and has_in_url_path(auth_url, ["/v2.0"]):
url_fixed = True
auth_url = url_path_replace(auth_url, "/v2.0", "/v3", 1)
return auth_url, url_fixed
def clean_up_auth_url(auth_url):
"""Clean up the auth url to extract the exact Keystone URL"""
# NOTE(mnaser): This drops the query and fragment because we're only
# trying to extract the Keystone URL.
scheme, netloc, path, query, fragment = urlparse.urlsplit(auth_url)
return urlparse.urlunsplit((
scheme, netloc, re.sub(r'/auth.*', '', path), '', ''))
def get_token_auth_plugin(auth_url, token, project_id=None, domain_name=None):
if get_keystone_version() >= 3:
if domain_name:
return v3_auth.Token(auth_url=auth_url,
token=token,
domain_name=domain_name,
reauthenticate=False)
else:
return v3_auth.Token(auth_url=auth_url,
token=token,
project_id=project_id,
reauthenticate=False)
else:
return v2_auth.Token(auth_url=auth_url,
token=token,
tenant_id=project_id,
reauthenticate=False)
def get_project_list(*args, **kwargs):
is_federated = kwargs.get('is_federated', False)
sess = kwargs.get('session') or get_session()
auth_url, _ = fix_auth_url_version_prefix(kwargs['auth_url'])
auth = token_endpoint.Token(auth_url, kwargs['token'])
client = get_keystone_client().Client(session=sess, auth=auth)
if get_keystone_version() < 3:
projects = client.tenants.list()
elif is_federated:
projects = client.federation.projects.list()
else:
projects = client.projects.list(user=kwargs.get('user_id'))
projects.sort(key=lambda project: project.name.lower())
return projects
def default_services_region(service_catalog, request=None,
selected_region=None):
"""Returns the first endpoint region for first non-identity service.
Extracted from the service catalog.
"""
if service_catalog:
available_regions = [get_endpoint_region(endpoint) for service
in service_catalog for endpoint
in service.get('endpoints', [])
if (service.get('type') is not None
and service.get('type') != 'identity')]
if not available_regions:
# this is very likely an incomplete keystone setup
LOG.warning('No regions could be found excluding identity.')
available_regions = [get_endpoint_region(endpoint) for service
in service_catalog for endpoint
in service.get('endpoints', [])]
if not available_regions:
# if there are no region setup for any service endpoint,
# this is a critical problem and it's not clear how this occurs
LOG.error('No regions can be found in the service catalog.')
return None
if request and selected_region is None:
selected_region = request.COOKIES.get('services_region',
available_regions[0])
if selected_region not in available_regions:
selected_region = available_regions[0]
return selected_region
return None
def set_response_cookie(response, cookie_name, cookie_value):
"""Common function for setting the cookie in the response.
Provides a common policy of setting cookies for last used project
and region, can be reused in other locations.
This method will set the cookie to expire in 365 days.
"""
now = timezone.now()
expire_date = now + datetime.timedelta(days=365)
response.set_cookie(cookie_name, cookie_value, expires=expire_date)
def get_endpoint_region(endpoint):
"""Common function for getting the region from endpoint.
In Keystone V3, region has been deprecated in favor of
region_id.
This method provides a way to get region that works for both
Keystone V2 and V3.
"""
return endpoint.get('region_id') or endpoint.get('region')
def using_cookie_backed_sessions():
engine = getattr(settings, 'SESSION_ENGINE', '')
return "signed_cookies" in engine
def get_admin_roles():
"""Common function for getting the admin roles from settings
:return:
Set object including all admin roles.
If there is no role, this will return empty::
{
"foo", "bar", "admin"
}
"""
admin_roles = {role.lower() for role
in getattr(settings, 'OPENSTACK_KEYSTONE_ADMIN_ROLES',
['admin'])}
return admin_roles
def get_role_permission(role):
"""Common function for getting the permission froms arg
This format is 'openstack.roles.xxx' and 'xxx' is a real role name.
:returns:
String like "openstack.roles.admin"
If role is None, this will return None.
"""
return "openstack.roles.%s" % role.lower()
def get_admin_permissions():
"""Common function for getting the admin permissions from settings
This format is 'openstack.roles.xxx' and 'xxx' is a real role name.
:returns:
Set object including all admin permission.
If there is no permission, this will return empty::
{
"openstack.roles.foo",
"openstack.roles.bar",
"openstack.roles.admin"
}
"""
return {get_role_permission(role) for role in get_admin_roles()}
def get_client_ip(request):
"""Return client ip address using SECURE_PROXY_ADDR_HEADER variable.
If not present or not defined on settings then REMOTE_ADDR is used.
:param request: Django http request object.
:type request: django.http.HttpRequest
:returns: Possible client ip address
:rtype: string
"""
_SECURE_PROXY_ADDR_HEADER = getattr(
settings, 'SECURE_PROXY_ADDR_HEADER', False
)
if _SECURE_PROXY_ADDR_HEADER:
return request.META.get(
_SECURE_PROXY_ADDR_HEADER,
request.META.get('REMOTE_ADDR')
)
return request.META.get('REMOTE_ADDR')
def store_initial_k2k_session(auth_url, request, scoped_auth_ref,
unscoped_auth_ref):
"""Stores session variables if there are k2k service providers
This stores variables related to Keystone2Keystone federation. This
function gets skipped if there are no Keystone service providers.
An unscoped token to the identity provider keystone gets stored
so that it can be used to do federated login into the service
providers when switching keystone providers.
The settings file can be configured to set the display name
of the local (identity provider) keystone by setting
KEYSTONE_PROVIDER_IDP_NAME. The KEYSTONE_PROVIDER_IDP_ID settings
variable is used for comparison against the service providers.
It should not conflict with any of the service provider ids.
:param auth_url: base token auth url
:param request: Django http request object
:param scoped_auth_ref: Scoped Keystone access info object
:param unscoped_auth_ref: Unscoped Keystone access info object
"""
keystone_provider_id = request.session.get('keystone_provider_id', None)
if keystone_provider_id:
return None
providers = getattr(scoped_auth_ref, 'service_providers', None)
if providers:
providers = getattr(providers, '_service_providers', None)
if providers:
keystone_idp_name = getattr(settings, 'KEYSTONE_PROVIDER_IDP_NAME',
'Local Keystone')
keystone_idp_id = getattr(
settings, 'KEYSTONE_PROVIDER_IDP_ID', 'localkeystone')
keystone_identity_provider = {'name': keystone_idp_name,
'id': keystone_idp_id}
# (edtubill) We will use the IDs as the display names
# We may want to be able to set display names in the future.
keystone_providers = [
{'name': provider_id, 'id': provider_id}
for provider_id in providers]
keystone_providers.append(keystone_identity_provider)
# We treat the Keystone idp ID as None
request.session['keystone_provider_id'] = keystone_idp_id
request.session['keystone_providers'] = keystone_providers
request.session['k2k_base_unscoped_token'] =\
unscoped_auth_ref.auth_token
request.session['k2k_auth_url'] = auth_url

View File

@ -1,327 +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 django.conf import settings
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.contrib.auth import views as django_auth_views
from django.contrib import messages
from django import http as django_http
from django import shortcuts
from django.utils import functional
from django.utils import http
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.debug import sensitive_post_parameters
from keystoneauth1 import exceptions as keystone_exceptions
import six
from openstack_auth import exceptions
from openstack_auth import forms
from openstack_auth import plugin
# This is historic and is added back in to not break older versions of
# Horizon, fix to Horizon to remove this requirement was committed in
# Juno
from openstack_auth.forms import Login # noqa:F401
from openstack_auth import user as auth_user
from openstack_auth import utils
try:
is_safe_url = http.is_safe_url
except AttributeError:
is_safe_url = utils.is_safe_url
LOG = logging.getLogger(__name__)
@sensitive_post_parameters()
@csrf_protect
@never_cache
def login(request, template_name=None, extra_context=None, **kwargs):
"""Logs a user in using the :class:`~openstack_auth.forms.Login` form."""
# If the user enabled websso and selects default protocol
# from the dropdown, We need to redirect user to the websso url
if request.method == 'POST':
auth_type = request.POST.get('auth_type', 'credentials')
if utils.is_websso_enabled() and auth_type != 'credentials':
auth_url = request.POST.get('region')
url = utils.get_websso_url(request, auth_url, auth_type)
return shortcuts.redirect(url)
if not request.is_ajax():
# If the user is already authenticated, redirect them to the
# dashboard straight away, unless the 'next' parameter is set as it
# usually indicates requesting access to a page that requires different
# permissions.
if (request.user.is_authenticated() and
auth.REDIRECT_FIELD_NAME not in request.GET and
auth.REDIRECT_FIELD_NAME not in request.POST):
return shortcuts.redirect(settings.LOGIN_REDIRECT_URL)
# Get our initial region for the form.
initial = {}
current_region = request.session.get('region_endpoint', None)
requested_region = request.GET.get('region', None)
regions = dict(getattr(settings, "AVAILABLE_REGIONS", []))
if requested_region in regions and requested_region != current_region:
initial.update({'region': requested_region})
if request.method == "POST":
form = functional.curry(forms.Login)
else:
form = functional.curry(forms.Login, initial=initial)
if extra_context is None:
extra_context = {'redirect_field_name': auth.REDIRECT_FIELD_NAME}
if not template_name:
if request.is_ajax():
template_name = 'auth/_login.html'
extra_context['hide'] = True
else:
template_name = 'auth/login.html'
res = django_auth_views.login(request,
template_name=template_name,
authentication_form=form,
extra_context=extra_context,
**kwargs)
# Save the region in the cookie, this is used as the default
# selected region next time the Login form loads.
if request.method == "POST":
utils.set_response_cookie(res, 'login_region',
request.POST.get('region', ''))
utils.set_response_cookie(res, 'login_domain',
request.POST.get('domain', ''))
# Set the session data here because django's session key rotation
# will erase it if we set it earlier.
if request.user.is_authenticated():
auth_user.set_session_from_user(request, request.user)
regions = dict(forms.Login.get_region_choices())
region = request.user.endpoint
login_region = request.POST.get('region')
region_name = regions.get(login_region)
request.session['region_endpoint'] = region
request.session['region_name'] = region_name
expiration_time = request.user.time_until_expiration()
threshold_days = getattr(
settings, 'PASSWORD_EXPIRES_WARNING_THRESHOLD_DAYS', -1)
if expiration_time is not None and \
expiration_time.days <= threshold_days:
expiration_time = str(expiration_time).rsplit(':', 1)[0]
msg = (_('Please consider changing your password, it will expire'
' in %s minutes') %
expiration_time).replace(':', ' Hours and ')
messages.warning(request, msg)
return res
@sensitive_post_parameters()
@csrf_exempt
@never_cache
def websso(request):
"""Logs a user in using a token from Keystone's POST."""
referer = request.META.get('HTTP_REFERER', settings.OPENSTACK_KEYSTONE_URL)
auth_url = utils.clean_up_auth_url(referer)
token = request.POST.get('token')
try:
request.user = auth.authenticate(request=request, auth_url=auth_url,
token=token)
except exceptions.KeystoneAuthException as exc:
msg = 'Login failed: %s' % six.text_type(exc)
res = django_http.HttpResponseRedirect(settings.LOGIN_URL)
res.set_cookie('logout_reason', msg, max_age=10)
return res
auth_user.set_session_from_user(request, request.user)
auth.login(request, request.user)
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
return django_http.HttpResponseRedirect(settings.LOGIN_REDIRECT_URL)
def logout(request, login_url=None, **kwargs):
"""Logs out the user if he is logged in. Then redirects to the log-in page.
:param login_url:
Once logged out, defines the URL where to redirect after login
:param kwargs:
see django.contrib.auth.views.logout_then_login extra parameters.
"""
msg = 'Logging out user "%(username)s".' % \
{'username': request.user.username}
LOG.info(msg)
""" Securely logs a user out. """
return django_auth_views.logout_then_login(request, login_url=login_url,
**kwargs)
def delete_token(endpoint, token_id):
"""Delete a token."""
LOG.warning("The delete_token method is deprecated and now does nothing")
@login_required
def switch(request, tenant_id, redirect_field_name=auth.REDIRECT_FIELD_NAME):
"""Switches an authenticated user from one project to another."""
LOG.debug('Switching to tenant %s for user "%s".'
% (tenant_id, request.user.username))
endpoint, __ = utils.fix_auth_url_version_prefix(request.user.endpoint)
session = utils.get_session()
# Keystone can be configured to prevent exchanging a scoped token for
# another token. Always use the unscoped token for requesting a
# scoped token.
unscoped_token = request.user.unscoped_token
auth = utils.get_token_auth_plugin(auth_url=endpoint,
token=unscoped_token,
project_id=tenant_id)
try:
auth_ref = auth.get_access(session)
msg = 'Project switch successful for user "%(username)s".' % \
{'username': request.user.username}
LOG.info(msg)
except keystone_exceptions.ClientException:
msg = (
_('Project switch failed for user "%(username)s".') %
{'username': request.user.username})
messages.error(request, msg)
auth_ref = None
LOG.exception('An error occurred while switching sessions.')
# Ensure the user-originating redirection url is safe.
# Taken from django.contrib.auth.views.login()
redirect_to = request.GET.get(redirect_field_name, '')
if not is_safe_url(url=redirect_to, host=request.get_host()):
redirect_to = settings.LOGIN_REDIRECT_URL
if auth_ref:
user = auth_user.create_user_from_token(
request,
auth_user.Token(auth_ref, unscoped_token=unscoped_token),
endpoint)
auth_user.set_session_from_user(request, user)
message = (
_('Switch to project "%(project_name)s" successful.') %
{'project_name': request.user.project_name})
messages.success(request, message)
response = shortcuts.redirect(redirect_to)
utils.set_response_cookie(response, 'recent_project',
request.user.project_id)
return response
@login_required
def switch_region(request, region_name,
redirect_field_name=auth.REDIRECT_FIELD_NAME):
"""Switches the user's region for all services except Identity service.
The region will be switched if the given region is one of the regions
available for the scoped project. Otherwise the region is not switched.
"""
if region_name in request.user.available_services_regions:
request.session['services_region'] = region_name
LOG.debug('Switching services region to %s for user "%s".'
% (region_name, request.user.username))
redirect_to = request.GET.get(redirect_field_name, '')
if not is_safe_url(url=redirect_to, host=request.get_host()):
redirect_to = settings.LOGIN_REDIRECT_URL
response = shortcuts.redirect(redirect_to)
utils.set_response_cookie(response, 'services_region',
request.session['services_region'])
return response
@login_required
def switch_keystone_provider(request, keystone_provider=None,
redirect_field_name=auth.REDIRECT_FIELD_NAME):
"""Switches the user's keystone provider using K2K Federation
If keystone_provider is given then we switch the user to
the keystone provider using K2K federation. Otherwise if keystone_provider
is None then we switch the user back to the Identity Provider Keystone
which a non federated token auth will be used.
"""
base_token = request.session.get('k2k_base_unscoped_token', None)
k2k_auth_url = request.session.get('k2k_auth_url', None)
keystone_providers = request.session.get('keystone_providers', None)
if not base_token or not k2k_auth_url:
msg = _('K2K Federation not setup for this session')
raise exceptions.KeystoneAuthException(msg)
redirect_to = request.GET.get(redirect_field_name, '')
if not is_safe_url(url=redirect_to, host=request.get_host()):
redirect_to = settings.LOGIN_REDIRECT_URL
unscoped_auth_ref = None
keystone_idp_id = getattr(
settings, 'KEYSTONE_PROVIDER_IDP_ID', 'localkeystone')
if keystone_provider == keystone_idp_id:
current_plugin = plugin.TokenPlugin()
unscoped_auth = current_plugin.get_plugin(auth_url=k2k_auth_url,
token=base_token)
else:
# Switch to service provider using K2K federation
plugins = [plugin.TokenPlugin()]
current_plugin = plugin.K2KAuthPlugin()
unscoped_auth = current_plugin.get_plugin(
auth_url=k2k_auth_url, service_provider=keystone_provider,
plugins=plugins, token=base_token)
try:
# Switch to identity provider using token auth
unscoped_auth_ref = current_plugin.get_access_info(unscoped_auth)
except exceptions.KeystoneAuthException as exc:
msg = 'Switching to Keystone Provider %s has failed. %s' \
% (keystone_provider, (six.text_type(exc)))
messages.error(request, msg)
if unscoped_auth_ref:
try:
request.user = auth.authenticate(
request=request, auth_url=unscoped_auth.auth_url,
token=unscoped_auth_ref.auth_token)
except exceptions.KeystoneAuthException as exc:
msg = 'Keystone provider switch failed: %s' % six.text_type(exc)
res = django_http.HttpResponseRedirect(settings.LOGIN_URL)
res.set_cookie('logout_reason', msg, max_age=10)
return res
auth.login(request, request.user)
auth_user.set_session_from_user(request, request.user)
request.session['keystone_provider_id'] = keystone_provider
request.session['keystone_providers'] = keystone_providers
request.session['k2k_base_unscoped_token'] = base_token
request.session['k2k_auth_url'] = k2k_auth_url
message = (
_('Switch to Keystone Provider "%(keystone_provider)s"'
'successful.') % {'keystone_provider': keystone_provider})
messages.success(request, message)
response = shortcuts.redirect(redirect_to)
return response

View File

@ -1,10 +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.
pbr!=2.1.0,>=2.0.0 # Apache-2.0
Django<2.0,>=1.8 # BSD
oslo.config>=4.6.0 # Apache-2.0
oslo.policy>=1.23.0 # Apache-2.0
python-keystoneclient>=3.8.0 # Apache-2.0
keystoneauth1>=3.2.0 # Apache-2.0
six>=1.9.0 # MIT

View File

@ -1,53 +0,0 @@
[metadata]
name = django_openstack_auth
summary = Django authentication backend for use with OpenStack Identity
description-file =
README.rst
author = OpenStack
author-email = openstack-dev@lists.openstack.org
home-page = http://www.openstack.org/
classifier =
Development Status :: 5 - Production/Stable
Environment :: OpenStack
Framework :: Django
Intended Audience :: Developers
Intended Audience :: Information Technology
Intended Audience :: System Administrators
License :: OSI Approved :: Apache Software License
Operating System :: OS Independent
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
Programming Language :: Python :: 3.5
Topic :: Internet :: WWW/HTTP
[files]
packages =
openstack_auth
[build_sphinx]
all-files = 1
warning-is-error = 1
build-dir = doc/build
source-dir = doc/source
[nosetests]
verbosity=2
detailed-errors=1
[extract_messages]
keywords = _ gettext ngettext l_ lazy_gettext
mapping_file = babel.cfg
output_file = openstack_auth/locale/django.pot
[compile_catalog]
directory = openstack_auth/locale
domain = django
[update_catalog]
domain = django
output_dir = openstack_auth/locale
input_file = openstack_auth/locale/django.pot

View File

@ -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>=2.0.0'],
pbr=True)

View File

@ -1,11 +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.13.0,<0.14,>=0.12.0 # Apache-2.0
Babel!=2.4.0,>=2.3.4 # BSD
coverage!=4.4,>=4.0 # Apache-2.0
mock>=2.0.0 # BSD
mox3>=0.20.0 # Apache-2.0
sphinx>=1.6.2 # BSD
openstackdocstheme>=1.17.0 # Apache-2.0
testscenarios>=0.4 # Apache-2.0/BSD

View File

@ -1,30 +0,0 @@
#!/usr/bin/env bash
# Client constraint file contains this client version pin that is in conflict
# with installing the client from source. We should remove the version pin in
# the constraints file before applying it for from-source installation.
CONSTRAINTS_FILE="$1"
shift 1
set -e
# NOTE(tonyb): Place this in the tox enviroment's log dir so it will get
# published to logs.openstack.org for easy debugging.
localfile="$VIRTUAL_ENV/log/upper-constraints.txt"
if [[ "$CONSTRAINTS_FILE" != http* ]]; then
CONSTRAINTS_FILE="file://$CONSTRAINTS_FILE"
fi
# NOTE(tonyb): need to add curl to bindep.txt if the project supports bindep
curl "$CONSTRAINTS_FILE" --insecure --progress-bar --output "$localfile"
pip install -c"$localfile" openstack-requirements
# This is the main purpose of the script: Allow local installation of
# the current repo. It is listed in constraints file and thus any
# install will be constrained and we need to unconstrain it.
edit-constraints "$localfile" -- "$CLIENT_NAME"
pip install -c"$localfile" -U "$@"
exit $?

64
tox.ini
View File

@ -1,64 +0,0 @@
[tox]
minversion = 2.0
skipsdist = True
envlist = py27,py27dj18,pep8,py35
[testenv]
usedevelop = True
install_command = {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
setenv = {[env-common]setenv}
NOSE_WITH_OPENSTACK=1
NOSE_OPENSTACK_COLOR=1
NOSE_OPENSTACK_RED=0.05
NOSE_OPENSTACK_YELLOW=0.025
NOSE_OPENSTACK_SHOW_ELAPSED=1
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands = python openstack_auth/tests/run_tests.py {posargs}
[env-common]
setenv = VIRTUAL_ENV={envdir}
BRANCH_NAME=master
CLIENT_NAME=django_openstack_auth
[testenv:cover]
setenv = {[env-common]setenv}
DJANGO_SETTINGS_MODULE=openstack_auth.tests.settings
commands =
python -m coverage erase
python -m coverage run openstack_auth/tests/run_tests.py {posargs}
python -m coverage html --include='openstack_auth/*' --omit='openstack_auth/tests/*' -d 'reports'
python -m coverage xml --include='openstack_auth/*' --omit='openstack_auth/tests/*'
# Django 1.8 is LTS
[testenv:py27dj18]
commands = pip install django>=1.8,<1.9
python openstack_auth/tests/run_tests.py {posargs}
[testenv:py27dj19]
commands = pip install django>=1.9,<1.10
python openstack_auth/tests/run_tests.py {posargs}
[testenv:py27dj110]
commands = pip install django>=1.10,<1.11
python openstack_auth/tests/run_tests.py {posargs}
[testenv:py27dj111]
commands = pip install django>=1.11,<2.0
python openstack_auth/tests/run_tests.py {posargs}
[testenv:pep8]
setenv = {[env-common]setenv}
DJANGO_SETTINGS_MODULE=openstack_auth.tests.settings
commands = flake8
[testenv:venv]
commands = {posargs}
[testenv:docs]
setenv = {[env-common]setenv}
commands = python setup.py build_sphinx
[flake8]
builtins = _
exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,panel_template,dash_template,local_settings.py